Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
lib-py-b2b / logging.py
Size: Mime:
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))