当前位置: 首页 > article >正文

Python Logging

一、简介

Python的logging模块提供了一种灵活的方式来记录日志信息。使用logging模块,你可以将日志记录到文件、控制台、syslog等不同的目标中,还可以根据日志级别过滤日志信息。logging模块还支持多个日志处理器和多个日志过滤器,可以根据需要自定义日志记录方式。

1.1 功能

logger:日志器,用于记录日志信息。logger对象可以有多个,每个logger对象可以有多个handler对象,用于将日志记录发送到不同的目标。logger对象还可以设置日志级别、过滤器等属性,用于控制日志记录的行为。

formatter:格式化器,用于将LogRecord对象转换为字符串。logging模块中提供了多种格式化器,如BasicFormatter、Formatter等。

handler:处理器,用于将日志记录发送到不同的目标,如文件、控制台、syslog等。logging模块中提供了多种处理器,如StreamHandler、FileHandler、SysLogHandler等。

getLogger()方法:用于获取logger对象。如果多次调用getLogger()方法并传入相同的名称,将返回同一个logger对象。如果不传入名称,则返回root logger对象。

getChild()方法:用于创建子logger对象。子logger对象的名称是父logger对象的名称加上一个后缀,后缀由getChild()方法的参数指定。子logger对象继承了父logger对象的所有属性,如日志级别、过滤器、处理器等。子logger对象还可以设置自己的属性,如日志级别、过滤器、处理器等。

1.2 用途

  • 可以定义多种级别,按需记录
    如:debug,info,warning,error,critical
  • 可以配置多套日志方式,记录到多个文件中
    如:根据需求记录到多个文件中,app.log, task.log
  • 可以配置不同的Handler,控制日志以什么载体记录
    如:log文件,stdout,elasticsearch等

二、文本格式

日志具体以什么载体展示取决于formatter参数,例如:
formatter = logging.Formatter(“%(asctime)s %(levelname)s %(message)s”,“%Y-%m-%d %H:%M:%S”)

import logging
import json
from logging.handlers import RotatingFileHandler

# 获取logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# 日志格式
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s","%Y-%m-%d %H:%M:%S")

# 根据业务的不同日志,定义不同的handler
ansible_handler = RotatingFileHandler('/tmp/ansible.log', maxBytes=100000000, backupCount=100)
ansible_handler.setLevel(logging.DEBUG)
ansible_handler.setFormatter(formatter)

task_handler = RotatingFileHandler('/tmp/task.log', maxBytes=100000000, backupCount=100)
task_handler.setLevel(logging.INFO)
task_handler.setFormatter(formatter)

app_handler = RotatingFileHandler('/tmp/app.log', maxBytes=100000000, backupCount=100)
app_handler.setLevel(logging.INFO)
app_handler.setFormatter(formatter)


# 方法用于创建子记录器,从而更好地组织你的日志信息。子记录器会继承父记录器的配置,但是你可以为它们单独设置日志级别、处理器等。
logger.getChild('ansible').addHandler(ansible_handler)
logger.getChild('task').addHandler(task_handler)
logger.getChild('app').addHandler(app_handler)


# 获取子记录器
ansibleLogger = logger.getChild('ansible')
taskLogger = logger.getChild('task')
appLogger = logger.getChild('app')

# 写入日志
ansibleLogger.info('这是ansible运行日志')
taskLogger.info('这是后端任务运行日志')
appLogger.info('这是主程序运行日志')

运行日志

yuehua@yuehuadeMacBook-Pro ~$ cat /tmp/app.log
2023-03-21 17:11:29 INFO 这是主程序运行日志
yuehua@yuehuadeMacBook-Pro ~$ cat /tmp/task.log
2023-03-21 17:11:29 INFO 这是后端任务运行日志
yuehua@yuehuadeMacBook-Pro ~$ cat /tmp/ansible.log
2023-03-21 17:11:29 INFO 这是ansible运行日志

三、JSON格式

可以定义一个JsonFormatter类,继承logging.Formatter类,重写format
然后将 formatter 指向这个类的实例对象

import logging
import json
from logging.handlers import RotatingFileHandler

# 获取logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# 日志格式(JSON)
class JsonFormatter(logging.Formatter):
    def format(self, record):
        data = {
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(record.created)),
            'level': record.levelname,
            'message': record.getMessage(),
            'module': record.module,
            'line': record.lineno,
            'function': record.funcName,
            'logger': record.name,
        }
        return json.dumps(data)
formatter = JsonFormatter()

# 根据业务的不同日志,定义不同的handler
ansible_handler = RotatingFileHandler('/tmp/ansible.log', maxBytes=100000000, backupCount=100)
ansible_handler.setLevel(logging.DEBUG)
ansible_handler.setFormatter(formatter)

task_handler = RotatingFileHandler('/tmp/task.log', maxBytes=100000000, backupCount=100)
task_handler.setLevel(logging.INFO)
task_handler.setFormatter(formatter)

app_handler = RotatingFileHandler('/tmp/app.log', maxBytes=100000000, backupCount=100)
app_handler.setLevel(logging.INFO)
app_handler.setFormatter(formatter)

# 方法用于创建子记录器,从而更好地组织你的日志信息。子记录器会继承父记录器的配置,但是你可以为它们单独设置日志级别、处理器等。
logger.getChild('ansible').addHandler(ansible_handler)
logger.getChild('task').addHandler(task_handler)
logger.getChild('app').addHandler(app_handler)

# 获取子记录器
ansibleLogger = logger.getChild('ansible')
taskLogger = logger.getChild('task')
appLogger = logger.getChild('app')

# 写入日志
ansibleLogger.info('这是ansible运行日志')
taskLogger.info('这是后端任务运行日志')
appLogger.info('这是主程序运行日志')

运行日志

yuehua@yuehuadeMacBook-Pro ~$ cat /tmp/app.log
{"timestamp": "2023-03-21 17:29:44", "level": "INFO", "message": "\u8fd9\u662f\u4e3b\u7a0b\u5e8f\u8fd0\u884c\u65e5\u5fd7", "module": "wlwlwl1", "line": 55, "function": "<module>", "logger": "__main__.app"}
yuehua@yuehuadeMacBook-Pro ~$ cat /tmp/ansible.log
{"timestamp": "2023-03-21 17:29:44", "level": "INFO", "message": "\u8fd9\u662fansible\u8fd0\u884c\u65e5\u5fd7", "module": "wlwlwl1", "line": 53, "function": "<module>", "logger": "__main__.ansible"}
yuehua@yuehuadeMacBook-Pro ~$ cat /tmp/task.log
{"timestamp": "2023-03-21 17:29:44", "level": "INFO", "message": "\u8fd9\u662f\u540e\u7aef\u4efb\u52a1\u8fd0\u884c\u65e5\u5fd7", "module": "wlwlwl1", "line": 54, "function": "<module>", "logger": "__main__.task"}

四、ES

定义一个 ElasticsearchHandler 的处理器,继承 logging.Handler 类,将业务日志的handler指向这个ElasticsearchHandler的实例对象,并在初始化的时候,传入一个索引名称。

import logging
import json
import time
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk

es = Elasticsearch("http://localhost:9200")

class ElasticsearchHandler(logging.Handler):
    def __init__(self, index_name):
        super().__init__()
        self.index_name = index_name

    def emit(self, record):
        log = {
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(record.created)),
            'level': record.levelname,
            'message': record.getMessage(),
            'module': record.module,
            'line': record.lineno,
            'function': record.funcName,
            'logger': record.name,
        }
        es.index(index=self.index_name, body=log)

# 获取logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# 根据业务的不同日志,定义不同的handler
ansible_handler = ElasticsearchHandler('ansible')
ansible_handler.setLevel(logging.DEBUG)

task_handler = ElasticsearchHandler('task')
task_handler.setLevel(logging.INFO)

app_handler = ElasticsearchHandler('app')
app_handler.setLevel(logging.INFO)

# 方法用于创建子记录器,从而更好地组织你的日志信息。子记录器会继承父记录器的配置,但是你可以为它们单独设置日志级别、处理器等。
logger.getChild('ansible').addHandler(ansible_handler)
logger.getChild('task').addHandler(task_handler)
logger.getChild('app').addHandler(app_handler)

# 通过子记录器获取日志对象
ansibleLogger = logger.getChild('ansible')
taskLogger = logger.getChild('task')
appLogger = logger.getChild('app')

ansibleLogger.info('这是ansible运行日志')
taskLogger.info('这是后端任务运行日志')
appLogger.info('这是主程序运行日志')

获取日志

{
    "took": 4,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "ansible",
                "_type": "_doc",
                "_id": "ymKhA4cBiDjJ60c3P1Wo",
                "_score": 1.0,
                "_source": {
                    "timestamp": "2023-03-21 18:05:10",
                    "level": "INFO",
                    "message": "\u8fd9\u662fansible\u8fd0\u884c\u65e5\u5fd7",
                    "module": "wlwlwl1",
                    "line": 50,
                    "function": "<module>",
                    "logger": "__main__.ansible"
                }
            }
        ]
    }
}

http://www.kler.cn/a/2008.html

相关文章:

  • CE之植物大战僵尸植物无冷却
  • Activiti开启流程实例
  • java全栈day20--Web后端实战(Mybatis基础2)
  • CS 144 check5: down the stack (the network interface)
  • 内置函数.
  • 安装milvus以及向量库增删改操作
  • Python爬虫——Python多线程爬虫详解
  • 血氧仪是如何得出血氧饱和度值的?
  • HTTPS协议,看这篇就够了
  • 二叉搜索树
  • 【canvas】简易小实例(钟表和画布)
  • 2023年全国最新道路运输从业人员精选真题及答案28
  • 【JavaEE】Thread 类及常用方法
  • 项目质量管理工作 不得不重视的4大关键点
  • web渗透之jwt 安全问题
  • 【Linux】Linux基本指令(下)
  • 让 new bing 使用 GPT-4 编写一个令人满意的程序全过程赏析
  • web前端开发和后端开发哪个难度大?
  • 【深度学习】迁移学习
  • 文心一言硬刚ChatGPT。文心一言能否为百度止颓?中国版ChatGPT“狂飙”的机会在哪儿?
  • 这几个过时Java技术不要再学了
  • lgsvl 现状
  • unable to resolve dependency tree、webpack与xxx-loader版本不兼容问题解决 (详细步骤)
  • 蓝桥杯刷题第十四天
  • QT CTK插件框架 (一 下载编译)
  • 弗洛伊德龟兔赛跑算法(弗洛伊德判圈算法)