gunicorn日志系列1-输出限制大小的问题 Unable to configure root logger: Unable to add handler ‘console‘: ‘console‘

参考:
issu:https://github.com/benoitc/gunicorn/pull/2431
案例文档:https://github.com/benoitc/gunicorn/blob/master/gunicorn/glogging.py

python官方日志参考:https://docs.python.org/3.7/library/logging.html

旧版配置方式,不能控制日志大小

loglevel = "info"    # debug, info, warning, error, critical.
pidfile = "logs/gunicore.pid"  # 设置进程id pid文件的文件名
accesslog = "logs/gunicorn_http.log"  # 设置访问日志
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" "%(q)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s %(p)s'
errorlog = "logs/gunicorn_info.log"  # 设置问题记录日志

新版配置方式,控制日志大小

logconfig_dict = {
    'version':1,
    'disable_existing_loggers': False,
    'loggers':{
        "gunicorn.error": {
            "level": "DEBUG",# 打日志的等级可以换的,下面的同理
            "handlers": ["error_file"], # 对应下面的键
            "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,# 打日志的大小,我这种写法是1个G
            "backupCount": 1,# 备份多少份,经过测试,最少也要写1,不然控制不住大小
            "formatter": "generic",# 对应下面的键
            # 'mode': 'w+',
            "filename": "/你要放日志的路径/gunicorn.error.log"# 打日志的路径
        },
        "access_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "maxBytes": 1024*1024*1024,
            "backupCount": 1,
            "formatter": "generic",
            "filename": "/你要放日志的路径/gunicorn.access.log",
        }
    },
    'formatters':{
        "generic": {
            "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'", # 打日志的格式
            "datefmt": "[%Y-%m-%d %H:%M:%S %z]",# 时间显示方法
            "class": "logging.Formatter"
        },
        "access": {
            "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'",
            "class": "logging.Formatter"
        }
    }
}

配置后运行报错

gunicorn -c gunicorn_cfg.py main_api:app  
Error: Unable to configure handler 'access_file'
gunicorn运行报错Error: Unable to configure root logger: Unable to add handler ‘console‘: ‘console‘

解决方案1,增加如下配置

"root": {"level": "INFO", "handlers": ["error_file", "access_file"]},
logconfig_dict = {
    "version": 1,
    "disable_existing_loggers": False,

    "root": {"level": "INFO", "handlers": ["error_file", "access_file"]},
    "loggers": {
        "gunicorn.error": {
            "level": "INFO",  # 打日志的等级可以换的,下面的同理
            "handlers": ["error_file"],  # 对应下面的键
            "propagate": 1,
            "qualname": "gunicorn.error"
        },

        "gunicorn.access": {
            "level": "INFO",
            "handlers": ["access_file"],
            "propagate": 0,
            "qualname": "gunicorn.access"
        }
    },
    "handlers": {
        "error_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "maxBytes": 1024 * 1024 * 50,  # 打日志的大小,我这种写法是1个G
            "backupCount": 1,  # 备份多少份,经过测试,最少也要写1,不然控制不住大小
            "formatter": "generic",  # 对应下面的键
            # "mode": "w+",
            "filename": "./logs/error.log"  # 打日志的路径
        },
        "access_file": {
            "class": "logging.handlers.RotatingFileHandler",
            "maxBytes": 1024 * 1024 * 50,
            "backupCount": 1,
            "formatter": "generic",
            "filename": "./logs/access.log",
        }
    },
    "formatters": {
        "generic": {
            "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'",  # 打日志的格式
            "datefmt": "[%Y-%m-%d %H:%M:%S %z]",  # 时间显示方法
            "class": "logging.Formatter"
        },
        "access": {
            "format": "'[%(process)d] [%(asctime)s] %(levelname)s [%(filename)s:%(lineno)s] %(message)s'",
            "class": "logging.Formatter"
        }
    }
}

解决方案2 以上配置报错后,按官方参考配置

案例文档:https://github.com/benoitc/gunicorn/blob/master/gunicorn/glogging.py

CONFIG_DEFAULTS = dict(
        version=1,
        disable_existing_loggers=False,

        root={"level": "INFO", "handlers": ["console"]},
        loggers={
            "gunicorn.error": {
                "level": "INFO",
                "handlers": ["error_console"],
                "propagate": True,
                "qualname": "gunicorn.error"
            },

            "gunicorn.access": {
                "level": "INFO",
                "handlers": ["console"],
                "propagate": True,
                "qualname": "gunicorn.access"
            }
        },
        handlers={
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "generic",
                "stream": "ext://sys.stdout"
            },
            "error_console": {
                "class": "logging.StreamHandler",
                "formatter": "generic",
                "stream": "ext://sys.stderr"
            },
        },
        formatters={
            "generic": {
                "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
                "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
                "class": "logging.Formatter"
            }
        }
)

备注

:logger可以看做是一个记录日志的人,对于记录的每个日志,他需要有一套规则,比如记录的格式(formatter),等级(level)等等,这个规则就是handler。使用logger.addHandler(handler)添加多个规则,就可以让一个logger记录多个日志。

创建logger
创建handler
定义formatter
给handler添加formatter
给logger添加handler
写成代码差不多就是酱婶的(这个是照别的网页抄的,参考附注):

 1 import logging 
 2 
 3 # 1、创建一个logger 
 4 logger = logging.getLogger('mylogger') 
 5 logger.setLevel(logging.DEBUG) 
 6 
 7 # 2、创建一个handler,用于写入日志文件 
 8 fh = logging.FileHandler('test.log') 
 9 fh.setLevel(logging.DEBUG) 
10 
11 # 再创建一个handler,用于输出到控制台 
12 ch = logging.StreamHandler() 
13 ch.setLevel(logging.DEBUG) 
14 
15 # 3、定义handler的输出格式(formatter)
16 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 
17 
18 # 4、给handler添加formatter
19 fh.setFormatter(formatter) 
20 ch.setFormatter(formatter) 
21 
22 # 5、给logger添加handler 
23 logger.addHandler(fh) 
24 logger.addHandler(ch) 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用 Flask-SocketIO 和 gunicorn 部署应用时,由于 gunicorn 默认使用的是 synchronous 的 worker class,因此需要使用 eventlet 或 gevent 等异步 worker class 才能够支持 WebSocket 的长连接。 使用 eventlet 或 gevent 时,不需要额外设置多线程,因为它们本身就是异步的并且支持并发处理请求。但是,需要注意的是,使用异步 worker class 时,需要在应用启动时设置 monkey patch,以确保所有的标准库在运行时都能够使用异步的方式进行处理。 在 Flask-SocketIO 中,可以使用 `socketio.run(app, **kwargs)` 方法启动应用,并且设置 `async_mode='eventlet'` 或 `async_mode='gevent'` 参数,以指定使用的异步模式。同时,也需要在启动应用前调用 `monkey_patch()` 方法进行 monkey patch。以下是一个使用 eventlet 异步 worker class 的示例代码: ``` from flask import Flask from flask_socketio import SocketIO app = Flask(__name__) socketio = SocketIO(app, async_mode='eventlet') # 进行 monkey patch import eventlet eventlet.monkey_patch() # 定义 SocketIO 事件处理函数 @socketio.on('connect') def handle_connect(): print('A client connected') # 启动应用 if __name__ == '__main__': socketio.run(app, host='0.0.0.0', port=5000) ``` 使用 gunicorn 启动应用时,可以使用以下命令: ``` gunicorn --worker-class eventlet -w 1 module:app ``` 其中,`--worker-class eventlet` 指定使用 eventlet 异步 worker class,`-w 1` 指定启动一个 worker 进程,`module:app` 指定 Flask 应用的入口模块和应用实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值