Django日志配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(pathname)s %(module)s %(lineno)s %(process)d %(thread)d %(message)s'
        }
    },
    'loggers': {
        'django': {
            'handlers': ['default'],
            'propagate': True,
            'level': 'DEBUG',
            'filters': ['special']
        }
    },
    'handlers': {
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/var/logs/django/default.log',
            'maxBytes': 1024 * 1024 * 5,
            'backupCount': 5,
            'formatter': 'verbose',
            'filters': ['special']
        }
    },
    'filters': {  # 过滤器
        'special': {  # 使用自定义的web.my_logging.ContextFilter,别名special,可以接受其他的参数
            '()': 'web.my_logging.ContextFilter'
        }
    },
}

配置分析说明

version

保留字。

disable_existing_loggers

是否禁用已经存在的logger实例。

  • 如果LOGGING 中的disable_existing_loggers 键为True(默认值),那么默认配置中的所有logger 都将禁用。

  • Logger 的禁用与删除不同;logger 仍然存在,但是将默默丢弃任何传递给它的信息,也不会传播给上一级logger。所以,你应该非常小心使用'disable_existing_loggers': True;它可能不是你想要的。你可以设置disable_existing_loggersFalse,并重新定义部分或所有的默认loggers;或者你可以设置LOGGING_CONFIGNone,并 自己处理logging 配置

  • Logging 的配置属于Django setup() 函数的一部分。所以,你可以肯定在你的项目代码中logger 是永远可用的。

formatters

定义输出的日志格式。 常用的格式化属性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
%(name)s Logger的名字
%(levelname)s 文本形式的日志级别
%(message)s 用户输出的消息
%(asctime)s 字符串形式的当前时间。默认格式是 2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(levelno)s 数字形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s  调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有

其他格式化属性请参 LogRecord attributes

handlers

处理器。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
'handlers': {
    'default': {
        'level': 'DEBUG',
        'class': 'logging.handlers.RotatingFileHandler',
        'filename': '/var/logs/django/default.log',
        'maxBytes': 1024 * 1024 * 5,
        'backupCount': 5,
        'formatter': 'verbose',
        'filters': ['special']
    }
}
  • key为处理器名,values为处理器配置。

  • level:日志处理级别。

  • formatter: 这个参数对应formatters

  • filters: 对应后面的 filters

  • class:处理类。常用的有:NullHandler(无任何操作,相当于丢弃日志),FileHandler(输出到磁盘文件)等。其他处理类请看 https://docs.python.org/3/library/logging.handlers.html

  • filename:记录日志的文件名。

  • maxBytes:文件最大字节数。

  • backupCount:最大扩展数。这个是和maxBytes一起使用的。例如当日志文件 pro.log 达到最大字节数,那么就会扩展一个文件pro.log.1文件继续记录日志, 依次扩展,达到backupCount的设定值,例如为5,那么到pro.log.5后,后面的日志会再次记入 pro.log文件,相当于轮询。

loggers

定义logger实例。

1
2
3
4
5
6
7
8
'loggers': {
    'django': {
        'handlers': ['default'],
        'propagate': True,
        'level': 'DEBUG',
        'filters': ['special']
    }
}
  • handlers:对应的handles对象列表。

  • level:logger实例输出的日志级别,但是这个级别并不是最终输出日志的级别,还有根据handlers的级别进行判断,两个level中取级别高的。DEBUG < INFO < WARNING < ERROR < CRITICAL

  • propagate:日志是否向上级传递。True 向上级传,False 不向上级传。默认为True。

  • filters: 对应后面的 filters。 更详细说明请参照:https://docs.python.org/3/library/logging.html#logrecord-attributes

filters

  • 过滤器。过滤器用来对传递给 Logger 或者 Handler 的日志信息提供附加的控制。
  • 默认情况下,所有满足级别的日志信息都会被处理,但是我们可以通过 filter 来过滤掉 CRITICAL 级别的日志,然后仅允许 ERROR 级别的日志通过。
  • filter 也可以被用来对前面被忽略掉的日志进行修改,例如,我们可以在一定条件下将 ERROR 日志降级为 WARNING 日志。
  • 过滤器可以安装在 logger 或者 handler 上,多个过滤器可以形成一个链来接连产生作用。

配置:

1
2
3
4
5
6
'filters': {  # 过滤器
    'special': {  
    # 使用自定义的web.my_logging.ContextFilter,别名special,可以接受其他的参数
        '()': 'web.my_logging.ContextFilter'
    }
}

自定义Filter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import logging
from random import choice


class ContextFilter(logging.Filter):
    """
    This is a filter which injects contextual information into the log.

    Rather than use actual contextual information, we just use random
    data in this demo.
    """

    USERS = ['jim', 'fred', 'sheila']
    IPS = ['123.231.231.123', '127.0.0.1', '192.168.0.1']

    def filter(self, record):
        record.ip = choice(ContextFilter.IPS)
        record.user = choice(ContextFilter.USERS)
        return True

可以不定义类,直接定义函数,返回True表示