python的日志模块:logging;django的日志系统

Posted 沧海一粟,何以久远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python的日志模块:logging;django的日志系统相关的知识,希望对你有一定的参考价值。

 Django的log,主要是复用Python标准库中的logging模块,在settings.py中进行配置 

 

源代码

 

1、__init__.py包含以下类:

StreamHandler
Formatter
%(name)s            Name of the logger (logging channel)
    %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
                        WARNING, ERROR, CRITICAL)
    %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
                        "WARNING", "ERROR", "CRITICAL")
    %(pathname)s        Full pathname of the source file where the logging
                        call was issued (if available)
    %(filename)s        Filename portion of pathname
    %(module)s          Module (name portion of filename)
    %(lineno)d          Source line number where the logging call was issued
                        (if available)
    %(funcName)s        Function name
    %(created)f         Time when the LogRecord was created (time.time()
                        return value)
    %(asctime)s         Textual time when the LogRecord was created
    %(msecs)d           Millisecond portion of the creation time
    %(relativeCreated)d Time in milliseconds when the LogRecord was created,
                        relative to the time the logging module was loaded
                        (typically at application startup time)
    %(thread)d          Thread ID (if available)
    %(threadName)s      Thread name (if available)
    %(process)d         Process ID (if available)
    %(message)s         The result of record.getMessage(), computed just as
                        the record is emitted

 

FileHandler
日志级别:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

 

2、config.py

3、handlers.py包含以下class

TimedRotatingFileHandler:可以根据时间自动生成新的日志文件
HTTPHandler:
RotatingFileHandler:可以根据日志大小自动生成新的日志文件

日志处理类:

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)场景。

 

 

 

分层传递日志

a.b.c.d会把日志传到a.b.c;a.b.c会把日志传到a.b;a.b会把日志传到a

写到相应层级日志的方法是,在需要记录日志的文件地方,使用如下函数,里面根据需要填写相应的层级:logger = logging.getLogger(\'a.b.c\')

 

 

 

Django日志示例:

配置:


# https://docs.djangoproject.com/zh-hans/2.1/topics/logging/
LOGGING = {
\'version\': 1,
\'disable_existing_loggers\': False,
\'formatters\': {
\'verbose\': {
# 后缀d表示数据格式是整数,s表示数据格式是字符串
\'format\': \'[%(levelname)s] [%(asctime)s] [%(module)s] %(filename)s:%(lineno)d %(funcName)s \'
\'%(processName)s:[%(process)d] %(threadName)s:[%(thread)d] %(message)s\'
# \'format\': \'{levelname} {asctime} {module} {process:d} {thread:d} {message}\',
# \'style\': \'{\',
},
\'simple\': {
\'format\': \'[%(levelname)s] [%(asctime)s] %(message)s\',
# \'format\': \'[%(asctime)s] %(message)s\',
# 后缀d表示数据格式是整数,s表示数据格式是字符串
# \'format\': \'[%(levelname)s] [%(asctime)s] [%(module)s] %(filename)s:%(lineno)d %(funcName)s \'
# \'%(processName)s:[%(process)d] %(threadName)s:[%(thread)d] %(message)s\',
# \'style\': \'{\',
},
\'standard\': {
# \'format\': \'%(asctime)s [%(levelname)s] %(name)s: %(message)s\',
\'format\': \'{asctime} [{levelname:6}] {name:30}: {message}\',
# 设置上面格式样式;{lineno:3}是行号,至少显示3个字符,少则补空格
# 这里style选择{,是指{asctime}这种形式。
# 如果选择%,则是%(asctime)s这种形式。
# 还有一种选择,是$,是$asctime或${asctime}这种形式。
\'style\': \'{\',
# 设置时间格式
\'datefmt\': \'%Y-%m-%d %H:%M:%S\',
},
\'operation\': {
\'format\': \'%(message)s\'
}
},
# \'filters\': {
# # \'special\': {
# # \'()\': \'erebus.logging.SpecialFilter\',
# # \'foo\': \'bar\',
# # },
# \'require_debug_true\': {
# \'()\': \'django.utils.log.RequireDebugTrue\',
# },
# },

# Handler是决定如何处理logger中每一条消息的引擎。它描述特定的日志行为,比如把消息输出到屏幕、文件或网络socket。
# 和 logger 一样,handler 也有日志级别的概念。如果一条日志记录的级别不匹配或者低于 handler 的日志级别,
# 对应的消息会被 handler 忽略。
\'handlers\': {
\'default\': {
\'level\': \'DEBUG\',
\'class\': \'logging.handlers.RotatingFileHandler\',
\'filename\': \'logs/default.log\',
# \'maxBytes\': 1024*1024*5, # 5 MB
\'maxBytes\': 1024*5, # 5 KB
\'backupCount\': 5,
\'formatter\': \'standard\',
},
\'output_to_file\': {
\'level\': \'INFO\', # 忽略debug信息
\'class\': \'logging.FileHandler\',
\'filename\': \'{}/{}.log\'.format(BASE_LOG_DIR, conf.get(\'log\', \'name\')),
\'formatter\': \'simple\' if DEBUG else \'verbose\',
\'encoding\': \'utf8\',
},
\'console_log\': {
\'level\': \'DEBUG\', # 所有的日志都会被输出到console
# \'filters\': [\'require_debug_true\'],
\'class\': \'logging.StreamHandler\',
\'formatter\': \'simple\'
},
\'operation\': {
\'level\': \'INFO\',
\'class\': \'logging.FileHandler\',
\'filename\': \'{}/{}.log\'.format(BASE_LOG_DIR, \'operation\'),
\'formatter\': \'operation\',
\'encoding\': \'utf8\'
}
# \'mail_admins\': {
# \'level\': \'ERROR\',
# \'class\': \'django.utils.log.AdminEmailHandler\',
# # \'filters\': [\'special\']
# }
},
\'loggers\': {
# 可以通过使用空字符串:\'\'来设置\'catch all\' logger
# 在以下设置中,将所有日志事件保存到logs/default.log,但配置为\'propagate\': False日志事件除外,
# 这些日志事件将保存到相应的日志文件中,比如本文的logs/erebus.log。
\'\': {
\'handlers\': [\'default\'],
\'level\': \'DEBUG\',
\'propagate\': True
},
# 名字随意起,用时,使用logger = logging.getLogger(conf.get(\'log\', \'name\'))获取,传到相应的loggers里就可以
conf.get(\'log\', \'name\'): {
\'handlers\': [\'output_to_file\', \'console_log\'],
# 当 logger 处理一条消息时,会将自己的日志级别和这条消息的日志级别做对比。
# 如果消息的日志级别匹配或者高于 logger 的日志级别,它就会被进一步处理。
# 否则这条消息就会被忽略掉。当 logger 确定了一条消息需要处理之后,会把它传给 Handler。

# \'level\': \'INFO\', # debug日志会被忽略
\'level\': \'DEBUG\', # 所有的日志都会被处理
\'propagate\': False, # 值为False,表示日志不会传到上个层级,自然也不会传到default.log里
},
# 使用logger = logging.getLogger(\'django.request\'), logger.info(\'info\'),
# 可以把日志输出到\'handlers\': [\'output_to_file\', \'console_log\'],
# 这里的名字不能随便取,命名为django、django.request才会捕获django的日志
conf.get(\'log\', \'name\')+\'.request\': {
\'handlers\': [\'output_to_file\', \'console_log\'],
\'level\': \'DEBUG\',
# 会把日志向django.request的上层django传播
\'propagate\': True,
},
# \'erebus.custom\': {
# \'handlers\': [\'console\', \'mail_admins\'],
# \'level\': \'INFO\',
# # \'filters\': [\'special\']
# },
\'operation\': {
\'handlers\': [\'operation\'],
\'level\': \'INFO\',
# \'propagate\': True,
}
}
}
 

使用日志

logger = logging.getLogger(\'django\')
def hello(request):
content = {\'hello\': \'hello world\'}
# return HttpResponse("hello world")
logger.error(\'test\')
logger.error(\'访问hello界面:error\')
logger.debug(\'访问hello界面:debug\')
logger.info(\'访问hello界面:info\')
logger.warning(\'访问hello界面:warning\')
logger.critical(\'访问hello界面:critical\')
logger.log(40, \'测试\')
logger.exception(\'ceshi\')
return render(request, \'hello.html\', content)

 

时间格式:

Directive    Meaning Notes
%a    Locale’s abbreviated weekday name.
%A    Locale’s full weekday name.
%b    Locale’s abbreviated month name.
%B    Locale’s full month name.
%c    Locale’s appropriate date and time representation.
%d    Day of the month as a decimal number [01,31].
%H    Hour (24-hour clock) as a decimal number [00,23].
%I    Hour (12-hour clock) as a decimal number [01,12].
%j    Day of the year as a decimal number [001,366].
%m    Month as a decimal number [01,12].
%M    Minute as a decimal number [00,59].
%p    Locale’s equivalent of either AM or PM. (1)
%S    Second as a decimal number [00,61]. (2)
%U    Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. (3)
%w    Weekday as a decimal number [0(Sunday),6].
%W    Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (3)
%x    Locale’s appropriate date representation.
%X    Locale’s appropriate time representation.
%y    Year without century as a decimal number [00,99].
%Y    Year with century as a decimal number.
%z    Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59].
%Z    Time zone name (no characters if no time zone exists).
%%    A literal \'%\' character.

 

Django内置的loggers:

Django provides several built-in loggers.

djangodjango.request、django.serverdjango.templatedjango.db.backends、django.security.*、django.security.csrf、django.db.backends.schema

 

日志输出时区问题

当设置日志时区为utc时,中国时区的日志输出会相差8个小时

# 使用utc时间,前端根据时区自动显示当地时间
USE_TZ = True
TIME_ZONE = \'UTC\'

USE_I18N = True

USE_L10N = True

这是需要修改日志模块,在settings配置里添加:

def beijing(sec, what):
    beijing_time = datetime.datetime.now() + datetime.timedelta(hours=8)
    return beijing_time.timetuple()


logging.Formatter.converter = beijing

 

参考:

1、https://codeday.me/bug/20170630/32009.html

2、http://note.qidong.name/2018/11/django-logging/

3、https://docs.djangoproject.com/zh-hans/2.1/topics/logging/#django-request

4、https://blog.csdn.net/u010099080/article/details/85944741

以上是关于python的日志模块:logging;django的日志系统的主要内容,如果未能解决你的问题,请参考以下文章

Python日志输出——logging模块

Python入门之logging日志模块以及多进程日志

python---Logging日志模块

Python之日志处理 logging模块

Python之日志处理(logging模块)

Python--logging日志模块