Skip to content

Instantly share code, notes, and snippets.

@dylanbstorey
Created July 31, 2017 13:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dylanbstorey/ebda4623a275072b49889f4ef84792e8 to your computer and use it in GitHub Desktop.
Save dylanbstorey/ebda4623a275072b49889f4ef84792e8 to your computer and use it in GitHub Desktop.
A general logging class for most projects to start with.
"""
Adapted from Camille Scott's dammit logger :
https://github.com/camillescott/dammit/blob/master/dammit/log.py
and
Robpol86
https://github.com/Robpol86/Flask-Large-Application-Example/blob/master/manage.py#L81
The general idea here is to encapsulate logging so that we can keep things quite unless we absolutely need them.
.. code-block: python
:linenos:
from log import Logger, getLogger
top_log = Logger()
top_log.start()
t = getLogger(__name__)
t.info('very useful logging message here')
#[INFO]:31-07-17 09:23:08:builtins:<module>:1::: very useful logging message here
"""
import logging
import os
import sys
import textwrap
class LogFormatter(logging.Formatter):
def __init__(self, width=90, padding=10):
super(LogFormatter, self).__init__('')
self.width = width
self.padding = padding
def do_wrap(self, msg, pad):
wrapped = textwrap.wrap(msg, self.width - self.padding)
return ['{0}{1}'.format(pad, ln) for ln in wrapped]
def format(self, record):
if record.levelno < 40:
pad = ' ' * self.padding
wrapped = self.do_wrap(record.msg, pad)
res = '\n'.join(wrapped) + '\n'
else:
extra = '[{0}:{1}]'.format(record.name, record.levelname)
res = record.msg + extra
return res
class Logger(object):
'''Set up logging for the angreal application.
Insulated to keep things from getting noisy.
'''
def __init__(self,name=None,log_dir=None):
"""
Initializes a top level logging object.
:param name: The file name of the log, defaults to Log-McLogface.log
:param log_dir: A directory where the log should be written to, defaults to None (essentially where main is)
"""
self.LOG_TO_DISK = False
if name:
self.LOG_TO_DISK=True
if log_dir:
#Attempt to create
try:
os.mkdir(log_dir)
except FileExistsError:
if os.path.isfile(log_dir):
print('ERROR: Directory {} does not exist'.format(log_dir))
sys.exit(1)
pass
if not os.access(log_dir,os.W_OK):
print('ERROR: Cant write to directory {} '.format(log_dir))
sys.exit(1)
if not name:
name = 'Log-McLogface.log'
self.LOG_TO_DISK = True
if log_dir:
self.log_file = os.path.join(log_dir,name)
else:
self.log_file = name
self.config = {
'format' : '[%(levelname)s]:%(asctime)s:%(name)s:%(funcName)s:%(lineno)d::: %(message)s\n',
'datefmt' : '%d-%m-%y %H:%M:%S',
'filemode' : 'a',
'filename' : self.log_file
}
# Default behaviour, silent logging, we do nothing.
self.logger = logging.getLogger(__name__)
noop = logging.NullHandler()
self.logger.addHandler(noop)
def start(self):
"""
Actually starts the logger.
:return:
"""
#setup the basic logging configuration
logging.basicConfig(level=logging.DEBUG, **self.config)
# Capture warnings to stderr
self.console = logging.StreamHandler(sys.stderr)
self.console.setLevel(logging.WARNING)
self.console.setFormatter(LogFormatter())
logging.getLogger('').addHandler(self.console)
logging.getLogger('main')
def getLogger(name):
"""
Just a wrapper to logging.getLogger
:param name:
:return:
"""
return logging.getLogger(name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment