Refactor handlers out of main reporting module.

This will give us a clearer separation between the core reporting code
(which shouldn't change very often) and the handler code (which is
likely to change more often as we add new handlers and new features to
existing handlers).

It is also the first (baby) step on the path of making handlers
pluggable so third-parties can easily drop their own in.

Change-Id: I648df057d2ff719a2a81398afc80aaef9225ff5c
This commit is contained in:
Daniel Watkins 2015-07-31 17:04:32 +01:00
parent c8fd01e292
commit 523967580a
3 changed files with 35 additions and 31 deletions

View File

@ -9,10 +9,8 @@ The reporting framework is intended to allow all parts of cloud-init to
report events in a structured manner.
"""
import abc
import logging
from cloudinit.registry import DictRegistry
from cloudinit.reporting.handlers import available_handlers
FINISH_EVENT_TYPE = 'finish'
@ -22,9 +20,7 @@ DEFAULT_CONFIG = {
'logging': {'type': 'log'},
}
instantiated_handler_registry = DictRegistry()
available_handlers = DictRegistry()
class ReportingEvent(object):
@ -56,23 +52,6 @@ class FinishReportingEvent(ReportingEvent):
self.event_type, self.name, success_string, self.description)
class ReportingHandler(object):
@abc.abstractmethod
def publish_event(self, event):
raise NotImplementedError
class LogHandler(ReportingHandler):
"""Publishes events to the cloud-init log at the ``INFO`` log level."""
def publish_event(self, event):
"""Publish an event to the ``INFO`` log level."""
logger = logging.getLogger(
'.'.join([__name__, event.event_type, event.name]))
logger.info(event.as_string())
def add_configuration(config):
for handler_name, handler_config in config.items():
handler_config = handler_config.copy()
@ -118,5 +97,4 @@ def report_start_event(event_name, event_description):
return report_event(event)
available_handlers.register_item('log', LogHandler)
add_configuration(DEFAULT_CONFIG)

View File

@ -0,0 +1,25 @@
import abc
import logging
from cloudinit.registry import DictRegistry
class ReportingHandler(object):
@abc.abstractmethod
def publish_event(self, event):
raise NotImplementedError
class LogHandler(ReportingHandler):
"""Publishes events to the cloud-init log at the ``INFO`` log level."""
def publish_event(self, event):
"""Publish an event to the ``INFO`` log level."""
logger = logging.getLogger(
'.'.join(['cloudinit', 'reporting', event.event_type, event.name]))
logger.info(event.as_string())
available_handlers = DictRegistry()
available_handlers.register_item('log', LogHandler)

View File

@ -4,6 +4,7 @@
# vi: ts=4 expandtab
from cloudinit import reporting
from cloudinit.reporting import handlers
from cloudinit.tests import TestCase
from cloudinit.tests.util import mock
@ -95,31 +96,31 @@ class TestReportingHandler(TestCase):
def test_no_default_publish_event_implementation(self):
self.assertRaises(NotImplementedError,
reporting.ReportingHandler().publish_event, None)
handlers.ReportingHandler().publish_event, None)
class TestLogHandler(TestCase):
@mock.patch.object(reporting.logging, 'getLogger')
@mock.patch.object(handlers.logging, 'getLogger')
def test_appropriate_logger_used(self, getLogger):
event_type, event_name = 'test_type', 'test_name'
event = reporting.ReportingEvent(event_type, event_name, 'description')
reporting.LogHandler().publish_event(event)
handlers.LogHandler().publish_event(event)
self.assertEqual(
[mock.call(
'cloudinit.reporting.{0}.{1}'.format(event_type, event_name))],
getLogger.call_args_list)
@mock.patch.object(reporting.logging, 'getLogger')
@mock.patch.object(handlers.logging, 'getLogger')
def test_single_log_message_at_info_published(self, getLogger):
event = reporting.ReportingEvent('type', 'name', 'description')
reporting.LogHandler().publish_event(event)
handlers.LogHandler().publish_event(event)
self.assertEqual(1, getLogger.return_value.info.call_count)
@mock.patch.object(reporting.logging, 'getLogger')
@mock.patch.object(handlers.logging, 'getLogger')
def test_log_message_uses_event_as_string(self, getLogger):
event = reporting.ReportingEvent('type', 'name', 'description')
reporting.LogHandler().publish_event(event)
handlers.LogHandler().publish_event(event)
self.assertIn(event.as_string(),
getLogger.return_value.info.call_args[0][0])
@ -130,7 +131,7 @@ class TestDefaultRegisteredHandler(TestCase):
registered_items = (
reporting.instantiated_handler_registry.registered_items)
for _, item in registered_items.items():
if isinstance(item, reporting.LogHandler):
if isinstance(item, handlers.LogHandler):
break
else:
self.fail('No reporting LogHandler registered by default.')