115
115
'--log-file paths'),
116
116
cfg.BoolOpt('use-syslog',
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
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')
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 '
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',
153
164
'sqlalchemy=WARN',
167
'requests.packages.urllib3.connectionpool=WARN'
157
help='list of logger=LEVEL pairs'),
169
help='List of logger=LEVEL pairs'),
158
170
cfg.BoolOpt('publish_errors',
160
help='publish error events'),
172
help='Publish error events'),
161
173
cfg.BoolOpt('fatal_deprecations',
163
help='make deprecations fatal'),
175
help='Make deprecations fatal'),
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
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)),
397
411
return logging_excepthook
418
432
raise LogConfigError(log_config_append, str(exc))
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)
426
_setup_logging_from_conf()
440
_setup_logging_from_conf(product_name, version)
427
441
sys.excepthook = _create_logging_excepthook(product_name)
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)
479
def format(self, record):
480
msg = super(RFCSysLogHandler, self).format(record)
481
msg = self.binary_name + ' ' + msg
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)
465
490
if CONF.use_syslog:
466
491
facility = _find_facility_from_conf()
467
syslog = logging.handlers.SysLogHandler(address='/dev/log',
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',
498
syslog = logging.handlers.SysLogHandler(address='/dev/log',
469
500
log_root.addHandler(syslog)
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')
502
handler.setFormatter(ContextFormatter(datefmt=datefmt))
533
handler.setFormatter(ContextFormatter(project=project,
505
538
log_root.setLevel(logging.DEBUG)
557
590
For information about what variables are available for the formatter see:
558
591
http://docs.python.org/library/logging.html#formatter
593
If available, uses the context value stored in TLS - local.store.context
597
def __init__(self, *args, **kwargs):
598
"""Initialize ContextFormatter instance
600
Takes additional keyword arguments which can be used in the message
603
:keyword project: project name
604
:type project: string
605
:keyword version: project version
606
:type version: string
610
self.project = kwargs.pop('project', 'unknown')
611
self.version = kwargs.pop('version', 'unknown')
613
logging.Formatter.__init__(self, *args, **kwargs)
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
619
record.project = self.project
620
record.version = self.version
623
context = getattr(local.store, 'context', None)
625
d = _dictify_context(context)
626
for k, v in d.items():
627
setattr(record, k, v)
629
# NOTE(sdague): default the fancier formatting params
565
630
# to an empty string so we don't throw an exception if
567
632
for key in ('instance', 'color'):
577
642
CONF.logging_debug_format_suffix):
578
643
self._fmt += " " + CONF.logging_debug_format_suffix
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)