← Back to team overview

cloud-init-dev team mailing list archive

Re: [Merge] lp:~smoser/cloud-init/trunk.reporting into lp:cloud-init

 

One of my comments suggests changes to the reporting framework itself, so making those changes in 2.0 and re-backporting probably makes most sense.

Diff comments:

> === modified file 'bin/cloud-init'
> --- bin/cloud-init	2015-07-31 15:20:36 +0000
> +++ bin/cloud-init	2015-08-07 05:57:11 +0000
> @@ -617,8 +633,28 @@
>      if name in ("modules", "init"):
>          functor = status_wrapper
>  
> -    return util.log_time(logfunc=LOG.debug, msg="cloud-init mode '%s'" % name,
> -                         get_uptime=True, func=functor, args=(name, args))
> +    report_on = True

This section seems like it could be split out to a 'get an appropriate ReportEventStack' function.

> +    if name == "init":
> +        if args.local:
> +            rname, rdesc = ("init-local", "searching for local datasources")
> +        else:
> +            rname, rdesc = ("init-network",
> +                            "searching for network datasources")
> +    elif name == "modules":
> +        rname, rdesc = ("modules-%s" % args.mode,
> +                        "running modules for %s" % args.mode)
> +    elif name == "single":
> +        rname, rdesc = ("single/%s" % args.name,
> +                        "running single module %s" % args.name)
> +        report_on = args.report
> +
> +    reporting.update_configuration({'print': {'type': 'print'}})
> +    args.reporter = reporting.ReportEventStack(
> +        rname, rdesc, reporting_enabled=report_on)
> +    with args.reporter:
> +        return util.log_time(
> +            logfunc=LOG.debug, msg="cloud-init mode '%s'" % name,
> +            get_uptime=True, func=functor, args=(name, args))
>  
>  
>  if __name__ == '__main__':
> 
> === added file 'cloudinit/reporting/handlers.py'
> --- cloudinit/reporting/handlers.py	1970-01-01 00:00:00 +0000
> +++ cloudinit/reporting/handlers.py	2015-08-07 05:57:11 +0000
> @@ -0,0 +1,73 @@
> +# vi: ts=4 expandtab
> +
> +import abc
> +import logging
> +import oauthlib.oauth1 as oauth1
> +
> +import six
> +
> +from ..registry import DictRegistry
> +from .. import (url_helper, util)
> +
> +
> +@six.add_metaclass(abc.ABCMeta)
> +class ReportingHandler(object):
> +    """Base class for report handlers.
> +
> +    Implement :meth:`~publish_event` for controlling what
> +    the handler does with an event.
> +    """
> +
> +    @abc.abstractmethod
> +    def publish_event(self, event):
> +        """Publish an event to the ``INFO`` log level."""
> +
> +
> +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())
> +
> +
> +class PrintHandler(ReportingHandler):
> +    def publish_event(self, event):
> +        """Publish an event to the ``INFO`` log level."""
> +        print(event.as_string())
> +
> +
> +class WebHookHandler(ReportingHandler):
> +    def __init__(self, endpoint, consumer_key=None, token_key=None,
> +                 token_secret=None, consumer_secret=None, timeout=None,
> +                 retries=None):
> +        super(WebHookHandler, self).__init__()
> +
> +        if any([consumer_key, token_key, token_secret, consumer_secret]):
> +            self.oauth_helper = url_helper.OauthUrlHelper(
> +                consumer_key=consumer_key, token_key=token_key,
> +                token_secret=token_secret, consumer_secret=consumer_secret)
> +        else:
> +            self.oauth_helper = None
> +        self.endpoint = endpoint
> +        self.timeout = timeout
> +        self.retries = retries
> +        self.ssl_details = util.fetch_ssl_details()
> +
> +    def publish_event(self, event):
> +        if self.oauth_helper:
> +            readurl = self.oauth_helper.readurl
> +        else:
> +            readurl = url_helper.readurl
> +        return readurl(

The reporting code assumes that handlers will never raise an exception, so if this might raise an exception then you should probably handle it here (and log something explaining what's gone wrong).

Thinking about it, the reporting code probably _should_ ensure that exceptions won't leak out of it (though individual handlers should still be expected to handle their exceptions, as they will be able to explain what went wrong more accurately); we should address that in 2.0 and backport.

> +            self.endpoint, data=event.as_dict(),
> +            timeout=self.timeout,
> +            retries=self.retries, ssl_details=self.ssl_details)
> +
> +
> +available_handlers = DictRegistry()
> +available_handlers.register_item('log', LogHandler)
> +available_handlers.register_item('print', PrintHandler)
> +available_handlers.register_item('webhook', WebHookHandler)


-- 
https://code.launchpad.net/~smoser/cloud-init/trunk.reporting/+merge/266578
Your team cloud init development team is requested to review the proposed merge of lp:~smoser/cloud-init/trunk.reporting into lp:cloud-init.


References