Skip to content

Commit

Permalink
Merge pull request #14 from kbakk/custom_log_format
Browse files Browse the repository at this point in the history
Custom log format
  • Loading branch information
bobbui authored Jan 26, 2019
2 parents be0e64e + 2219954 commit db18f62
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
74 changes: 74 additions & 0 deletions example/custom_log_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# This example shows how the logger can be set up to use a custom JSON format.
import logging
import json
import traceback
from datetime import datetime
import copy
import json_logging
import sys

json_logging.ENABLE_JSON_LOGGING = True


def extra(**kw):
'''Add the required nested props layer'''
return {'extra': {'props': kw}}


class CustomJSONLog(logging.Formatter):
"""
Customized logger
"""
python_log_prefix = 'python.'
def get_exc_fields(self, record):
if record.exc_info:
exc_info = self.format_exception(record.exc_info)
else:
exc_info = record.exc_text
return {f'{self.python_log_prefix}exc_info': exc_info}

@classmethod
def format_exception(cls, exc_info):
return ''.join(traceback.format_exception(*exc_info)) if exc_info else ''

def format(self, record):
json_log_object = {"@timestamp": datetime.utcnow().isoformat(),
"level": record.levelname,
"message": record.getMessage(),
"caller": record.filename + '::' + record.funcName
}
json_log_object['data'] = {
f'{self.python_log_prefix}logger_name': record.name,
f'{self.python_log_prefix}module': record.module,
f'{self.python_log_prefix}funcName': record.funcName,
f'{self.python_log_prefix}filename': record.filename,
f'{self.python_log_prefix}lineno': record.lineno,
f'{self.python_log_prefix}thread': f'{record.threadName}[{record.thread}]',
f'{self.python_log_prefix}pid': record.process
}
if hasattr(record, 'props'):
json_log_object['data'].update(record.props)

if record.exc_info or record.exc_text:
json_log_object['data'].update(self.get_exc_fields(record))

return json.dumps(json_log_object)


def logger_init():
json_logging.init(custom_formatter=CustomJSONLog)

# You would normally import logger_init and setup the logger in your main module - e.g.
# main.py

logger_init()

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.StreamHandler(sys.stderr))

logger.info('Starting')
try:
1/0
except: # noqa pylint: disable=bare-except
logger.exception('You can\t divide by zero')
9 changes: 8 additions & 1 deletion json_logging/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,15 @@ def config_root_logger():
"logging.basicConfig() or logging.getLogger('root')")


def init(framework_name=None):
def init(framework_name=None, custom_formatter=None):
"""
Initialize JSON logging support, if no **framework_name** passed, logging will be initialized in non-web context.
This is supposed to be called only one time.
If **custom_formatter** is passed, it will (in non-web context) use this formatter over the default.
:param framework_name: type of framework logging should support.
:param custom_formatter: formatter to override default JSONLogFormatter.
"""

global _current_framework
Expand All @@ -123,6 +126,10 @@ def init(framework_name=None):
_current_framework['app_configurator']().config()

formatter = JSONLogWebFormatter
elif custom_formatter:
if not issubclass(custom_formatter, logging.Formatter):
raise ValueError('custom_formatter is not subclass of logging.Formatter', custom_formatter)
formatter = custom_formatter
else:
formatter = JSONLogFormatter

Expand Down

0 comments on commit db18f62

Please sign in to comment.