Last active
April 18, 2020 03:31
-
-
Save airstrike/c4a1dbad231345563ae7ab12f536e5ca to your computer and use it in GitHub Desktop.
Pretty logging in django
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# add to settings.py | |
LOGGING = { | |
'version': 1, | |
'disable_existing_loggers': True, | |
'loggers': { | |
'django.db.backends': { | |
'handlers': ['console_sql'], | |
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO').upper(), | |
}, | |
'cache': { | |
'handlers': ['console'], | |
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO').upper(), | |
}, | |
'django.utils.autoreload': { | |
'handlers': ['console'], | |
'level': 'ERROR', | |
}, | |
}, | |
'handlers': { | |
'console': { | |
'class': 'logging.StreamHandler', | |
'formatter': 'simple', | |
}, | |
'console_sql': { | |
'class': 'logging.StreamHandler', | |
'formatter': 'sql', | |
}, | |
}, | |
'formatters': { | |
'simple': { | |
'()': 'myproject.logging.ColorFormatter', # colored output | |
'format': '{bg %(levelname)s} %(levelname)s %(name)s %(filename)s@%(lineno)s {clear}\n{clear}{%(levelname)s}%(message)s\n{clear}' | |
}, | |
'sql': { | |
'()': 'myproject.logging.SQLFormatter', # colored output | |
'format': '{bg %(levelname)s} %(levelname)s %(name)s %(filename)s@%(lineno)s {clear}\n{clear}{%(levelname)s}%(message)s\n{clear}' | |
}, | |
'verbose': { | |
'()': 'myproject.logging.ColorFormatter', # colored output | |
'format': '%(levelname)s %(name)s %(asctime)s %(module)s %(process)d %(thread)d %(pathname)s@%(lineno)s: %(message)s{clear}' | |
}, | |
}, | |
} | |
# myproject/logging.py | |
from itertools import cycle | |
import logging | |
import sqlparse | |
COLORS = { | |
'DEBUG': '\033[0;34m', 'bold DEBUG': '\033[0;94m', 'bg DEBUG': '\033[7;34m', | |
'INFO': '\033[0;32m', 'bold INFO': '\033[1;32m', 'bg INFO': '\033[7;32m', | |
'WARNING': '\033[0;33m', 'bold WARNING': '\033[1;33m', 'bg WARNING': '\033[7;33m', | |
'CRITICAL': '\033[0;31m', 'bold CRITICAL': '\033[1;31m', 'bg CRITICAL': '\033[7;31m', | |
'ERROR': '\033[0;35m', 'bold ERROR': '\033[1;35m', 'bg ERROR': '\033[7;35m', | |
'black': '\033[0;30m', 'bold black': '\033[1;30m', | |
'red': '\033[0;31m', 'bold red': '\033[1;31m', | |
'green': '\033[0;32m', 'bold green': '\033[1;32m', | |
'yellow': '\033[0;33m', 'bold yellow': '\033[1;33m', | |
'blue': '\033[0;34m', 'bold blue': '\033[1;34m', | |
'purple': '\033[0;35m', 'bold purple': '\033[1;35m', | |
'cyan': '\033[0;36m', 'bold cyan': '\033[1;36m', | |
'gray': '\033[0;37m', 'bold gray': '\033[1;37m', | |
'white': '\033[1;37m', | |
'clear': '\033[0m', 'reverse': '\033[0;7m' | |
} | |
class GracefulDict(dict): | |
def __missing__(self, key): | |
return '{'+key+'}' | |
def graceful_format_map(record, mapping): | |
""" | |
Since someone thought it was smart to make {} the special characters for delimiting | |
string parameters to be formatted despite how ubiquitous curly braces are in json, | |
css files, python dict literals (!!!) and whatnot, we need to be a little creative | |
in our escaping so that .format_map() doesn't spit out an exception | |
""" | |
chunks = record.split('}') | |
results = '' | |
for chunk in chunks: | |
chunk = chunk + '}' | |
try: | |
chunk = chunk.format_map(GracefulDict(**mapping)) | |
except ValueError: | |
pass | |
results += chunk | |
return results[:-1] | |
class ColorFormatter(logging.Formatter): | |
colors = COLORS | |
def format(self, record): | |
record = super().format(record) | |
return graceful_format_map(record, self.colors) + self.colors['clear'] | |
class SQLFormatter(logging.Formatter): | |
colors = COLORS | |
def format(self, record): | |
try: | |
record = super().format(record) | |
record = sqlparse.format(record, reindent=True, keyword_case='upper') | |
record = graceful_format_map(record, self.colors) + self.colors['clear'] | |
except: | |
logging.exception(record) | |
return record |
Author
airstrike
commented
Apr 17, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment