Django 之日志配置
日志作为服务的,排查故障分析性能及问题的重要“帮手”,是服务必不可少的。
配置日志
定义日志记录器
定义了三个日志记录器,分别针对Django、自定义应用程序和自定义库。每个日志记录器都有不同的日志级别和处理器,例如控制台和文件处理器。
Django日志记录器的级别为INFO,意味着只有INFO级别及以上的日志消息才会被记录。自定义应用程序的日志记录器的级别为ERROR,意味着只有ERROR级别及以上的日志消息才会被记录。
自定义库的日志记录器的级别为WARNING,意味着只有WARNING级别及以上的日志消息才会被记录。
### ### myproject/myproject/settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
#'level': 'INFO' 表示只记录INFO级别及以上的日志消息,不包含DEBUG级别的消息
#'level': 'DEBUG',记录所有级别的日志消息,包括DEBUG、INFO、WARNING、ERROR和CRITICAL
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/git/Python/myproject/myapp/myapp.log',
'encoding': 'utf-8',
},
},
'loggers': {
'myapp_info': {
'handlers': ['file'],
'level': 'INFO',
},
'myapp_error': {
'handlers': ['file'],
'level': 'ERROR',
},
'myapp_warn': {
'handlers': ['file'],
'level': 'WARNING',
},
'myapp_critical': {
'handlers': ['file'],
'level': 'CRITICAL',
},
'myapp_debug': {
'handlers': ['file'],
'level': 'DEBUG',
},
},
}
定义视图配置日志
设置日志等级
- logger.setLevel(logging.INFO)
-
- 表示将控制台处理器的日志记录级别设置为 INFO。这意味着,只有 INFO 级别及以上的日志消息才会被发送到控制台进行输出。
- 更低级别的日志消息,例如 DEBUG 级别的消息,将被忽略,不会在控制台上输出。
- 因此,只有 INFO、WARNING、ERROR 和 CRITICAL 级别的日志消息会被记录并输出到控制台。
- logger.setLevel(logging.DEBUG)
-
- 将文件处理器的日志记录级别设置为 DEBUG,这样所有级别的日志消息都会被记录到文件中。
- 将控制台处理器的日志记录级别也设置为 DEBUG,这样所有级别的日志消息都会被输出到控制台中
### ### myproject/myapp/views.py
import logging
# 创建一个名为myapp的日志记录器
# 使用了名为logger的默认记录器来记录日志消息
logger = logging.getLogger('myapp1')
logger.setLevel(logging.INFO)
# 创建一个控制台处理程序,并将其添加到日志记录器中
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(status)s: %(message)s')
# console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s')
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
# 将默认记录器的处理器设置为file,以确保日志消息被写入文件
# 日志文件输出为乱码,可能是因为文件的编码格式不正确。你可以尝试在创建FileHandler对象时指定正确的编码格式
# 添加了一个名为file_handler的处理器,并将其级别设置为INFO。我们还将处理器的格式化程序设置为与handler相同的格式化程序。
# 然后,我们将处理器添加到默认记录器中,以确保日志消息被写入文件
# 创建一个文件处理程序,并将其添加到日志记录器中
file_handler = logging.FileHandler('/git/Python/myproject/myapp/myapp.log', encoding='utf-8')
file_handler.setLevel(logging.INFO)
file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(status)s: %(message)s')
# file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s')
# file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
@csrf_exempt
def config_form(request):
...
if request.method == 'POST':
#首先在settings.py文件中配置了两个日志记录器:一个是Django日志记录器,级别为INFO;另一个是自定义应用程序的日志记录器,级别也为INFO。然后,在我们的视图函数中,我们使用自定义应用程序的日志记录器来记录一条日志消息。这条消息将被记录到控制台和文件中,因为我们在日志处理器中指定了这两个处理器
try:
logger.info('提交表单,重定向到/myapp/config/success/', extra={'status': 200})
except Exception as e:
logger.error('跳转失败: %s', str(e), extra={'status': 500})
#可测试日志等级示例
# logger.debug('这是一条DEBUG级别的日志消息')
# logger.info('这是一条INFO级别的日志消息')
# logger.warning('这是一条WARNING级别的日志消息')
# logger.error('这是一条ERROR级别的日志消息')
# logger.critical('这是一条CRITICAL级别的日志消息')
# return HttpResponse('这是响应消息')
# 重定向到成功页面
return HttpResponseRedirect('/myapp/config/success/', content)
else:
#首先在settings.py文件中配置了两个日志记录器:一个是Django日志记录器,级别为INFO;另一个是自定义应用程序的日志记录器,级别也为INFO。
# 然后,在我们的视图函数中,我们使用自定义应用程序的日志记录器来记录一条日志消息。
# 这条消息将被记录到控制台和文件中,因为我们在日志处理器中指定了这两个处理器。最后,我们使用render函数来渲染模板并返回响应。
try:
if logger.isEnabledFor(logging.INFO):
logger.info('跳转显示表单页面', extra={'status': 200})
except Exception as e:
if logger.isEnabledFor(logging.ERROR):
logger.error('跳转显示表单页面失败: %s', str(e), extra={'status': 500})
return render(request, 'config_form.html', context)
@validate_header
def config_success(request):
...
try:
if logger.isEnabledFor(logging.INFO):
logger.info('重定向到/myapp/config/success/,显示配置页面', extra={'status': 200})
except Exception as e:
if logger.isEnabledFor(logging.ERROR):
logger.error('重定向到显示配置页面失败: %s', str(e), extra={'status': 500})
# 第一个语句使用了extra参数,它是一个字典,可以用来传递额外的信息给日志记录器。在这里,它被用来传递状态码信息。当使用extra参数时,需要在日志格式化字符串中加入%(key)s占位符来表示额外信息的键名。
# 第二个语句直接使用了关键字参数来传递状态码信息。这种方式不需要在日志格式化字符串中加入额外信息的占位符。
# 总的来说,使用extra参数可以传递更多的额外信息,而使用关键字参数则更为简单直接。
# logger.error('重定向到显示配置页面失败', extra={'status': 500})
# logger.error('重定向到显示配置页面失败', status=401)
return response
访问查看日志
http://localhost:8080/myapp/config
异常访问失败日志
正常访问日志
日志记录
2023-08-07 23:08:02,651 - myapp - DEBUG - middleware - 401: Invalid request header,未经授权的访问
2023-08-07 23:08:02,695 - myapp - DEBUG - middleware - 401: Invalid request header,未经授权的访问
2023-08-07 23:08:16,785 - myapp - DEBUG - middleware - 401: Invalid request header,未经授权的访问
2023-08-07 23:08:16,825 - myapp - DEBUG - middleware - 401: Invalid request header,未经授权的访问
2023-08-07 23:10:24,872 - myapp1 - INFO - views - 200: 重定向到/myapp/config/success/,显示配置页面
2023-08-07 23:10:24,874 - myapp - INFO - middleware - 200: 浏览器验证成功
2023-08-07 23:10:50,017 - myapp1 - INFO - views - 200: 跳转显示表单页面
2023-08-07 23:11:16,137 - myapp1 - INFO - views - 200: 提交表单,重定向到/myapp/config/success/
2023-08-07 23:11:16,190 - myapp1 - INFO - views - 200: 重定向到/myapp/config/success/,显示配置页面
2023-08-07 23:11:16,191 - myapp - INFO - middleware - 200: 浏览器验证成功
2023-08-07 23:11:18,304 - myapp1 - INFO - views - 200: 跳转显示表单页面