logging
The logging framework is mainly composed of four parts:
- Loggers: interfaces that can be called directly by programs
- Handlers: decide to assign log records to the correct destination
- Filters: provides a more granular judgment of whether the log is output
- Formatters: make the format layout of final record printing
Logging is introduced as a module. logging.debug uses the method of logging module. Logger is logging Generated by getlogger () is a log object, logger Debug calls the method of logger, the log object. In the following example, logging Debug and logger The effect of debug is exactly the same.
import logging logging.debug('debug information') logger = logging.getLogger() logger.debug('debug information')
For the convenience of developers, the logging module provides a series of module methods, which can be used directly after the module is introduced. In this way, the developer does not need to concern the details of the log module and outputs the log like print.
When using the module method, logging actually creates a log object - root logger. Logging The call of debug is essentially a call to the logging method of root logger. Equivalent to that root logger will be used as the log processing object by default. The root logger object can be accessed through logging. Without parameters Getlogger () method.
- Basic use
import logging logging.basicConfig(level = logging.INFO,filename="path",filemode="a",format = '%(asctime)s %(message)s') #Global configuration logging.info("") logging.debuge("") logging.warning("")
- Advanced use
import logging logger = logging.getLogger() # Recorder logger.setLevel(logging.INFO) consoleHandler = logging.StreamHandler() # processor consoleHandler.setLevel(logging.DEBUG) fileHandler = logging.FileHandler("path") # processor formatter = logging.Formatter('%(asctime)s %(message)s') # Output format # Associate Handler with Formatter consoleHandler.setFormatter(formatter) fileHandler.setFormatter(formatter) #Associate Handler with logger logger.addHandler(consoleHandler) logger.addHandler(fileHandler) # Write log information using logger logger.info("") logger.debug("")
Flash log
Flash has its own logger, so you only need to use app Just call logger.
-
The flash log is displayed in the file.
if __name__ == '__main__': fh = logging.FileHandler(filename='./log/flask_matting_head.log', encoding='utf-8') logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d, %b %Y %H:%M:%S', handlers=[fh]) app.debug = True app.run(host='0.0.0.0', port=7788, debug=True)
-
The flash log is displayed on the console
if __name__ == '__main__': logger = logging.getLogger() logger.setLevel('DEBUG') BASIC_FORMAT = '%(asctimie)s:%(levelname)s:%(message)s' DATE_FORMAT = '%y-%m-%d %H:%M:%S' formatter = logging.Formatter(BASIC_FORMAT, DATE_FORMAT) chlr = logging.StreamHandler() chlr.setFormatter(formatter) logger.addHandler(chlr) logger.setLevel('DEBUG') app.run(host='0.0.0.0', port=7788, debug=True)
gunicorn log
gunicorn can use logging Config for complete configuration.
Configuration of logs in gunicorn.
```python # !/usr/bin/env python # -*- coding: utf-8 -*- # # @Author: xxx # @Date : 1/17/22 9:09 AM # @File : config.py # config.py import os import gevent.monkey gevent.monkey.patch_all() import multiprocessing #debug = True bind = '0.0.0.0:7788' pidfile = 'log/gunicorn.pid' logconfig_dict = { 'version':1, 'disable_existing_loggers': False, 'loggers':{ "gunicorn.error": { "level": "WARNING",# The level of logging can be changed. The same is true for the following "handlers": ["error_file"], # Corresponding to the following key "propagate": 1, "qualname": "gunicorn.error" }, "gunicorn.access": { "level": "DEBUG", "handlers": ["access_file"], "propagate": 0, "qualname": "gunicorn.access" } }, 'handlers':{ "error_file": { "class": "logging.handlers.RotatingFileHandler", "maxBytes": 1024*1024*1024,# The size of the log is 1 G "backupCount": 1,# How many copies to back up, after testing, at least write 1, otherwise you can't control the size "formatter": "generic",# Corresponding to the following key # 'mode': 'w+', "filename": "./log/gunicorn.error.log"# Log path }, "access_file": { "class": "logging.handlers.RotatingFileHandler", "maxBytes": 1024*1024*1024, "backupCount": 1, "formatter": "generic", "filename": "./log/gunicorn.access.log", } }, 'formatters':{ "generic": { "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", # Format of printing log "datefmt": "[%Y-%m-%d %H:%M:%S %z]",# Time display method "class": "logging.Formatter" }, "access": { "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", "class": "logging.Formatter" } } } capture_output = True #loglevel = 'warning' loglevel = 'debug' daemon = True #Background start reload = True #workers = multiprocessing.cpu_count() workers = 1 worker_class = 'gevent' x_forwarded_for_header = 'X-FORWARDED-FOR' ```
If you need to merge the logger of Flask and the log of Gunicorn, you need to add such a piece of code to Flask. That is, when Flask is not self started, it is started by Gunicorn, then Gunicorn is obtained Error's logger, which will app The handler of the logger is assigned Gunicorn error. handler. Add app Logger of logger The level is set to the same level as the Gunicorn configuration.
if __name__ != '__main__': gunicorn_logger = logging.getLogger('gunicorn.error') app.logger.handlers = gunicorn_logger.handlers app.logger.setLevel(gunicorn_logger.level)
reference material
Understanding and using of logging
Flag and Gunicorn's logger
log processing of gunicorn deployment flash
gunicorn log problem
Artifact logging, do you really understand?
Basic use of logging