I just implemented logging in my app, and I'd like to know if there's a method to check if a logger is empty or not.
What I have in mind is to set two handlers in my script:
WARNING
DEBUG
At the end of the script, I need to check if CONSOLE
logger is not empty. This means that during the run, some messages with level >= WARNING
were logged, and in this case I'd like to send the log file with debug level thru smtp
to my mailbox.
Is this check possible inside the python
script itself, without shell redirection to file?
There's a general purpose way to count the number of times a function was called using decorators you can check out here
If you wrap this decorator around class calls you are interested in you could find out how many times each member function was called, something like this:
def counted(fn):
def wrapper(*args, **kwargs):
wrapper.called += 1
return fn(*args, **kwargs)
wrapper.called = 0
wrapper.__name__ = fn.__name__
return wrapper
class MyLogger(logging.Logger, object):
@counted
def info(self, *args, **kwargs):
super(MyLogger, self).info(*args, **kwargs)
@counted
def warning(self, *args, **kwargs):
super(MyLogger, self).warning(*args, **kwargs)
Next just set up your logger like any other and use it as you normally would:
log = my_logger.MyLogger('test_logger')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
log.addHandler(ch)
log.setLevel(logging.DEBUG)
>>> log.info('no big deal')
no big deal
>>> log.info('harmless message')
harmless message
>>> log.warning('oh no')
oh no
>>> log.info.called
2
>>> log.warning.called
1
You would need to decorate all of the classes you wanted counted, so exception, debug etc.
I'm sorry, I forgot to complete this thread.
Following Mike's idea, I came up with something like this :
in a module called logset.py :
def counted(fn):
def wrapper(*args, **kwargs):
wrapper.count += 1
return fn(*args, **kwargs)
wrapper.count = 0
wrapper.__name__ = fn.__name__
return wrapper
class MyLogger(logging.Logger):
def __init__(self, name=None, level=logging.NOTSET):
super(MyLogger, self).__init__(name, level)
@counted
def info(self, *args, **kwargs):
super(MyLogger, self).info(*args, **kwargs)
@counted
def warning(self, *args, **kwargs):
super(MyLogger, self).warning(*args, **kwargs)
@counted
def critical(self, msg, *args, **kwargs):
super(MyLogger, self).warning(*args, **kwargs)
@counted
def error(self, *args, **kwargs):
super(MyLogger, self).warning(*args, **kwargs)
def logfile(self):
for h in self.handlers:
if hasattr(h, 'baseFilename'):
return h.baseFilename
def empty(self):
if self.warning.count or self.critical.count or self.error.count:
return False
else:
return True
def status(self):
msg = "WARNINGS:%s ERRORS:%s CRITICAL:%s" % (self.warning.count, self.error.count, self.critical.count)
return msg
def addLogFile(logger, filepath):
handler = logging.FileHandler(filepath, "w", encoding=None, delay="true")
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(levelname)s\t: %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
def addLogConsole(logger):
handler = logging.StreamHandler()
handler.setLevel(logging.WARNING)
formatter = logging.Formatter("%(levelname)s\t: %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
def myLog(level=None):
if not LOGGER.handlers:
# "Adding Handlers..."
addLogConsole(LOGGER)
addLogFile(LOGGER, '#YOUR LOG FILE#')
return LOGGER
LOGGER = MyLogger("root")
In my app's start file :
from logset import myLog
.
.
. # Initialize the log
root = myLog()
.
.
. # Do something in your app and at end check :
if not root.empty():
print "\nProgram has logged some errors, check log : %s" % root.logfile()
print root.status()
# now I can send root.logfile() via smtp for further examination
You can repeat the import in every module that needs logging, it always refers to the same logger object:
from logset import myLog
log = myLog()
.
.
.
log.info("Adding something")
log.debug("this var has value : %s" % value)
Thank you for your help and attention.
Enrico
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.