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

生成日志系统和监控

背景:已知某后台服务将日志存放在本地硬盘的日志文件中,该服务也支持代码热更新,并在完成热更新后输出一条日志。我们需要对服务日志进行监控,以确保文件热更新后的错误能被第一时间发现。

我们提供 Python 程序模拟(https://pastebin.com/pZH8wruC,密码pWXRFeSpwU)上述行为,该程序会不断生成日志,并输出到日志文件 1.log 中,日志格式参考源码。

要求:
1、使用 Python 或者 Shell 对上述日志进行检测,检测方式可以是常驻进程实时检测,也可以通过系统定时任务(需要说明如何配置)定时检测日志;
2、当检测到热更新日志时(以"load file:"开头,具体格式参考源码),对错误日志(error级别)进行分类统计(分类按照日志内容进行);
3、如果热更新后1分钟内某一类别的错误日志比热更新前1分钟内的量级更多(增加50%),则在另一个文件 2.log 中记录相关日志(附带该量级超标的日志内容、热更新前后的量级信息)。
 

//这是链接里面的代码# 日志生成用例# - 程序随机地生成 info 和 error 级别日志# - 每隔一段时间产生热更新日志# - 模拟热更新后出现更多的错误日志import osimport timeimport randomimport loggingdef init_logging():logger = logging.getLogger()logger.setLevel(logging.INFO)logger_format = logging.Formatter("[%(asctime)s][%(levelname)s][%(module)s:%(funcName)s:%(lineno)d] %(message)s")logger_console = logging.StreamHandler()logger_console.setLevel(logging.INFO)logger_console.setFormatter(logger_format)logger.addHandler(logger_console)logger_file = logging.FileHandler("1.log")logger_file.setLevel(logging.INFO)logger_file.setFormatter(logger_format)logger.addHandler(logger_file)STAGE_CONFIG = {"normal": {"duration": "70±10","info_base_prob": 0.01,"info_add_prob": 0,"error_base_prob": 0.01,"error_add_prob": 0,},"after_hotreload": {"duration": "80±20","info_base_prob": 0.1,"info_add_prob": 0.1,"error_base_prob": 0.1,"error_add_prob": 0.2,}}INFO_LOG_TEMPLATE = ["session connected","session closed","player login","player registered","player logout","buy item flow","sell item flow",]ERROR_LOG_TEMPLATE = ["function %d error occur","player login failed","incorrect password","establish connection failed","bad arguments",]INFO_HOTRELOAD_TEMPLATE = ["load file: %d.lua .......... [ok]"]def random_stage_time(duration):pos = duration.find('±')base_time = int(duration[:pos])offset_time = int(duration[pos + 1:])return base_time + (random.random() * 2 - 1) * offset_timedef random_select(l):e = random.choice(l)if e.find('%') >= 0:r = random.randint(0, 10)return e % rreturn eclass App:def __init__(self):self._stage = Noneself._stage_time = 0self._timer = 0self._init_state("normal")def _init_state(self, stage):self._stage = stageself._stage_time = random_stage_time(STAGE_CONFIG[stage]["duration"])self._timer = 0def on_tick(self, elapsed_time):self._timer += elapsed_timeif self._timer >= self._stage_time:if self._stage == "normal":logging.info(random_select(INFO_HOTRELOAD_TEMPLATE))self._init_state("after_hotreload")elif self._stage == "after_hotreload":self._init_state("normal")log_add_strength = 1 - min(1.0, (self._stage_time - self._timer) / self._stage_time)log_info_prob = STAGE_CONFIG[self._stage]["info_base_prob"] + \log_add_strength * STAGE_CONFIG[self._stage]["info_add_prob"]log_err_prob = STAGE_CONFIG[self._stage]["error_base_prob"] + \log_add_strength * STAGE_CONFIG[self._stage]["error_add_prob"]if random.random() < log_info_prob:logging.info(random_select(INFO_LOG_TEMPLATE))if random.random() < log_err_prob:logging.error(random_select(ERROR_LOG_TEMPLATE))def main():init_logging()app = App()last_time = time.time()while True:now_time = time.time()app.on_tick(now_time - last_time)last_time = now_timetime.sleep(0.01)if __name__ == "__main__":main()

解决方法:

为了使用Python来实现上述要求,我们可以编写一个Python脚本来处理日志文件的读取、解析、分类统计以及比较热更新前后的错误日志数量。同时,我们将使用系统定时任务(如Linux下的cron)来定期运行这个Python脚本。

步骤 1: 编写Python脚本

首先,我们需要编写一个Python脚本来处理日志文件。这个脚本将需要能够:

  1. 读取日志文件。
  2. 检测热更新日志(以"load file:"开头)。
  3. 提取错误日志并根据内容进行分类统计。
  4. 比较热更新前后的错误日志数量。
  5. 记录超标的日志内容和统计信息到另一个文件。

下面是一个简化的Python脚本示例:

import re  
import os  
from datetime import datetime, timedelta  LOG_FILE = '/path/to/your/logfile.log'  
OUTPUT_FILE = '/path/to/2.log'  
TEMP_STATS_FILE = '/tmp/stats.tmp'  # 模拟从日志文件中读取行(实际中应使用文件操作)  
def read_log_lines(file_path):  # 这里只是模拟,实际中应打开文件并逐行读取  with open(file_path, 'r') as file:  return file.readlines()  # 检测热更新并处理日志  
def process_logs():  lines = read_log_lines(LOG_FILE)  update_time = None  before_counts = {}  after_counts = {}  # 遍历日志行  for line in lines:  if line.startswith('load file:'):  # 检测到热更新,记录时间并重置计数器  update_time = datetime.strptime(line.split(' ')[-1], '%Y-%m-%d %H:%M:%S')  before_counts = {}  after_counts = {}  elif 'ERROR' in line:  # 假设每行日志包含时间和级别  log_time = datetime.strptime(re.search(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}', line).group(), '%Y-%m-%d %H:%M:%S')  error_type = re.search(r'ERROR: (.+?)(?: \[|$)', line).group(1)  if update_time and update_time - timedelta(minutes=1) <= log_time <= update_time + timedelta(minutes=1):  # 在热更新前后1分钟内  if log_time < update_time:  before_counts[error_type] = before_counts.get(error_type, 0) + 1  else:  after_counts[error_type] = after_counts.get(error_type, 0) + 1  # 比较并记录结果  for type, after_count in after_counts.items():  before_count = before_counts.get(type, 0)  if after_count > before_count * 1.5:  with open(OUTPUT_FILE, 'a') as file:  file.write(f"Error type {type} increased significantly after update:\n")  file.write(f"Before: {before_count}, After: {after_count}\n")  # 这里可以添加更多逻辑来记录具体的日志内容  # 定时任务将调用这个函数  
if __name__ == '__main__':  process_logs()

注意:上面的脚本有几个简化和假设的地方,比如直接读取整个日志文件并假设时间戳和错误类型可以直接从日志行中提取。在实际应用中,你可能需要处理更复杂的日志格式和更大的日志文件。

步骤 2: 配置Cron定时任务

接下来,你需要在Linux系统上设置Cron定时任务来定期运行这个Python脚本。

  1. 打开终端。
  2. 输入crontab -e命令来编辑当前用户的Cron任务列表。
  3. 添加一个定时任务来每分钟运行一次脚本(或者根据你的需求设置不同的频率):
    * * * * * /usr/bin/python3 /path/to/your/script.py

    注意将/usr/bin/python3替换为你的Python解释器的实际路径,/path/to/your/script.py替换为你的Python脚本的实际路径。

    保存并关闭编辑器。Cron将自动加载新的任务列表。
    现在,你的Python脚本将按照Cron任务的设置定期运行,检测日志文件中的热更新,并对错误

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 算法·高精度
  • C++的介绍与认识
  • 用JavaScript将 NCR(Numeric Character Reference)标记转换为对应字符的方法
  • 对称加密和非对称加密解析
  • 关于力扣150题目——逆波兰表达式求值Java实现的三种解法
  • 如何写好品牌宣传稿提升品牌曝光?看这篇文章就够了
  • Java虚拟机(JVM):深入理解与性能调优
  • 如何在应用运行时定期监控内存使用情况
  • “LNMP环境搭建实战指南:从零开始配置CentOS 7下的Nginx、MySQL与PHP“
  • C# —— Directory类
  • Java 中的异常处理机制是如何工作的?请解释 try-catch-finally 的基本用法?
  • 如何远程访问运行电脑上运行的程序?
  • 【知网CNKI-注册安全分析报告】
  • C++:filter2D函数简要概述
  • 手撸俄罗斯方块(一)——简单介绍
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 《Java编程思想》读书笔记-对象导论
  • 【RocksDB】TransactionDB源码分析
  • Angular 响应式表单之下拉框
  • Apache Pulsar 2.1 重磅发布
  • Cumulo 的 ClojureScript 模块已经成型
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Java Agent 学习笔记
  • Javascript Math对象和Date对象常用方法详解
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Lsb图片隐写
  • Lucene解析 - 基本概念
  • node学习系列之简单文件上传
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • VUE es6技巧写法(持续更新中~~~)
  • 基于组件的设计工作流与界面抽象
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 扑朔迷离的属性和特性【彻底弄清】
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 移动端 h5开发相关内容总结(三)
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • 仓管云——企业云erp功能有哪些?
  • 第二十章:异步和文件I/O.(二十三)
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #etcd#安装时出错
  • #git 撤消对文件的更改
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (1)常见O(n^2)排序算法解析
  • (11)MSP430F5529 定时器B
  • (2)STL算法之元素计数
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (7)svelte 教程: Props(属性)
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (精确度,召回率,真阳性,假阳性)ACC、敏感性、特异性等 ROC指标
  • (七)Knockout 创建自定义绑定
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)