上篇文章我们学习了视频的数据采集,今天主要了解一下日志数据采集的方法。日志数据采集的目的通常是:调试、运维监控和业务分析。调试主要是工程师在程序异常时针对关键环节把相关参数通过日志打印出来,找出哪个环节出现了问题。运维监控主要是监控系统运行的负载、并发性能以及消耗时间等指标。通过日志可以记录用户的每一次操作,以及相关维度信息,有了这些数据就可以做一些运营分析,如访问量、用户转化、留存分析等。
1、基础知识准备
1)日志数据
日志-log 数据记录的是信息系统产生的过程性事件数据。通过查看日志数据,管理员可以了解哪个用户什么时间在哪台设备使用了什么应用系统做了什么具体的操作。
2)日志组成
日志由日期、信息、等级三要素组成。日志的等级如下:
| |||||||
致命 | 错误 | 警告 | 信息 | 调试 | 痕迹 | 全部 | |
OFF | |||||||
致命 | X | ||||||
错误 | X | X | |||||
警告 | X | X | X | ||||
信息 | X | X | X | X | |||
调试 | X | X | X | X | X | ||
痕迹 | X | X | X | X | X | X | |
全部 | X | X | X | X | X | X | X |
- OFF:最高等级,用于关闭所有日志记录。
- FATAL:严重错误级别,表示系统无法继续运行。
- ERROR:错误级别,用于记录错误信息。
- WARN:警告级别,表示潜在的问题,但不影响程序的运行。
- INFO:信息级别,用于记录程序的正常运行信息。
- DEBUG:调试级别,用于详细记录调试信息。
- TRACE:追踪级别,提供比DEBUG更详细的信息。
- ALL:最低级别,用于启用所有日志记录。
即如上表所示,将日志设置在某一个等级上,那么比此等级优先级高的日志都能被输出。
例如,如果设置为WARN,那么FATAL、ERROR、WARN 、OFF 4个等级的日志都能被输出。
3)Logging库
在Python中,logging 模块是内置的,用于记录程序的运行日志。它可以非常灵活地配置,以满足不同场景的需求,例如记录到文件、控制台、通过网络发送日志等。
Logging 库包括Logger(日志采集器)、Handler(日志处理器)、Filter(日志处理器)、Formatter(日志各式器)4个组件。
日志模块最常用的类:
Logger:公开了一个接口,代码通过使用该接口记录日志消息。即用采集器采集日志。
Handler:处理器,将logger创建的日志发送到目的地(控制台或文件)。常用的处理程序包括:
FileHandler:用于将日志消息发送到文件
StreamHandler:用于向输出流(如stdout)发送日志消息
SyslogHandler:用于向syslog守护进程发送日志消息
HTTPHandler:用于使用HTTP协议发送日志消息
Filter:过滤器,提供一种机制来确定记录哪些日志。
Formatter:格式器,决定日志消息的输出格式。
A、Logger类
Logger类是入口,使用模块级别函数 logging.getLogger(name) 实例化,最终由Handler来对日志进行处理,Handler会调用Filter和Formatter来对日志进行过滤和格式化。
import logging
logger = logging.getLogger('mylogger')
logger.debug('Debug 级别日志信息')
logger.info('Info 级别日志信息')
logger.warning('Warning 级别日志信息')
logger.error('Error 级别日志信息')
logger.critical('Critical 级别日志信息')
自定义logger不能使用 basicConfig() 来配置,需要使用 处理器(Handler)和 格式器(Formatter)来配置。
B、处理器
可以使用处理器(Handler)来配置自定义logger将日志保存到文件、输出到控制台、通过HTTP发送或者通过邮件发送。
处理器也可以设置日志严重级别,为文件处理器(FileHandler)和控制台处理器(StreamHandler)设置不同的日志级别。
# 创建处理器 handlers
console_handler = logging.StreamHandler() # 输出到控制台
file_handler = logging.FileHandler(logname) # 输出到文件
console_handler.setLevel(logging.WARNING)
file_handler.setLevel(logging.ERROR)
C、格式器
格式器(Formatter)用来配置格式化输出。
# 创建格式器
console_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')
file_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')
C、过滤器
过滤器(Filter)可实现日志过滤操作,
import logging
import sys
import os
class failureFilter(logging.Filter):
def filter(self, record):
if 'Failure' in record.msg:
return True
return False
logger = logging.getLogger(__name__)
console_handler = logging.StreamHandler(stream=sys.stdout) # 输出到控制台
# 添加filter
loggingFiletr = failureFilter()
console_handler.addFilter(loggingFiletr)
logger.addHandler(console_handler)
logger.info('Info 级别日志信息')
logger.error('Failure')
D、使用配置文件配置 Logger(高级用法)
对于更复杂的项目,你可以使用配置文件(如 JSON 或 YAML 文件)来配置 logging。这可以通过 logging.config.dictConfig 方法实现。例如:
import logging.config
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
},
'handlers': {
'default': {
'level':'DEBUG',
'class':'logging.StreamHandler',
'formatter': 'standard'
},
'file': {
'level':'DEBUG',
'class':'logging.FileHandler',
'formatter': 'standard',
'filename': 'app.log',
},
},
'loggers': {
'': { # root logger配置使用上面定义的handler和level等配置。也可以为不同的logger指定不同的配置。
'handlers': ['default', 'file'],
'level': 'DEBUG',
'propagate': True, # 是否将日志向上传递到root logger。默认为True。如果设置为False,则不会将此logger的日志传递给上级logger。
},
}
}
logging.config.dictConfig(LOGGING_CONFIG) # 应用配置
2、举例说明
写一个日志采集的实例,步骤:
- 创建一个日志采集器:logging.fetLogger(“”)
- 给收集器设置日志级别
- 给日志采集器创建一个输出处理器
- 给处理器设置一个日志输出内容的格式
- 将设置的格式绑定到处理器中
- 将设置好的渠道添加到收集器中
参考如下:
import logging.handlers #导入库,才能使用handler 类创建对象
#创建日志采集器对象,logger
logger = logging.getLogger()
#设置采集器级别,logger 等级设置
logger.setLevel(logging.INFO) #设置了信息等级,消息在粗粒度级别上强调应用程序的运行过程
#创建处理器handler 对象
sh = logging.StreamHandler()
#根据时间分割日志
th = logging.handlers.TimedRotatingFileHandler(filename="D:\\dewi\\project2024\\myListPractice\\pythonProject1\\test_data\\0402.log",
when="S",
interval=1,
backupCount=3
)
#创建日志格式
fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d)] - %(message)s"
fm = logging.Formatter(fmt)
#将日志格式设置给处理器
sh.setFormatter(fm)
th.setFormatter(fm)
#将控制台处理器添加到logger
logger.addHandler(sh)
logger.addHandler(th)
#外部程序调用采集器获取日志
logger.info("Hi,it is an info")
logger.debug("Hi,it is a debug")
logger.error("Hi,it is an error")
logger.warning("Hi,this is a warning!")
输出结果,过滤了info消息日志:
2025-04-13 16:47:41,864 INFO [root] [get_log.py (<module>:31)] - Hi,it is an info
2025-04-13 16:47:41,866 ERROR [root] [get_log.py (<module>:33)] - Hi,it is an error
2025-04-13 16:47:41,866 WARNING [root] [get_log.py (<module>:34)] - Hi,this is a warning!
Process finished with exit code 0
每天进步一点点,继续加油!