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:
parent
c8fd01e292
commit
523967580a
@ -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)
|
25
cloudinit/reporting/handlers.py
Normal file
25
cloudinit/reporting/handlers.py
Normal 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)
|
@ -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.')
|
||||
|
Loading…
x
Reference in New Issue
Block a user