首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何重写Gunicorn的日志配置以使用自定义格式化程序

如何重写Gunicorn的日志配置以使用自定义格式化程序
EN

Stack Overflow用户
提问于 2016-12-11 23:26:41
回答 5查看 15K关注 0票数 13

我希望gunicorn.error使用以下基于键值的日志格式,而不是gunicorn/glogging.py中定义的默认格式

代码语言:javascript
运行
复制
'format': 'timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s'`

在我的gunicorn配置文件中:

代码语言:javascript
运行
复制
import logging.config

workers = 2
bind = "127.0.0.1:8000"
loglevel = 'INFO'

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'key_value': {
            'format': 'timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s'
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'key_value',
            'stream': 'ext://sys.stdout'
        }
    },
    'loggers': {
        'gunicorn.error': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        },
        'flask.app': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        }
    },
}

logging.config.dictConfig(LOGGING)

Gunicorn以我的自定义格式和默认格式记录了两次:

代码语言:javascript
运行
复制
timestamp=2016-12-11 15:20:49,559 pid=22110 loglevel=INFO msg=Starting gunicorn 19.6.0
[2016-12-11 15:20:49 +0000] [22110] [INFO] Starting gunicorn 19.6.0
timestamp=2016-12-11 15:20:49,559 pid=22110 loglevel=INFO msg=Listening at: http://127.0.0.1:8000 (22110)
[2016-12-11 15:20:49 +0000] [22110] [INFO] Listening at: http://127.0.0.1:8000 (22110)
timestamp=2016-12-11 15:20:49,559 pid=22110 loglevel=INFO msg=Using worker: sync
[2016-12-11 15:20:49 +0000] [22110] [INFO] Using worker: sync
timestamp=2016-12-11 15:20:49,560 pid=22115 loglevel=INFO msg=Booting worker with pid: 22115
[2016-12-11 15:20:49 +0000] [22115] [INFO] Booting worker with pid: 22115
timestamp=2016-12-11 15:20:49,595 pid=22115 loglevel=INFO msg=Starting Flask application
timestamp=2016-12-11 15:20:49,659 pid=22120 loglevel=INFO msg=Booting worker with pid: 22120
[2016-12-11 15:20:49 +0000] [22120] [INFO] Booting worker with pid: 22120
timestamp=2016-12-11 15:20:49,693 pid=22120 loglevel=INFO msg=Starting Flask application

我使用logging_tree库查看了已配置的记录器,我看到两个黑角记录器向控制台发出:

代码语言:javascript
运行
复制
<--""
   Level WARNING
   |
   o<--"flask"
   |   Level NOTSET so inherits level WARNING
   |   |
   |   o   "flask.app"
   |       Level INFO
   |       Propagate OFF
   |       Handler Stream <open file '<stdout>', mode 'w' at 0x7f86676b1150>
   |         Level INFO
   |         Formatter fmt='timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s' datefmt=None
   |
   o<--"gunicorn"
       Level NOTSET so inherits level WARNING
       |
       o   "gunicorn.access"
       |   Level INFO
       |   Propagate OFF
       |
       o   "gunicorn.error"
       |   Level INFO
       |   Propagate OFF
       |   Handler Stream <open file '<stdout>', mode 'w' at 0x7f86676b1150>
       |     Level INFO
       |     Formatter fmt='timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s' datefmt=None
       |   Handler Stream <open file '<stderr>', mode 'w' at 0x7f86676b11e0>
       |     Formatter fmt='%(asctime)s [%(process)d] [%(levelname)s] %(message)s' datefmt='[%Y-%m-%d %H:%M:%S %z]'
       |
       o<--"gunicorn.http"
           Level NOTSET so inherits level WARNING
           |
           o<--"gunicorn.http.wsgi"
               Level NOTSET so inherits level WARNING

Gunicorn的docs说可以指定要使用的记录器类,但我不知道如何做到这一点。

EN

Stack Overflow用户

发布于 2021-07-25 18:20:16

gunicorn的日志记录的问题是,它通常在你的代码之前运行在相同的Python进程中,configures logging在你的任何与WSGI相关的代码运行之前记录一些消息,你有机会按照自己的方式配置日志记录。

代码语言:javascript
运行
复制
$ gunicorn --help | grep logger
  --logger-class STRING
                        The logger you want to use to log events in Gunicorn.

请注意,不推荐使用incremental configuration (即gunicorn调用dictConfig一次,然后由您调用),这可能也不是您想要的:

...一旦设置了配置,就不存在在运行时任意更改记录器、处理程序、过滤器、格式化程序的对象图的令人信服的情况;记录器和处理程序的冗长可以仅通过设置级别(对于记录器,传播标志)来控制。在多线程环境中,以安全的方式任意更改对象图是有问题的;虽然并非不可能,但其带来的好处并不值得为实现增加复杂性。

因此,我建议将gunicorn视为regular library with regards to logging,并完全禁用其日志记录配置(有利于您的应用程序)。

这是一个简单的应用程序,它具有HTTP和控制台入口点,这两个入口点应该具有相同的日志配置:

代码语言:javascript
运行
复制
logging_cfg = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'KeyValueFormatter': {
            'format': (
                'timestamp=%(asctime)s pid=%(process)d '
                'loglevel=%(levelname)s msg=%(message)s'
            )
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'KeyValueFormatter',
        }
    },
    'loggers': {
        'gunicorn.access': {
            'propagate': True,
        },
        'gunicorn.error': {
            'propagate': True,
        },
    },
    'root': {
        'level': 'INFO',
        'handlers': ['console'],
    }
}

这里是它的实现,app.py

代码语言:javascript
运行
复制
import logging.config

from gunicorn import glogging


logger = logging.getLogger(__name__)

def get_result():
    logger.info('Calculating result')
    return b'Hello world!'

def wsgi_app(environ, start_response):
    result = get_result()
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [result]

def configure_logging():
    logging.config.dictConfig(logging_cfg)

class UniformLogger(glogging.Logger):

    def setup(self, cfg):
        configure_logging()


if __name__ == '__main__':
    configure_logging()
    print(get_result())

如果你运行python app.py,你应该会得到:

代码语言:javascript
运行
复制
timestamp=2021-07-25 12:09:04,488 pid=4599 loglevel=INFO msg=Calculating result
b'Hello world!'

如果先运行gunicorn --logger-class=app.UniformLogger app:wsgi_app,然后运行curl localhost:8000

代码语言:javascript
运行
复制
timestamp=2021-07-25 12:16:56,892 pid=4874 loglevel=INFO msg=Starting gunicorn 20.1.0
timestamp=2021-07-25 12:16:56,892 pid=4874 loglevel=INFO msg=Listening at: http://127.0.0.1:8000 (4874)
timestamp=2021-07-25 12:16:56,893 pid=4874 loglevel=INFO msg=Using worker: sync
timestamp=2021-07-25 12:16:56,894 pid=4876 loglevel=INFO msg=Booting worker with pid: 4876
timestamp=2021-07-25 12:17:06,926 pid=4876 loglevel=INFO msg=Calculating result
票数 0
EN
查看全部 5 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41087790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档