首页 > 编程语言 >Python logging 通用模板

Python logging 通用模板

时间:2023-06-20 10:37:38浏览次数:36  
标签:info logging level Python request handler 日志 id 模板

# logger.py

import logging
import socket
import threading
import uuid
from logging.config import dictConfig

local = threading.local()


# 定义一个类,用于实现自定义的过滤器功能
class RequestFilter(logging.Filter):
    def filter(self, record):
        get_req_id()
        request_id = getattr(local, "request_id", None)  # 获取当前线程的请求ID
        ip = getattr(local, "ip", None)  # 获取当前线程的IP

        record.request_id = request_id  # 将请求ID添加到日志记录对象的extra属性中
        record.ip = ip  # 将IP添加到日志记录对象的extra属性中
        return True  # 返回True表示该日志记录可以被处理


def generate_uid():
    uid = str(uuid.uuid4())[-8:]
    th_name = threading.currentThread().name
    _uid = f'{th_name}_{uid}'
    # _uid = str(uuid.uuid4())
    return _uid.replace('-', '_').lower()


def get_req_id():
    if hasattr(local, 'request_id'):
        return local.request_id
    else:
        # local.request_id = str(uuid.uuid4()).replace('-', '_')  # 随机生成一个请求ID,并存储在本地变量中, 替换下划线方便复制
        local.request_id = generate_uid()  # 随机生成一个请求ID,并存储在本地变量中
        local.ip = socket.gethostbyname(socket.gethostname())  # 获取本机IP地址,并存储在本地变量中
        return local.request_id


LOGGING_CONFIG = {
    'version': 1,  # 版本号,必须为1
    'disable_existing_loggers': False,  # 是否禁用已存在的logger对象
    'filters': {  # 过滤器对象,用于对日志记录进行过滤操作
        'request_filter': {  # 名称为request_filter 的过滤器
            '()': RequestFilter  # 使用自定义的RequestFilter 类来创建过滤器对象
        }
    },

    'formatters': {  # 格式化器对象,用于定义日志的格式
        'console_fmt': {  # 名称为info的格式化器
            'format': '[{asctime}] [{request_id}] [{module}.{funcName}:{lineno}] [{levelname:^8s}] {message}',
            'style': '{',
        },
        'info': {  # 名称为info的格式化器
            'format': '[{asctime}] [{ip}] [{request_id}] [{module}.{funcName}:{lineno}] [{levelname:^8s}] [{message}]',
            'style': '{',
        },
        'error': {  # 名称为error的格式化器
            'format': '[{asctime}] [{ip}] [{request_id}] [{module}.{funcName}:{lineno}] [{levelname:^8s}] [{message}]',
            'style': '{',

        }
    },
    'handlers': {  # 处理器对象,用于将日志记录发送到不同的目的地
        'info_rotating_file_handler': {  # 名称为info_rotating_file_handler的处理器,使用RotatingFileHandler类创建
            'level': "INFO",  # 处理INFO及以上级别的日志记录(根据参数level决定)
            'formatter': 'info',  # 使用info格式化器来格式化日志记录
            'class': 'logging.handlers.TimedRotatingFileHandler',  # 使用TimedRotatingFileHandler类来创建处理器对象
            'filename': "flask.log",  # 将日志记录写入path指定的文件中(根据参数path决定)
            'when': 'midnight',  # 在每天凌晨进行日志切割
            'backupCount': 10,  # 保留最近10天的日志备份文件
            'filters': ['request_filter'],  # 使用request_filter过滤器来过滤日志记录
            # 'filemode': 'a'
        },
        'error_file_handler': {  # 名称为error_file_handler的处理器,使用FileHandler类创建
            'level': 'ERROR',  # 处理ERROR及以上级别的日志记录(根据参数level决定)
            'formatter': 'error',  # 使用error格式化器来格式化日志记录
            'class': 'logging.FileHandler',  # 使用FileHandler类来创建处理器对象
            'filename': 'flask.log',  # 将日志记录写入path指定的文件中,并加上.err后缀(根据参数path决定)
            'filters': ['request_filter'],  # 使用request_filter过滤器来过滤日志记录
            # 'mode': 'a'
        },
        "console_handler": {  # 名称为console_handler的处理器,使用StreamHandler类创建
            "level": "DEBUG",  # 处理DEBUG及以上级别的日志记录
            "formatter": "console_fmt",  # 使用info格式化器来格式化日志记录
            "class": "logging.StreamHandler",  # 使用StreamHandler类来创建处理器对象
            "stream": "ext://sys.stdout",  # 将日志记录输出到标准输出流中
            'filters': ['request_filter']  #
        },

        'wsgi': {  # 名称为info_rotating_file_handler的处理器,使用RotatingFileHandler类创建
            'level': "DEBUG",  # 处理INFO及以上级别的日志记录(根据参数level决定)
            'formatter': 'info',  # 使用info格式化器来格式化日志记录
            'class': 'logging.handlers.TimedRotatingFileHandler',  # 使用TimedRotatingFileHandler类来创建处理器对象
            'filename': "wsgi.log",  # 将日志记录写入path指定的文件中(根据参数path决定)
            'when': 'midnight',  # 在每天凌晨进行日志切割
            'backupCount': 10,  # 保留最近10天的日志备份文件
            'filters': ['request_filter'],  # 使用request_filter过滤器来过滤日志记录
            # 'filemode': 'a'
        },
        # 'wsgi': {
        #     'class': 'logging.FileHandler',  # 使用FileHandler类来创建处理器对象
        #     "level": "DEBUG",  # 处理DEBUG及以上级别的日志记录
        #     # 'stream': 'ext://flask.logging.wsgi_errors_stream',
        #     'formatter': 'info',
        #     'filename': 'wsgi.log',
        #     'filters': ['request_filter']  #
        # },
    },
    'loggers': {  # 日志收集器对象,用于管理不同的logger对象
        # "root": {  # 名称为name指定的logger对象(根据参数name决定)
        #     'handlers': ['info_rotating_file_handler', 'error_file_handler', 'console_handler', 'wsgi'],
        #     # 使用两个处理器来处理该logger对象的日志记录
        #     'level': "DEBUG",  # 设置该logger对象的级别(根据参数level决定)
        #     'propagate': False  # 设置该logger对象是否向上级传递,默认为False,表示不传递
        # },
        'sqlalchemy.engine': {  # 支持对sqlalchemy日志收集
            'level': "DEBUG",
            'handlers': ['info_rotating_file_handler', 'error_file_handler', 'console_handler'],
        }
    },
    "root": {  # 名称为name指定的logger对象(根据参数name决定)
        'handlers': ['info_rotating_file_handler', 'error_file_handler', 'console_handler', 'wsgi'],
        # 'handlers': ['info_rotating_file_handler', 'error_file_handler', 'console_handler'],
        # 使用两个处理器来处理该logger对象的日志记录
        'level': "DEBUG",  # 设置该logger对象的级别(根据参数level决定)
        'propagate': False  # 设置该logger对象是否向上级传递,默认为False,表示不传递
    },
}

dictConfig(LOGGING_CONFIG)  # 根据字典配置信息,配置logger对象

log = logging.getLogger()

if __name__ == '__main__':
    def log_test():
        log.info('hello world')
        import time
        def worker(num):
            log.info('Worker %d started' % num)
            time.sleep(1)
            log.info('Worker %d finished' % num)

        for i in range(5):
            t = threading.Thread(target=worker, args=(i,))
            t.start()
        log.info('done')


    log_test()

标签:info,logging,level,Python,request,handler,日志,id,模板
From: https://www.cnblogs.com/l806760/p/17492918.html

相关文章

  • 一文掌握Python多线程与多进程
    Python的多线程和多进程一、简介并发是今天计算机编程中的一项重要能力,尤其是在面对需要大量计算或I/O操作的任务时。Python提供了多种并发的处理方式,本篇文章将深入探讨其中的两种:多线程与多进程,解析其使用场景、优点、缺点,并结合代码例子深入解读。二、多线程Python中的线程......
  • 从零开始学Python第06课:循环结构
    我们在写程序的时候,极有可能遇到需要重复执行某条指令或某些指令的场景,例如我们需要每隔1秒钟在屏幕上输出一次“hello,world”并持续输出一个小时。如下所示的代码可以完成一次这样的操作,如果要持续输出一个小时,我们就需要把这段代码写3600遍,你愿意这么做吗?importtimeprint('h......
  • 从零开始学Python第05课:分支结构
    迄今为止,我们写的Python代码都是一条一条语句按顺序向下执行的,这种代码结构叫做顺序结构。然而仅有顺序结构并不能解决所有的问题,比如我们设计一个游戏,游戏第一关的过关条件是玩家获得1000分,那么在第一关完成后,我们要根据玩家得到分数来决定是进入第二关,还是告诉玩家“GameOver......
  • 从零开始学Python第04课:Python语言元素之运算符
    Python语言支持很多种运算符,下面的表格按照运算符的优先级从高到低,对Python中的运算符进行了罗列。有了变量和运算符,我们就可以构造各种各样的表达式来解决实际问题。在计算机科学中,表达式是计算机程序中的句法实体,它由一个或多个常量、变量、函数和运算符组合而成,编程语言可以......
  • 一文掌握Python多线程与多进程
    Python的多线程和多进程一、简介并发是今天计算机编程中的一项重要能力,尤其是在面对需要大量计算或I/O操作的任务时。Python提供了多种并发的处理方式,本篇文章将深入探讨其中的两种:多线程与多进程,解析其使用场景、优点、缺点,并结合代码例子深入解读。二、多线程Python中的线......
  • 从零开始学Python第03课:Python语言中的变量
    对于想学习编程的新手来说,有两个问题可能是他们很想知道的,其一是“什么是(计算机)程序”,其二是“写(计算机)程序能做什么”。先说说我对这两个问题的理解:程序是数据和指令的有序集合,写程序就是用数据和指令控制计算机做我们想让它做的事情。今时今日,为什么有那么多人选择用Python语言......
  • 从零开始学Python第01课:初识Python
    Python简介Python(英式发音:/ˈpaɪθən/;美式发音:/ˈpaɪθɑːn/)是由荷兰人吉多·范罗苏姆(GuidovonRossum)发明的一种编程语言,是目前世界上最受欢迎和拥有最多用户群体的编程语言。Python强调代码的可读性和语法的简洁性,相较于C或Java,Python让使用者能够用更少的代码表达自己......
  • 从零开始学Python第12课:常用数据结构之集合
    在学习了列表和元组之后,我们再来学习一种容器型的数据类型,它的名字叫集合(set)。说到集合这个词大家一定不会陌生,在数学课本上就有这个概念。如果我们把一定范围的、确定的、可以区别的事物当作一个整体来看待,那么这个整体就是集合,集合中的各个事物称为集合的元素。通常,集合需要满足......
  • 从零开始学Python第14课:函数和模块
    在讲解本节课的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。你可能已经想到了,这个问题其实等同于将8个苹果分成四组且每组至少一个苹果有多少种方案,也等价于在分隔8个苹果的7个间隙之间放入三个隔断将苹果分成四组有多少种方案,所以答案是$C_7^3=35C_{7}^{......
  • 从零开始学Python第11课:常用数据结构之字符串
    第二次世界大战促使了现代电子计算机的诞生,世界上的第一台通用电子计算机名叫ENIAC(电子数值积分计算机),诞生于美国的宾夕法尼亚大学,占地167平米,重量约27吨,每秒钟大约能够完成约5000次浮点运算,如下图所示。ENIAC诞生之后被应用于导弹弹道的计算,而数值计算也是现代电子计算机最为重......