带有 TimedRotatingFileHandler 的 django+uwsgi 日志记录“覆盖旋转的日志文件”

Pis*_*ino 5 python django logging nginx uwsgi

我最近将我的 django 生产网络应用程序从 切换apache+mod_wsginginx+uwsgiin emperor mode。除了 Time Rotated 日志文件,其他一切都好。我的网络应用程序使用一个名为appname.log的日志文件来记录所有请求,并且使用 apache 它在午夜轮换没有问题。

由于uwsgi文件在午夜轮换,但一些 uwsgi 进程/工作程序写入此轮换文件(示例轮换文件:appname.log.2017-01-08)而不是写入appname.log这会导致轮换文件被覆盖

一个解决方案似乎正在触及 uwsgi .ini 文件(我不完全确定......),但如果用户仍然连接到我的应用程序,我不想重新启动/重新加载 uwsgi。

我可以使用一种可能性或配置来通知所有 uwsgi 进程日志文件已更改,而无需重新启动 Web 应用程序?如果可能的话,我会有和我在apache+mod_wsgi.

ConcurrentLogHandler太旧了,我不想使用 syslog 或 logrotate :)

有人有同样的问题吗?有人有建议吗?

谢谢

这是我的设置:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '[%(asctime)s];[%(levelname)s];[Proc:%(process)d];[Thread:%(thread)d];%(module)s-%(funcName)s:%(lineno)d;Msg:%(message)s;'
        },
        'simple': {
            'format': '[%(asctime)s] [%(levelname)s] %(message)s'
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': LOG_FILE,
            'when': 'midnight',
            'interval': 1,
            'backupCount': 365,
            'formatter': 'verbose'
        },
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['require_debug_false']
        }
    },
    'loggers': {
        APP_NAME: {
            'handlers': ['console', 'file'],
            'propagate': True,
            'level': 'INFO',
        },
        'django': {
            'handlers': ['mail_admins', 'file'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
Run Code Online (Sandbox Code Playgroud)

cgl*_*cgl 2

我们在使用 nginx+gunicorn 时也遇到了同样的问题。我们有非常相似的设置:

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "verbose": {"format": "%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s"},
        "simple": {"format": "%(levelname)s %(asctime)s  %(message)s", "datefmt": "%Y-%m-%d %H:%M"},
    },
    "filters": {
          "require_debug_true": {"()": "django.utils.log.RequireDebugTrue"},
          "require_debug_false": {"()": "django.utils.log.RequireDebugFalse"},
    },
    "handlers": {
        "logfile": {
            "class": "logging.handlers.TimedRotatingFileHandler",
            "when": "D",
            "interval": 10, 
            "backupCount": 100,
            "filename": LOG_FILE,
            "formatter": "simple",
            "level": "DEBUG",
        },
    },
    "loggers": {    
        APP_NAME: {
            "handlers": ["console", "plus_logfile"],
            "propagate": True,
            "level": "DEBUG",
        },
    },
}
Run Code Online (Sandbox Code Playgroud)

根据Python Logging Cookbook - Logging to a single file from multiple process

尽管日志记录是线程安全的,并且支持从单个进程中的多个线程记录到单个文件,但不支持从多个进程记录到单个文件,因为没有标准方法来序列化跨多个进程对单个文件的访问。 Python 中的进程。如果需要从多个进程记录到单个文件,一种方法是让所有进程记录到 SocketHandler,并有一个单独的进程来实现从套接字读取数据并将日志记录到文件的套接字服务器。(如果您愿意,可以在现有进程之一中专门指定一个线程来执行此功能。)

因此,最好的方法是拥有一个套接字侦听器,同时侦听多个 uwsgi 工作人员并记录日志。

设置看起来像这样:

"loggers": {    
    APP_NAME: {
        "handlers": ["console", "plus_logfile"],
        "propagate": True,
        "level": "DEBUG",
    },
}, 
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到示例侦听器代码。然而,此代码写入控制台。因此,如果您想写入文件,则需要编辑侦听器脚本。