Reputation: 318
My log code:
import os
import logging
import logging.handlers
import sys
from logging import raiseExceptions
from logging import Logger
LOG_PATH = '/tmp/'
class AppLogger(Logger):
def __init__(self, name, level=logging.NOTSET):
super(AppLogger, self).__init__(name, level)
def callHandlers(self, record):
"""
Pass a record to all relevant handlers.
Loop through all handlers for this logger and its parents in the
logger hierarchy. If no handler was found, output a one-off error
message to sys.stderr. Stop searching up the hierarchy whenever a
logger with the "propagate" attribute set to zero is found - that
will be the last logger whose handlers are called.
"""
c = self
found = 0
while c:
for hdlr in c.handlers:
found = found + 1
if hdlr.name == 'console':
if record.levelno >= hdlr.level:
hdlr.handle(record)
else:
if record.levelno == hdlr.level:
hdlr.handle(record)
if not c.propagate:
c = None # break out
else:
c = c.parent
if (found == 0) and raiseExceptions and not self.manager.emittedNoHandlerWarning:
sys.stderr.write("No handlers could be found for logger"
" \"%s\"\n" % self.name)
self.manager.emittedNoHandlerWarning = 1
def get_logger(logfile_name=__name__, log_path=LOG_PATH):
'''save log to diffrent file by different log level into the log path
and print all log in console'''
logging.setLoggerClass(AppLogger)
formatter = logging.Formatter(
'%(asctime)s %(name)s %(levelname)s %(message)s',
'%Y-%m-%d %H:%M:%S')
log_files = {
logging.DEBUG: os.path.join(log_path, logfile_name + '-debug.log'),
logging.INFO: os.path.join(log_path, logfile_name + '-info.log'),
logging.WARNING: os.path.join(log_path, logfile_name + '-warning.log'),
logging.ERROR: os.path.join(log_path, logfile_name + '-error.log'),
logging.CRITICAL: os.path.join(log_path, logfile_name + '-critical.log')
}
logger = logging.getLogger()
logger.name = 'app'
logger.setLevel(logging.DEBUG)
for log_level, log_file in log_files.items():
file_handler = logging.handlers.TimedRotatingFileHandler(log_file, 'midnight')
file_handler.setLevel(log_level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
console_handler = logging.StreamHandler()
console_handler.name = "console"
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
logger = get_logger()
my flask code:
from log import logger
from flask import Flask
app = Flask(__name__)
app.debug = True
@app.route("/")
def hello():
return "Hello World!"
logger.debug('----')
logger.info('----')
logger.error('----')
logger.warning('----')
app.run()
I want to save the DEBUG level log in debug.log, INFO level log in info.log, WARNING level log in warning.log, ERROR level log in error.log, both the flask framework's log and my custom log, and I need print all the log in console.
I custom the AppLogger, but now this just working on the flask framework's log, my custom log not save in right file, the info,warning,error all write in the info.log, the name app
is my custom log, it save log together.
how to make the info.log just save the app's INFO log?
the info.log:
2017-11-08 20:07:31 app INFO ----
2017-11-08 20:07:31 app ERROR ----
2017-11-08 20:07:31 app WARNING ----
2017-11-08 20:07:31 werkzeug INFO * Restarting with stat
2017-11-08 20:07:31 app INFO ----
2017-11-08 20:07:31 app ERROR ----
2017-11-08 20:07:31 app WARNING ----
2017-11-08 20:07:31 werkzeug INFO * Debugger PIN: 971-444-041
2017-11-08 20:07:31 werkzeug INFO * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
the warning.log
2017-11-08 20:07:31 app ERROR ----
2017-11-08 20:07:31 app WARNING ----
2017-11-08 20:07:31 app ERROR ----
2017-11-08 20:07:31 app WARNING ----
2017-11-08 20:07:31 werkzeug WARNING * Debugger is active!
Upvotes: 2
Views: 2415
Reputation: 511
You can create a filter:
import logging
class LevelFilter(object):
def __init__(self, level):
self.level = logging._checkLevel(level)
def filter(self, record):
return record.levelno == self.level
Then associate this with each file:
(In YAML):
handlers:
info_handler:
class: logging.handlers.RotatingFileHandler
filename: /tmp/info.log
...
filters: [info_filter]
error_handler:
class: logging.handlers.RotatingFileHandler
filename: /tmp/errors.log
...
filters: [err_filter]
filters:
info_filter:
(): <somelogclassmodule>.LevelFilter
level: INFO
err_filter:
(): <somelogclassmodule>.LevelFilter
level: ERROR
root:
handlers: [info_handler, error_handler]
(in raw python):
from <somelogclassmodule> import LevelFilter
root = logging.getLogger()
info_handler = logging.handlers.RotatingFileHandler('info.log', ...)
error_handler = logging.handlers.RotatingFileHandler('error.log', ...)
info_filter = LevelFilter('INFO')
err_filter = LevelFilter('ERROR')
info_handler.addFilter(info_filter)
error_handler.addFilter(err_filter)
# set formatters, etc..
...
root.addHandler(info_handler)
root.addHandler(error_handler)
Upvotes: 2
Reputation: 787
you have to add only file name for each log handler change your code by getting idea from this
import logging
class MultiFileHandler(logging.FileHandler):
def __init__(self, filename, mode, encoding=None, delay=0):
logging.FileHandler.__init__(self, filename, mode, encoding, delay)
def emit(self, record):
if self.should_change_file(record):
self.change_file(record.file_id)
logging.FileHandler.emit(self, record)
def should_change_file(self, record):
if not hasattr(record, 'file_id') or record.file_id == self.baseFilename:
return False
return True
def change_file(self, file_id):
self.stream.close()
self.baseFilename = file_id
self.stream = self._open()
if __name__ == '__main__':
logger = logging.getLogger('request_logger')
logger.setLevel(logging.DEBUG)
handler = MultiFileHandler(filename='out.log', mode='a')
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
# Log some messages to the original file
logger.debug('debug message')
logger.info('info message')
# Log some messages to a different file
logger.debug('debug message', extra={'file_id':'debug.log'})
logger.info('info message', extra={'file_id':'info.log'})
logger.warn('warn message', extra={'file_id':'warn.log'})
logger.error('error message', extra={'file_id':'error.log'})
Upvotes: 1