Repository URL to install this package:
|
Version:
0.4.200 ▾
|
lib-py-b2b
/
logging.py
|
|---|
import json
import logging
from lib_b2b.util import UtilityEncoder
def json_formatter(obj):
"""Formatter for unserialisable values."""
return str(obj)
class JsonFormatter(logging.Formatter):
"""AWS Lambda Logging formatter.
Formats the log message as a JSON encoded string. If the message is a
dict it will be used directly. If the message can be parsed as JSON, then
the parse d value is used in the output record.
"""
def __init__(self, **kwargs):
"""Return a JsonFormatter instance.
The `json_default` kwarg is used to specify a formatter for otherwise
unserialisable values. It must not throw. Defaults to a function that
coerces the value to a string.
Other kwargs are used to specify log field format strings.
"""
datefmt = kwargs.pop('datefmt', None)
super(JsonFormatter, self).__init__(datefmt=datefmt)
self.format_dict = {
'timestamp': '%(asctime)s',
'level': '%(levelname)s',
'location': '%(name)s.%(funcName)s:%(lineno)d',
'aws_request_id': '%(aws_request_id)s'
}
self.format_dict.update(kwargs)
self.default_json_formatter = kwargs.pop(
'json_default', json_formatter)
def format(self, record):
record_dict = record.__dict__.copy()
record_dict['asctime'] = self.formatTime(record, self.datefmt)
record_dict['aws_request_id'] = getattr(record, 'aws_request_id', '00000000-0000-0000-0000-000000000000')
log_dict = {
k: v % record_dict
for k, v in self.format_dict.items()
if v
}
if isinstance(record_dict['msg'], dict):
log_dict['message'] = record_dict['msg']
else:
log_dict['message'] = record.getMessage()
# Attempt to decode the message as JSON, if so, merge it with the
# overall message for clarity.
try:
log_dict['message'] = json.loads(log_dict['message'])
except (TypeError, ValueError):
pass
if record.exc_info:
# Cache the traceback text to avoid converting it multiple times
# (it's constant anyway)
# from logging.Formatter:format
if not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
if record.exc_text:
log_dict['exception'] = record.exc_text
json_record = json.dumps(log_dict, default=self.default_json_formatter)
if hasattr(json_record, 'decode'): # pragma: no cover
json_record = json_record.decode('utf-8')
return json_record
def setup(level='DEBUG', formatter_cls=JsonFormatter,
boto_level=None, **kwargs):
"""Overall Metadata Formatting."""
if formatter_cls:
for handler in logging.root.handlers:
handler.setFormatter(formatter_cls(**kwargs))
try:
logging.root.setLevel(level)
except ValueError:
logging.root.error('Invalid log level: %s', level)
level = 'INFO'
logging.root.setLevel(level)
if not boto_level:
boto_level = level
try:
logging.getLogger('boto').setLevel(boto_level)
logging.getLogger('boto3').setLevel(boto_level)
logging.getLogger('botocore').setLevel(boto_level)
except ValueError:
logging.root.error('Invalid log level: %s', boto_level)
# class StructuredMessage(object):
# def __init__(self, message, **kwargs):
# self.message = message
# self.kwargs = kwargs
#
# def __str__(self):
# return '%s >>> %s' % (self.message, json.dumps(self.kwargs))
#
# _ = StructuredMessage # optional, to improve readability
#
# logging.basicConfig(level=logging.INFO, format='%(message)s')
# logging.info(_('message 1', foo='bar', bar='baz', num=123, fnum=123.456))
#
#
# class StructuredLogFormatter(logging.Formatter):
#
# def format(self, record):
# record.message = record.getMessage()
# if self.usesTime():
# record.asctime = self.formatTime(record, self.datefmt)
# j = {
# 'levelname': record.levelname,
# 'time': '%(asctime)s.%(msecs)dZ' % dict(asctime=record.asctime, msecs=record.msecs),
# 'aws_request_id': getattr(record, 'aws_request_id', '00000000-0000-0000-0000-000000000000'),
# 'message': record.message,
# 'module': record.module,
# 'extra_data': record.__dict__.get('data', {}),
# }
# return json.dumps(j)
#
#
# logger = logging.getLogger()
# logger.setLevel('INFO')
#
# formatter = FormatterJSON(
# '[%(levelname)s]\t%(asctime)s.%(msecs)dZ\t%(levelno)s\t%(message)s\n',
# '%Y-%m-%dT%H:%M:%S'
# )
# # Replace the LambdaLoggerHandler formatter :
# logger.handlers[0].setFormatter(formatter)
#
#
# def lambda_handler(event, context):
# my_input = {
# 'key1': 'value1',
# 'key2': 'value2'
# }
# logger.info('Process Info: %s', 'Hello', extra=dict(data=my_input))