August Rush

一个还在努力成长的小火汁!

游龙当归海,海不迎我自来也。

We create our own demons.

You can reach me at augustrush0923@gmail.com
Django中的logging
发布:2021年03月19日 | 作者:augustrush | 阅读量: 430

对网站、微服务来说,log(日志)是比较重要的运维工具。 Django的log,主要是复用Python标准库中的logging模块,在settings.py中进行配置。 此外,也提供了一些独特的扩展。


一份完整配置示例

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 是否禁用已经存在的日志器
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        }
    },
    'filters': {  # 对日志进行过滤
        'require_debug_true': {  # django在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志处理方法
        'console': {  # 向终端中输出日志
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {  # 向文件中输出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/meiduo.log"),  # 日志文件的位置
            # 'filename': BASE_DIR / "logs/meeting.log",  # 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定义了一个名为django的日志器
            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
    }
}


日志框架的组成元素

一份 Python logging 配置有下面四个部分组成:

  • formatters -- 日志记录最终是需要以文本来呈现的。Formatter 描述了文本的格式。
  • filters -- 在日志记录从 logger 传到 handler 的过程中,使用 Filter 来做额外的控制。
  • handlers -- Handler 是决定如何处理 logger 中每一条消息的引擎。它描述特定的日志行为,比如把消息输出到屏幕、文件或网络 socket。
  • loggers -- logger 是日志系统的入口。每个 logger 都是命名了的 bucket, 消息写入 bucket 以便进一步处理。


formatters

日志记录最终是需要以文本来呈现的。Formatter 描述了文本的格式。一个 formatter 通常由包含 LogRecord attributes 的 Python 格式化字符串组成,不过你也可以为特定的格式来配置自定义的 formatter。

'formatters': {
    'verbose': {
        'format': '{asctime} {module}.{funcName} {lineno:3} {levelname:7} => {message}',
        'style': '{',
    },
    'simple': {
        'format': "{levelname} -- {message}",
        'style': '{',
    }
},

Formatter就是log格式化的样式。 这里定义了两种formatter,那就是verbosesimple


format键

比较常用的:

  • {asctime}: 默认的日期与时间,默认形式大概是2021-03-11 17:17:25,223。这个形式可以通过datefmt修改。
  • {module}:模块名。
  • {funcName}: 函数名。
  • {lineno:3}: 行号,至少显示3个字符,少则补空格。
  • {levelname:7}: log级别。
  • {message}: log内容。

其他的:

  • {created}: 创建日志记录的时间。
  • {filename}: 文件名。
  • {msecs}: 创建日志记录时的毫秒部分。
  • {name}: formatter的名称。
  • {pathname}: 源文件的完整路径名。
  • {process}: process ID。
  • {processName}: process 名称。
  • {thread}: 线程ID。
  • {threadName}: 线程名称。
  • {relativeCreated}: 与加载记录模块的时间相比,创建日志记录的时间在毫秒内。


style键

style的选择有{, %, $

  • {: 是指{asctime}这种形式
  • %: 是指%(asctime)s这种形式
  • $: 是指$asctime或$(asctime)这种形式


datefmt键

Django自带模块默认的格式化形式,打印出来,日期时间的形式大致是这样:16/Nov/2018 09:03:22。 相当于设置了下面的datefmt

 'formatters': {
        'default': {
            ...
            'style': '{',
            'datefmt': '%d/%b/%Y %H:%M:%S',
        },
    },


handler

Handler 是决定如何处理 logger 中每一条消息的引擎。它描述特定的日志行为,比如把消息输出到屏幕、文件或网络 socket。

和 logger 一样,handler 也有日志级别的概念。如果一条日志记录的级别不匹配或者低于 handler 的日志级别,对应的消息会被 handler 忽略。

一个 logger 可以有多个 handler,每一个 handler 可以有不同的日志级别。这样就可以根据消息的重要性不同,来提供不同格式的输出。例如,你可以添加一个 handler 把 ERRORCRITICAL 消息发到寻呼机,再添加另一个 handler 把所有的消息(包括 ERRORCRITICAL 消息)保存到文件里以便日后分析。

'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'formatter': 'verbose',
            'filename': '/tmp/django.log',
            'maxBytes': 4194304,  # 4 MB
            'backupCount': 10,
            'level': 'DEBUG',
        },
    },

consolefile是处理器的名称


class

class是指定处理log的类,在Python里logging.handlers中。

可选class列出如下,详见Useful Handlers

class 功能
StreamHandler 输出到Stream。通常用来打印到标准输出。
FileHandler 打印到文件。
NullHandler 不格式化也不打印。主要是为了避免No handlers could be found for logger XXX的设计。
WatchedFileHandler 自动重开log文件,配合别的会自动切分的log文件使用。
RotatingFileHandler 自动按大小切分的log文件。
TimedRotatingFileHandler 按时间自动切分的log文件。
SocketHandler 向Socket打log,基于TCP协议。
DatagramHandler 向Socket打log,基于UDP协议。
SysLogHandler 在Unix-like系统打印到remote或local的Unix syslog。
NTEventLogHandler 在Windows系统打印到微软的event log。
SMTPHandler 通过email发送log。
MemoryHandler 打印到内存buffer。
HTTPHandler 通过HTTP协议向服务器发送log。
QueueHandler 打log到Queue中,适合多进程(multiprocessing)场景。

这里主要选择了StreamHandler和RotatingFileHandler。 既能在./manage.py runserver时打印在前台,又能在部署后打印到文件,方便前期开发和后期运维。

此外,Django额外定义了一个handler——AdminEmailHandler,向管理员发送邮件。

    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'email_backend': 'django.core.mail.backends.filebased.EmailBackend',
            'include_html': True,
        }
    },

有需要可以添加,但要确保邮件SMTP服务器的通畅。


formatter

formatter是指定一个格式化方式,也就是前面formatters定义的那些。 这里选择了前面定义的verboase


level

level是选择log的最低等级。 由低到高,列出如下,需要按需选择。

  • DEBUG: Low level system information for debugging purposes.
  • INFO: General system information.
  • WARNING: Information describing a minor problem that has occurred.
  • ERROR: Information describing a major problem that has occurred.
  • CRITICAL: Information describing a critical problem that has occurred.


loggers

logger 是日志系统的入口。每个 logger 都是命名了的 bucket, 消息写入 bucket 以便进一步处理。

每一条写入 logger 的消息都是一条 日志记录。每一条日志记录也包含 日志级别,代表对应消息的严重程度。日志记录还包含有用的元数据,来描述被记录了日志的事件细节,例如堆栈跟踪或者错误码。

当 logger 处理一条消息时,会将自己的日志级别和这条消息的日志级别做对比。如果消息的日志级别匹配或者高于 logger 的日志级别,它就会被进一步处理。否则这条消息就会被忽略掉。

当 logger 确定了一条消息需要处理之后,会把它传给 Handler

    'loggers': {
        '': {
            'handlers': ['console', 'file'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
        },
        'django': {
            'handlers': ['console', 'file'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
            'propagate': False,
        },
    },

loggers模块,最重要的是选择设置哪些logger。 这里设置了''(root)和'django'。 前者是为了方便地使用logging,所以设了root的logger,这也是默认的logger。 后者是打印所有Django自身的logger。

propagate是设定是否向父logger传播信息。 对root来说,这一条可有可无。 但在本例中,root被使用了,所以'django'logger必须设置为'propagate': False,,否则会打印两次。

level有如下几个级别:

  • DEBUG:排查故障时使用的低级别系统信息
  • INFO:一般的系统信息
  • WARNING:描述系统发生了一些小问题的信息
  • ERROR:描述系统发生了大问题的信息
  • CRITICAL:描述系统发生严重问题的信息

Django额外提供的loggers扩展如下:

  • django
  • django.request
  • django.server
  • django.template
  • django.db.backends
  • django.security.*
    • django.security.DisallowedHost
    • django.security.SuspiciousOperation
    • django.security.SuspiciousOperation
    • django.security.DisallowedHost
  • django.db.backends.schema


filters

在日志记录从 logger 传到 handler 的过程中,使用 Filter 来做额外的控制。

默认情况下,只要级别匹配,任何日志消息都会被处理。不过,也可以通过添加 filter 来给日志处理的过程增加额外条件。例如,可以添加一个 filter 只允许某个特定来源的 ERROR 消息输出。

Filter 还被用来在日志输出之前对日志记录做修改。例如,可以写一个 filter,当满足一定条件时,把日志记录从 ERROR 降到 WARNING 级别。

Filter 在 logger 和 handler 中都可以添加;多个 filter 可以链接起来使用,来做多重过滤操作。

 'filters': {  # 对日志进行过滤
        'require_debug_true': {  # django在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },


CallbackFilter

这个过滤器接受一个回调函数(它应该接受一个单一的参数,即要记录的记录),并对每个通过过滤器的记录进行调用。如果回调函数返回 False,则不会对该记录进行处理。

例如,要从管理员邮件中过滤掉 UnreadablePostError (当用户取消上传时引发),你可以创建一个过滤函数:

from django.http import UnreadablePostError

def skip_unreadable_post(record):
    if record.exc_info:
        exc_type, exc_value = record.exc_info[:2]
        if isinstance(exc_value, UnreadablePostError):
            return False
    return True

然后将其添加到你的日志记录配置中:

'filters': {
    'skip_unreadable_posts': {
        '()': 'django.utils.log.CallbackFilter',
        'callback': skip_unreadable_post,
    }
},
'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'filters': ['skip_unreadable_posts'],
        'class': 'django.utils.log.AdminEmailHandler'
    }
},


RequireDebugFalse

只有当 settings.DEBUG 为 False 时,该过滤器才会传递记录。

该过滤器在默认的 logging 配置中使用如下,以确保 AdminEmailHandler 只在 DEBUGFalse 时向管理员发送错误邮件:

'filters': {
    'require_debug_false': {
        '()': 'django.utils.log.RequireDebugFalse',
    }
},
'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'django.utils.log.AdminEmailHandler'
    }
},


RequireDebugTrue

该过滤器类似于 RequireDebugFalse,但只有当 DEBUGTrue 时才会传递记录。



  • 标签云

  • 支付宝扫码支持一下

  • 微信扫码支持一下



基于Nginx+Supervisord+uWSGI+Django1.11.1+Python3.6.5构建

版权所有 © 2020-2021 August Rush

京ICP备20007446号-1 & 豫公网安备 41100202000460号

网站地图 & RSS | Feed