~ubuntu-branches/ubuntu/vivid/ceilometer/vivid

« back to all changes in this revision

Viewing changes to ceilometer/openstack/common/log.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2014-03-06 14:44:28 UTC
  • mto: (28.1.1 utopic-proposed) (1.2.1)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: package-import@ubuntu.com-20140306144428-rvphsh4igwyulzf0
Tags: upstream-2014.1~b3
ImportĀ upstreamĀ versionĀ 2014.1~b3

Show diffs side-by-side

added added

removed removed

Lines of Context:
115
115
                    '--log-file paths'),
116
116
    cfg.BoolOpt('use-syslog',
117
117
                default=False,
118
 
                help='Use syslog for logging.'),
 
118
                help='Use syslog for logging. '
 
119
                     'Existing syslog format is DEPRECATED during I, '
 
120
                     'and then will be changed in J to honor RFC5424'),
 
121
    cfg.BoolOpt('use-syslog-rfc-format',
 
122
                # TODO(bogdando) remove or use True after existing
 
123
                #    syslog format deprecation in J
 
124
                default=False,
 
125
                help='(Optional) Use syslog rfc5424 format for logging. '
 
126
                     'If enabled, will add APP-NAME (RFC5424) before the '
 
127
                     'MSG part of the syslog message.  The old format '
 
128
                     'without APP-NAME is deprecated in I, '
 
129
                     'and will be removed in J.'),
119
130
    cfg.StrOpt('syslog-log-facility',
120
131
               default='LOG_USER',
121
 
               help='syslog facility to receive log lines')
 
132
               help='Syslog facility to receive log lines')
122
133
]
123
134
 
124
135
generic_log_opts = [
132
143
               default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
133
144
                       '%(name)s [%(request_id)s %(user_identity)s] '
134
145
                       '%(instance)s%(message)s',
135
 
               help='format string to use for log messages with context'),
 
146
               help='Format string to use for log messages with context'),
136
147
    cfg.StrOpt('logging_default_format_string',
137
148
               default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
138
149
                       '%(name)s [-] %(instance)s%(message)s',
139
 
               help='format string to use for log messages without context'),
 
150
               help='Format string to use for log messages without context'),
140
151
    cfg.StrOpt('logging_debug_format_suffix',
141
152
               default='%(funcName)s %(pathname)s:%(lineno)d',
142
 
               help='data to append to log format when level is DEBUG'),
 
153
               help='Data to append to log format when level is DEBUG'),
143
154
    cfg.StrOpt('logging_exception_prefix',
144
155
               default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s '
145
156
               '%(instance)s',
146
 
               help='prefix each line of exception output with this format'),
 
157
               help='Prefix each line of exception output with this format'),
147
158
    cfg.ListOpt('default_log_levels',
148
159
                default=[
149
160
                    'amqp=WARN',
153
164
                    'sqlalchemy=WARN',
154
165
                    'suds=INFO',
155
166
                    'iso8601=WARN',
 
167
                    'requests.packages.urllib3.connectionpool=WARN'
156
168
                ],
157
 
                help='list of logger=LEVEL pairs'),
 
169
                help='List of logger=LEVEL pairs'),
158
170
    cfg.BoolOpt('publish_errors',
159
171
                default=False,
160
 
                help='publish error events'),
 
172
                help='Publish error events'),
161
173
    cfg.BoolOpt('fatal_deprecations',
162
174
                default=False,
163
 
                help='make deprecations fatal'),
 
175
                help='Make deprecations fatal'),
164
176
 
165
177
    # NOTE(mikal): there are two options here because sometimes we are handed
166
178
    # a full instance (and could include more information), and other times we
393
405
        extra = {}
394
406
        if CONF.verbose or CONF.debug:
395
407
            extra['exc_info'] = (exc_type, value, tb)
396
 
        getLogger(product_name).critical(str(value), **extra)
 
408
        getLogger(product_name).critical(
 
409
            "".join(traceback.format_exception_only(exc_type, value)),
 
410
            **extra)
397
411
    return logging_excepthook
398
412
 
399
413
 
418
432
        raise LogConfigError(log_config_append, str(exc))
419
433
 
420
434
 
421
 
def setup(product_name):
 
435
def setup(product_name, version='unknown'):
422
436
    """Setup logging."""
423
437
    if CONF.log_config_append:
424
438
        _load_log_config(CONF.log_config_append)
425
439
    else:
426
 
        _setup_logging_from_conf()
 
440
        _setup_logging_from_conf(product_name, version)
427
441
    sys.excepthook = _create_logging_excepthook(product_name)
428
442
 
429
443
 
457
471
    return facility
458
472
 
459
473
 
460
 
def _setup_logging_from_conf():
 
474
class RFCSysLogHandler(logging.handlers.SysLogHandler):
 
475
    def __init__(self, *args, **kwargs):
 
476
        self.binary_name = _get_binary_name()
 
477
        super(RFCSysLogHandler, self).__init__(*args, **kwargs)
 
478
 
 
479
    def format(self, record):
 
480
        msg = super(RFCSysLogHandler, self).format(record)
 
481
        msg = self.binary_name + ' ' + msg
 
482
        return msg
 
483
 
 
484
 
 
485
def _setup_logging_from_conf(project, version):
461
486
    log_root = getLogger(None).logger
462
487
    for handler in log_root.handlers:
463
488
        log_root.removeHandler(handler)
464
489
 
465
490
    if CONF.use_syslog:
466
491
        facility = _find_facility_from_conf()
467
 
        syslog = logging.handlers.SysLogHandler(address='/dev/log',
468
 
                                                facility=facility)
 
492
        # TODO(bogdando) use the format provided by RFCSysLogHandler
 
493
        #   after existing syslog format deprecation in J
 
494
        if CONF.use_syslog_rfc_format:
 
495
            syslog = RFCSysLogHandler(address='/dev/log',
 
496
                                      facility=facility)
 
497
        else:
 
498
            syslog = logging.handlers.SysLogHandler(address='/dev/log',
 
499
                                                    facility=facility)
469
500
        log_root.addHandler(syslog)
470
501
 
471
502
    logpath = _get_log_file_path()
499
530
            log_root.info('Deprecated: log_format is now deprecated and will '
500
531
                          'be removed in the next release')
501
532
        else:
502
 
            handler.setFormatter(ContextFormatter(datefmt=datefmt))
 
533
            handler.setFormatter(ContextFormatter(project=project,
 
534
                                                  version=version,
 
535
                                                  datefmt=datefmt))
503
536
 
504
537
    if CONF.debug:
505
538
        log_root.setLevel(logging.DEBUG)
543
576
        self.level = level
544
577
 
545
578
    def write(self, msg):
546
 
        self.logger.log(self.level, msg)
 
579
        self.logger.log(self.level, msg.rstrip())
547
580
 
548
581
 
549
582
class ContextFormatter(logging.Formatter):
557
590
    For information about what variables are available for the formatter see:
558
591
    http://docs.python.org/library/logging.html#formatter
559
592
 
 
593
    If available, uses the context value stored in TLS - local.store.context
 
594
 
560
595
    """
561
596
 
 
597
    def __init__(self, *args, **kwargs):
 
598
        """Initialize ContextFormatter instance
 
599
 
 
600
        Takes additional keyword arguments which can be used in the message
 
601
        format string.
 
602
 
 
603
        :keyword project: project name
 
604
        :type project: string
 
605
        :keyword version: project version
 
606
        :type version: string
 
607
 
 
608
        """
 
609
 
 
610
        self.project = kwargs.pop('project', 'unknown')
 
611
        self.version = kwargs.pop('version', 'unknown')
 
612
 
 
613
        logging.Formatter.__init__(self, *args, **kwargs)
 
614
 
562
615
    def format(self, record):
563
616
        """Uses contextstring if request_id is set, otherwise default."""
564
 
        # NOTE(sdague): default the fancier formating params
 
617
 
 
618
        # store project info
 
619
        record.project = self.project
 
620
        record.version = self.version
 
621
 
 
622
        # store request info
 
623
        context = getattr(local.store, 'context', None)
 
624
        if context:
 
625
            d = _dictify_context(context)
 
626
            for k, v in d.items():
 
627
                setattr(record, k, v)
 
628
 
 
629
        # NOTE(sdague): default the fancier formatting params
565
630
        # to an empty string so we don't throw an exception if
566
631
        # they get used
567
632
        for key in ('instance', 'color'):
577
642
                CONF.logging_debug_format_suffix):
578
643
            self._fmt += " " + CONF.logging_debug_format_suffix
579
644
 
580
 
        # Cache this on the record, Logger will respect our formated copy
 
645
        # Cache this on the record, Logger will respect our formatted copy
581
646
        if record.exc_info:
582
647
            record.exc_text = self.formatException(record.exc_info, record)
583
648
        return logging.Formatter.format(self, record)