122 lines
4.4 KiB
Python
122 lines
4.4 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Basic logger, storing data in /var/log/clogger/*.log
|
|
# Author : Pierre-Elliott Bécue <becue@crans.org>
|
|
# License : GPLv3
|
|
# Date : 27/04/2014
|
|
|
|
import os
|
|
import datetime
|
|
import pytz
|
|
import logging
|
|
|
|
TZ = pytz.timezone('Europe/Paris')
|
|
LDIRPATH = os.getenv('DBG_CLOGGER_PATH', '/var/log/clogger')
|
|
|
|
class CLogger(logging.Logger):
|
|
"""
|
|
Crans logger.
|
|
"""
|
|
|
|
def __init__(self, loggerName, service=None, level="info", debug=False):
|
|
"""
|
|
Initializes logger. The debug variable is useful to have a print to stdout (when debugging)
|
|
"""
|
|
super(CLogger, self).__init__(loggerName)
|
|
|
|
self.c_formatter = None
|
|
self.c_file_handler = None
|
|
self.c_sh = None
|
|
self.c_level = level
|
|
|
|
# When no service is specified, we don't put the reference in the format.
|
|
if service is None:
|
|
self.c_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
else:
|
|
self.c_format = "%%(asctime)s - %%(name)s - %(service)s - %%(levelname)s - %%(message)s" % {'service': service}
|
|
|
|
self.create_formatter()
|
|
self.apply_file_handler(loggerName)
|
|
if debug:
|
|
self.apply_stream_handler()
|
|
|
|
def get_file_handler_path(self):
|
|
"""Returns the file handler path"""
|
|
if self.__file_handler_path is None:
|
|
return ''
|
|
return self.__file_handler_path
|
|
|
|
def create_formatter(self):
|
|
"""Creates a formatter based on CFormatter class.
|
|
It uses self.format as a source."""
|
|
|
|
if self.c_formatter is not None:
|
|
return
|
|
|
|
# Creates formatter
|
|
self.c_formatter = CFormatter(self.c_format, "%Y-%m-%dT%H:%M:%S.%f%z")
|
|
|
|
def apply_stream_handler(self):
|
|
"""Creates a streamhandler that prints to stdout.
|
|
Its level is debug"""
|
|
self.c_sh = logging.StreamHandler()
|
|
self.c_shlevel = logging.DEBUG
|
|
self.c_sh.setLevel(self.c_shlevel)
|
|
self.c_sh.setFormatter(self.c_formatter)
|
|
self.addHandler(self.c_sh)
|
|
|
|
def apply_file_handler(self, loggerName):
|
|
"""Creates a file handler which level is given by self.c_level"""
|
|
if self.c_file_handler is not None:
|
|
return
|
|
|
|
# Computes the file handler name using service name.
|
|
self.__file_handler_path = os.path.join(LDIRPATH, "%s.log" % (loggerName,))
|
|
|
|
# Creates FileHandler
|
|
self.c_file_handler = logging.FileHandler(self.__file_handler_path)
|
|
|
|
# Catches appropriate level in logging.
|
|
self.c_file_handler_level = getattr(logging, self.c_level.upper(), logging.INFO)
|
|
self.c_file_handler.setLevel(self.c_file_handler_level)
|
|
|
|
# Adds formatter to FileHandler
|
|
self.c_file_handler.setFormatter(self.c_formatter)
|
|
|
|
# Adds FileHandler to Handlers
|
|
self.addHandler(self.c_file_handler)
|
|
|
|
class CFormatter(logging.Formatter):
|
|
"""
|
|
This Formatter subclasses the classic formatter to provide a
|
|
timezone-aware logging.
|
|
"""
|
|
|
|
converter = datetime.datetime.fromtimestamp
|
|
|
|
def formatTime(self, record, datefmt=None):
|
|
"""
|
|
Return the creation time of the specified LogRecord as formatted text.
|
|
|
|
This method should be called from format() by a formatter which
|
|
wants to make use of a formatted time. This method can be overridden
|
|
in formatters to provide for any specific requirement, but the
|
|
basic behaviour is as follows: if datefmt (a string) is specified,
|
|
it is used with time.strftime() to format the creation time of the
|
|
record. Otherwise, the ISO8601 format is used. The resulting
|
|
string is returned. This function uses a user-configurable function
|
|
to convert the creation time to a tuple. By default, time.localtime()
|
|
is used; to change this for a particular formatter instance, set the
|
|
'converter' attribute to a function with the same signature as
|
|
time.localtime() or time.gmtime(). To change it for all formatters,
|
|
for example if you want all logging times to be shown in GMT,
|
|
set the 'converter' attribute in the Formatter class.
|
|
"""
|
|
ct = self.converter(record.created, TZ)
|
|
ct = ct.replace(microsecond=int(record.msecs * 1000))
|
|
if datefmt:
|
|
s = ct.strftime(datefmt)
|
|
else:
|
|
s = ct.strftime("%Y-%m-%d %H:%M:%S.%f")
|
|
return s
|