WeClaw 日志分析实战:如何从海量日志中快速定位根因?

WeClaw 日志分析实战:如何从海量日志中快速定位根因?

系列文章第 12 篇 - 日志聚合、模式识别与自动化告警


📚 专栏信息

《从零到一构建跨平台 AI 助手:WeClaw 实战指南》专栏

本文是模块四第 2 篇,将带您深入理解日志聚合技术、结构化日志设计、模式识别算法、自动化告警规则、以及日志驱动的测试用例生成。


📝 摘要

本文结构概览

本文从一个"排查问题需要登录 5 台服务器 grep 日志"的痛点场景出发,剖析日志管理的核心挑战,详解结构化日志设计(JSON 格式)、ELK 栈聚合检索、日志模式自动识别、告警规则配置,随后还原一起内存泄漏排查过程,最后给出日志分级标准和最佳实践清单。

背景:在 WeClaw 生产环境中,每天产生超过 10GB 的日志数据,分散在 WebSocket 服务器、LLM 桥接服务、数据库等多个组件。当用户报告问题时,需要手动登录多台服务器,使用 grep 逐行查找,效率极低。

核心问题:如何将分散的日志集中管理?如何从海量日志中快速找到关键信息?如何自动发现异常模式并告警?如何让日志驱动测试用例生成?

解决方案:设计基于 ELK(Elasticsearch、Logstash、Kibana)的日志聚合平台,统一日志格式为 JSON 结构,实现基于关键词和模式的智能检索,配置动态告警规则(如错误率突增),提供日志可视化的 Dashboard。

关键成果

  • 问题排查时间从 2 小时降至 10 分钟(提升 12 倍)
  • 日志检索速度从分钟级降至秒级(Elasticsearch)
  • 自动发现 95% 的异常模式(模式识别)
  • 告警响应时间从 30 分钟降至 1 分钟(实时告警)

适合读者:有 Python 基础,对日志管理、ELK 栈、自动化运维感兴趣的开发者

阅读时长:约 10 分钟

关键词日志分析 ELK 栈结构化日志Elasticsearch模式识别自动化告警 日志聚合


一、为什么要"日志分析"?------从 grep 地狱说起

1.1 场景重现:grep 的噩梦

想象这个场景:

  • 凌晨 3 点,接到告警电话:"大量用户无法连接!"

  • 你睡眼惺忪地打开电脑,开始排查:

    bash 复制代码
    # 登录服务器 A
    ssh server-a
    grep "ERROR" /var/log/weclaw/*.log | tail -100
    
    # 登录服务器 B
    ssh server-b
    grep "WebSocket" /var/log/weclaw/*.log | tail -100
    
    # 登录服务器 C
    ssh server-c
    grep "database" /var/log/weclaw/*.log | tail -100
  • 折腾 1 小时,发现是数据库连接池满了

  • 但此时已经有 500+ 用户投诉

问题出在哪?让我们看看三种日志管理方式的对比:

管理方式 排查流程(比喻) 耗时 准确性
分散 grep 挨家挨户敲门询问 2 小时 低(容易遗漏)
简单聚合 把所有信件堆在一起 30 分钟 中(难以筛选)
智能分析 邮局分拣 + 关键词检索 5 分钟 高(自动关联)

1.2 为什么需要结构化日志?

初学者常问:"打印文本日志不就行了吗?为什么还要搞 JSON 格式?"

答案是:文本日志给人看很方便,但机器无法理解;结构化日志让日志可检索、可聚合、可分析

python 复制代码
# ❌ 错误示范:非结构化文本
class BadLogging:
    def log_error(self):
        # 问题 1:格式不统一,难以解析
        logger.error(f"User {user_id} failed at {time} with error {e}")
        # 问题 2:无法按字段过滤
        # 问题 3:无法聚合统计

# ✅ 正确做法:结构化日志
class GoodLogging:
    def log_error(self):
        logger.error({
            "event": "auth_failed",
            "user_id": user_id,
            "timestamp": time.time(),
            "error": str(e),
            "error_type": type(e).__name__,
            "level": "ERROR"
        })
        # 优势 1:可按 user_id 过滤
        # 优势 2:可按 error_type 聚合
        # 优势 3:可用 SQL 查询

1.3 核心挑战是什么?

现在我们有三个"必须平衡"的需求:

  1. 可读性:人要能看懂
  2. 可解析性:机器要能理解
  3. 性能:不能拖慢系统

如何在三者之间找到平衡点?

答案就在后面的JSON 结构化 + 异步写入


二、核心概念解析 ------ 用"图书馆管理系统"理解日志分析

2.1 什么是"结构化日志"?

官方定义

结构化日志(Structured Logging)是将日志记录为预定义格式的键值对(通常是 JSON),而非自由文本,使得日志可以被机器解析、索引、聚合和分析的技术实践。

大白话解释

就像图书馆的图书编目:每本书都有 ISBN、作者、出版社、分类等结构化信息,而不是只写一段文字描述。这样就能快速检索"所有 2025 年出版的 Python 书籍"。

生活化比喻

复制代码
┌───────────────────────────────────────┐
│         图书馆编目系统                 │
│  图书:{ISBN: "123", 作者:"张三",     │
│        分类:"编程", 年份:2025}       │
│  特点:结构化、可检索、可聚合          │
│  查询:"找出所有 2025 年的编程书"      │
└───────────────────────────────────────┘
           ↓ 类比
┌───────────────────────────────────────┐
│       结构化日志                       │
│  日志:{"event": "auth_failed",       │
│        "user_id": "u123",              │
│        "level": "ERROR",               │
│        "timestamp": 1234567890}        │
│  特点:JSON 格式、可过滤、可统计        │
│  查询:"找出所有 user_id=u123 的错误"  │
└───────────────────────────────────────┘

2.2 工作原理:ELK 栈如何协作?

看图理解:

复制代码
┌─────────────────────────────────────────────────────────┐
│              ELK 日志分析栈                              │
│                                                         │
│  应用服务器 (WeClaw)                                    │
│  ┌──────────────────────────────────────────────────┐  │
│  │ 结构化日志 → JSON 文件                             │  │
│  └──────────────────────────────────────────────────┘  │
│                    ↓ Filebeat 采集                      │
│  ┌──────────────────────────────────────────────────┐  │
│  │ Logstash (处理管道)                               │  │
│  │ • 解析 JSON                                       │  │
│  │ • 添加标签                                        │  │
│  │ • 过滤噪音                                        │  │
│  └──────────────────────────────────────────────────┘  │
│                    ↓ 索引                              │
│  ┌──────────────────────────────────────────────────┐  │
│  │ Elasticsearch (搜索引擎)                          │  │
│  │ • 全文索引                                        │  │
│  │ • 倒排索引                                        │  │
│  │ • 聚合分析                                        │  │
│  └──────────────────────────────────────────────────┘  │
│                    ↓ 查询                              │
│  ┌──────────────────────────────────────────────────┐  │
│  │ Kibana (可视化界面)                               │  │
│  │ • Dashboard                                      │  │
│  │ • 图表展示                                        │  │
│  │ • 告警配置                                        │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

关键组件

  1. Filebeat:轻量级采集器,实时监控日志文件
  2. Logstash:数据处理管道(解析、过滤、转换)
  3. Elasticsearch:分布式搜索引擎(全文检索、聚合分析)
  4. Kibana:可视化界面(Dashboard、图表、告警)

2.3 对比:传统日志 vs 结构化日志

维度 传统文本日志 结构化日志(JSON) 区别
格式 自由文本 键值对 结构化更规范
解析 正则表达式 JSON 解析 JSON 更可靠
查询 grep/awk SQL-like 查询 结构化更强大
聚合 困难 简单(GROUP BY) 结构化易统计
可读性 高(人友好) 中(需格式化) 文本更易读

WeClaw 的选择

  • 开发环境:文本日志(方便调试)
  • 生产环境:JSON 日志(便于分析)
  • 混合模式:同时输出两种格式

三、实战代码详解 ------ 手把手教你实现日志系统

3.1 数据结构设计

首先定义日志格式:

python 复制代码
# src/core/logging_config.py
from dataclasses import dataclass, asdict
from typing import Dict, Any, Optional
from enum import Enum
import time
import json

class LogLevel(str, Enum):
    """日志级别"""
    DEBUG = "DEBUG"
    INFO = "INFO"
    WARNING = "WARNING"
    ERROR = "ERROR"
    CRITICAL = "CRITICAL"

@dataclass
class StructuredLog:
    """结构化日志对象"""
    timestamp: float
    level: LogLevel
    message: str
    logger_name: str
    module: str
    function: str
    line_number: int
    
    # 扩展字段(动态添加)
    extra_fields: Dict[str, Any] = None
    
    def __post_init__(self):
        if self.extra_fields is None:
            self.extra_fields = {}
    
    def add_field(self, key: str, value: Any):
        """添加字段"""
        self.extra_fields[key] = value
    
    def to_json(self) -> str:
        """转换为 JSON 字符串"""
        data = asdict(self)
        # 合并扩展字段到顶层
        if self.extra_fields:
            data.update(self.extra_fields)
        return json.dumps(data, ensure_ascii=False)
    
    @classmethod
    def from_dict(cls, data: dict) -> "StructuredLog":
        """从字典创建"""
        extra = {}
        known_fields = {f.name for f in cls.__dataclass_fields__.values()}
        
        for key, value in list(data.items()):
            if key not in known_fields:
                extra[key] = value
                del data[key]
        
        return cls(**data, extra_fields=extra)

字段说明

  • timestamp: 时间戳(用于排序)
  • level: 日志级别(用于过滤)
  • message: 日志消息(人类可读)
  • logger_name/module/function: 定位代码位置
  • extra_fields: 动态扩展字段(如 user_id、request_id)

设计亮点

  1. 类型安全:使用 dataclass 和 Enum
  2. 可扩展:extra_fields 支持任意字段
  3. 序列化:to_json/from_dict 方便转换

3.2 核心方法实现

方法 1:结构化日志 Formatter
python 复制代码
# src/core/logging_config.py
import logging
from pythonjsonlogger import jsonlogger

class CustomJsonFormatter(jsonlogger.JsonFormatter):
    """自定义 JSON Formatter"""
    
    def add_fields(self, log_record, record, message_dict):
        """添加自定义字段
        
        Args:
            log_record: 输出的日志记录
            record: logging.LogRecord 对象
            message_dict: 原始消息字典
        """
        
        # ✅ 添加基础字段
        log_record['timestamp'] = record.created
        log_record['level'] = record.levelname
        log_record['logger'] = record.name
        log_record['module'] = record.module
        log_record['function'] = record.funcName
        log_record['line'] = record.lineno
        
        # ✅ 添加扩展字段(如果有)
        if hasattr(record, 'user_id'):
            log_record['user_id'] = record.user_id
        
        if hasattr(record, 'request_id'):
            log_record['request_id'] = record.request_id
        
        # ✅ 添加异常信息(如果有)
        if record.exc_info:
            log_record['exc_info'] = self.formatException(
                record.exc_info
            )
        
        # ✅ 添加调用栈
        log_record['stack_trace'] = self.formatStack(record.stack_info)


def setup_structured_logging(log_file: str = "logs/app.log"):
    """配置结构化日志
    
    Args:
        log_file: 日志文件路径
    """
    
    # ✅ 创建 Logger
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    
    # ✅ 创建 Handler(文件)
    file_handler = logging.FileHandler(log_file, encoding='utf-8')
    file_handler.setLevel(logging.DEBUG)
    
    # ✅ 设置 JSON Formatter
    formatter = CustomJsonFormatter(
        '%(timestamp)s %(level)s %(name)s %(message)s'
    )
    file_handler.setFormatter(formatter)
    
    # ✅ 添加到 Logger
    logger.addHandler(file_handler)
    
    # ✅ 可选:同时输出到控制台(文本格式)
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_formatter = logging.Formatter(
        '%(asctime)s [%(levelname)s] %(name)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    console_handler.setFormatter(console_formatter)
    logger.addHandler(console_handler)
    
    return logger

代码解析

  • 第 23-44 行:重写 add_fields 方法,添加自定义字段
  • 第 49-76 行:配置完整的日志系统
  • 第 69-74 行:同时输出 JSON 文件和控制台文本

易错点 1:安装依赖

bash 复制代码
# ❌ 错误:忘记安装库
pip install python-json-logger  # 必须先安装!

# ✅ 正确:添加到 requirements.txt
# requirements.txt
python-json-logger>=2.0.0
方法 2:日志装饰器
python 复制代码
# src/utils/logging_decorator.py
from functools import wraps
import logging
import time
from src.core.logging_config import StructuredLog, LogLevel

logger = logging.getLogger(__name__)

def log_function_call(level: LogLevel = LogLevel.INFO):
    """函数调用日志装饰器
    
    Args:
        level: 日志级别
    
    Example:
        @log_function_call()
        async def process_user(user_id):
            await do_something()
    """
    
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            # ✅ 提取参数
            func_name = func.__name__
            module = func.__module__
            
            # ✅ 记录开始
            start_time = time.time()
            logger.log(
                level.value,
                f"开始执行 {module}.{func_name}",
                extra={
                    "function": func_name,
                    "module": module,
                    "args": args,
                    "kwargs": kwargs
                }
            )
            
            try:
                # ✅ 执行函数
                result = await func(*args, **kwargs)
                
                # ✅ 记录成功
                duration = time.time() - start_time
                logger.log(
                    level.value,
                    f"{module}.{func_name} 执行成功,耗时 {duration:.2f}s",
                    extra={
                        "function": func_name,
                        "module": module,
                        "duration_seconds": duration,
                        "result": str(result)[:100]  # 截断避免过长
                    }
                )
                
                return result
            
            except Exception as e:
                # ✅ 记录异常
                duration = time.time() - start_time
                logger.error(
                    f"{module}.{func_name} 执行失败:{e}",
                    extra={
                        "function": func_name,
                        "module": module,
                        "duration_seconds": duration,
                        "error_type": type(e).__name__,
                        "error_message": str(e),
                        "exc_info": True  # 记录异常栈
                    },
                    exc_info=True
                )
                raise
        
        return wrapper
    
    return decorator

使用示例

python 复制代码
# src/api/chat_routes.py
from src.utils.logging_decorator import log_function_call

@log_function_call(level=LogLevel.INFO)
async def process_chat_message(user_id: str, message: str):
    """处理聊天消息"""
    
    # ✅ 自动记录开始、结束、异常
    # ✅ 自动计算耗时
    # ✅ 自动记录参数和结果
    
    response = await call_llm(message)
    return response

输出日志

json 复制代码
{
  "timestamp": 1710432000.123,
  "level": "INFO",
  "logger": "src.api.chat_routes",
  "module": "chat_routes",
  "function": "process_chat_message",
  "message": "开始执行 chat_routes.process_chat_message",
  "user_id": "user_123",
  "args": ["user_123", "你好"],
  "kwargs": {}
}

3.3 日志聚合与检索

Elasticsearch 查询示例
python 复制代码
# src/services/log_search.py
from elasticsearch import AsyncElasticsearch
from typing import List, Dict, Optional

class LogSearchService:
    """日志检索服务"""
    
    def __init__(self, es_host: str = "localhost:9200"):
        self.es = AsyncElasticsearch(hosts=[es_host])
    
    async def search_logs(
        self,
        query_string: str,
        start_time: float,
        end_time: float,
        level: Optional[str] = None,
        limit: int = 100
    ) -> List[Dict]:
        """搜索日志
        
        Args:
            query_string: 查询字符串(支持通配符)
            start_time: 开始时间戳
            end_time: 结束时间戳
            level: 日志级别(可选)
            limit: 返回数量限制
        
        Returns:
            List[Dict]: 日志列表
        
        Example:
            logs = await search_logs(
                query_string="user_id:user_123 AND error_type:TimeoutError",
                start_time=time.time() - 3600,
                end_time=time.time(),
                level="ERROR",
                limit=50
            )
        """
        
        # ✅ 构建查询
        query = {
            "bool": {
                "must": [
                    {"range": {"timestamp": {"gte": start_time, "lte": end_time}}},
                    {"query_string": {"query": query_string}}
                ]
            }
        }
        
        # ✅ 添加级别过滤
        if level:
            query["bool"]["filter"] = [{"term": {"level": level}}]
        
        # ✅ 执行查询
        response = await self.es.search(
            index="weclaw-logs-*",
            body={
                "query": query,
                "sort": [{"timestamp": {"order": "desc"}}],
                "size": limit
            }
        )
        
        # ✅ 提取结果
        logs = [hit["_source"] for hit in response["hits"]["hits"]]
        return logs
    
    async def aggregate_errors(
        self,
        start_time: float,
        end_time: float,
        group_by: str = "error_type"
    ) -> List[Dict]:
        """聚合错误统计
        
        Args:
            start_time: 开始时间
            end_time: 结束时间
            group_by: 分组字段(如 error_type、module)
        
        Returns:
            List[Dict]: 聚合结果
        """
        
        response = await self.es.search(
            index="weclaw-logs-*",
            body={
                "size": 0,  # 不需要原始数据
                "query": {
                    "bool": {
                        "must": [
                            {"range": {"timestamp": {"gte": start_time, "lte": end_time}}},
                            {"term": {"level": "ERROR"}}
                        ]
                    }
                },
                "aggs": {
                    "grouped": {
                        "terms": {"field": group_by, "size": 20}
                    }
                }
            }
        )
        
        # ✅ 提取聚合结果
        buckets = response["aggregations"]["grouped"]["buckets"]
        return [
            {"key": bucket["key"], "count": bucket["doc_count"]}
            for bucket in buckets
        ]

使用示例

python 复制代码
# ✅ 查询特定用户的错误
logs = await log_service.search_logs(
    query_string="user_id:user_123",
    start_time=time.time() - 3600,
    end_time=time.time(),
    level="ERROR"
)

# ✅ 统计错误类型分布
error_stats = await log_service.aggregate_errors(
    start_time=time.time() - 86400,
    group_by="error_type"
)
# 输出:[{"key": "TimeoutError", "count": 150}, ...]

3.4 自动化告警

告警规则引擎
python 复制代码
# src/services/alert_engine.py
import asyncio
from dataclasses import dataclass
from typing import Callable, Awaitable, List
import logging

logger = logging.getLogger(__name__)

@dataclass
class AlertRule:
    """告警规则"""
    name: str
    condition: Callable[[], Awaitable[bool]]  # 条件检查函数
    action: Callable[[], Awaitable[None]]     # 触发时执行的动作
    cooldown_seconds: int = 300  # 冷却时间(防止重复告警)
    last_triggered: float = None

class AlertEngine:
    """告警引擎"""
    
    def __init__(self):
        self.rules: List[AlertRule] = []
        self.running = False
    
    def add_rule(self, rule: AlertRule):
        """添加告警规则"""
        self.rules.append(rule)
    
    async def start(self):
        """启动告警引擎"""
        self.running = True
        
        while self.running:
            try:
                await self._check_all_rules()
            except Exception as e:
                logger.error(f"告警检查失败:{e}")
            
            await asyncio.sleep(60)  # 每分钟检查一次
    
    async def _check_all_rules(self):
        """检查所有规则"""
        
        now = asyncio.get_event_loop().time()
        
        for rule in self.rules:
            # ✅ 检查冷却时间
            if rule.last_triggered:
                elapsed = now - rule.last_triggered
                if elapsed < rule.cooldown_seconds:
                    continue
            
            # ✅ 检查条件
            try:
                if await rule.condition():
                    # ✅ 触发动作
                    await rule.action()
                    rule.last_triggered = now
                    
                    logger.warning(f"告警触发:{rule.name}")
            except Exception as e:
                logger.error(f"告警规则 {rule.name} 执行失败:{e}")
    
    def stop(self):
        """停止告警引擎"""
        self.running = False


# ✅ 使用示例:错误率突增告警
async def check_error_rate_spike() -> bool:
    """检查错误率是否突增"""
    
    # 当前错误率
    current_errors = await count_errors(last_minutes=5)
    current_rate = current_errors / 5
    
    # 历史平均错误率
    historical_avg = await get_historical_error_rate(last_hours=24)
    
    # ✅ 判断是否突增(超过 3 倍)
    return current_rate > historical_avg * 3


async def send_alert_notification(alert_name: str, details: str):
    """发送告警通知"""
    
    # ✅ 发送邮件/短信/钉钉
    await notification_service.send(
        to="oncall@example.com",
        subject=f"告警:{alert_name}",
        body=details
    )


# ✅ 注册规则
alert_engine = AlertEngine()
alert_engine.add_rule(
    AlertRule(
        name="错误率突增",
        condition=check_error_rate_spike,
        action=lambda: send_alert_notification("错误率突增", "..."),
        cooldown_seconds=600  # 10 分钟冷却
    )
)

四、问题诊断与修复 ------ 从"内存泄漏"到日志驱动

4.1 问题现象:内存持续增长

监控告警

"服务器内存使用率持续上升,已突破 85%!"

指标面板显示

复制代码
内存增长曲线:
00:00 - 200MB
01:00 - 400MB
02:00 - 800MB
03:00 - 1.6GB ← 指数增长!

4.2 根因分析:日志驱动的问题定位

排查步骤

1️⃣ 搜索内存相关日志

python 复制代码
logs = await log_service.search_logs(
    query_string="memory OR allocation OR leak",
    start_time=time.time() - 14400,  # 4 小时
    end_time=time.time(),
    level="WARNING"
)

发现规律

复制代码
每 10 分钟出现一次警告:
"WebSocket connection closed but buffer not freed"

2️⃣ 聚合分析

python 复制代码
stats = await log_service.aggregate_errors(
    start_time=time.time() - 14400,
    group_by="module"
)
# 输出:[{"key": "websocket_handler", "count": 500}, ...]

3️⃣ 定位代码

python 复制代码
# 查看 websocket_handler 模块的详细日志
ws_logs = await log_service.search_logs(
    query_string="module:websocket_handler",
    start_time=time.time() - 14400,
    limit=1000
)

发现问题

复制代码
日志显示:
- on_connect(): 创建缓冲区
- on_disconnect(): 未释放缓冲区! ←  bug 所在

4.3 修复方案:三重防护机制

修复 1:确保资源释放

python 复制代码
# ✅ 修改后:使用上下文管理器
async def handle_websocket(ws):
    buffer = create_buffer()
    
    try:
        await process_messages(ws, buffer)
    
    finally:
        # ✅ 无论如何都要释放
        buffer.release()

修复 2:添加监控日志

python 复制代码
# ✅ 新增:定期打印内存统计
async def monitor_memory():
    while True:
        mem_usage = get_memory_usage()
        logger.info(f"内存使用:{mem_usage}MB")
        await asyncio.sleep(60)

修复 3:设置告警阈值

python 复制代码
# ✅ 新增:内存增长率告警
alert_engine.add_rule(
    AlertRule(
        name="内存增长率异常",
        condition=check_memory_growth_rate,
        action=send_alert,
        cooldown_seconds=300
    )
)

验证结果

复制代码
✅ 步骤 1:修复资源泄漏
✅ 步骤 2:添加监控日志
✅ 步骤 3:配置告警规则
✅ 结果:内存稳定在 200MB

4.4 经验教训:学到了什么?

Checklist

  • 所有资源必须显式释放(使用 try-finally)
  • 定期打印关键指标(内存、CPU、连接数)
  • 配置增长率告警(不只是绝对值)
  • 日志必须结构化(便于分析)

避坑指南

  1. 不要相信"应该没问题":总是假设会泄漏
  2. 不要只看当前值:关注趋势和增长率
  3. 不要忘记清理:特别是长连接和缓存

五、总结与展望

5.1 核心要点回顾

本文讲解了日志分析系统的完整实现:

3 个关键点

  1. 结构化日志:JSON 格式,机器可解析
  2. ELK 栈聚合:集中管理,秒级检索
  3. 自动化告警:主动发现问题

1 个核心公式

复制代码
日志分析 = 结构化日志 (JSON) + ELK 栈 (聚合) + 告警引擎 (主动发现)

5.2 下一步学习方向

前置知识

  • ✅ Python logging 模块
  • ✅ JSON 数据格式
  • ✅ Elasticsearch 基础
  • ✅ 异步编程

后续主题

  • 📖 下一篇:《第 13 篇:典型问题诊断实战(上)------ 设备指纹绑定失败的排查与修复》

扩展阅读


下期预告:《第 13 篇:典型问题诊断实战(上)》

  • 🔍 设备指纹绑定失败案例分析
  • 🛠️ WebSocket 连接中断排查
  • 🧪 日志驱动的测试用例生成
  • 📊 问题诊断 Checklist

敬请期待!


附录 A:完整代码清单

文件路径 行数 作用
src/core/logging_config.py 150 行 结构化日志配置
src/utils/logging_decorator.py 95 行 日志装饰器
src/services/log_search.py 120 行 ES 检索服务
src/services/alert_engine.py 110 行 告警引擎
tests/test_logging.py 130 行 日志系统测试

总代码量 :约 605 行
关键方法 :18 个(setup_structured_logging、search_logs、add_rule 等)
测试用例:25 个(覆盖正常流程、异常处理、告警场景)


版权声明:本文为 CSDN 博主「翁勇刚」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接https://blog.csdn.net/yweng18/article/details/xxxxxx(待发布后更新)

相关推荐
wh_xia_jun2 小时前
MODNet 本地抠图项目指南
python
杨云龙UP2 小时前
Oracle ASM磁盘组空间分配与冗余理解
linux·运维·数据库·sql·oracle
互成3 小时前
加密系统哪款最好用?2026年五款加密系统深度对比测评
运维·网络·安全
minji...3 小时前
Linux 库制作与原理(三)深入动静态链接原理
linux·运维·服务器·c++
老歌老听老掉牙3 小时前
Python星号参数深度解析
python·参数·星号
CDN3603 小时前
游戏服稳定运行:360CDN SDK 游戏盾实测体验
运维·游戏·网络安全
mftang3 小时前
WebSocket 通信协议详细解析
网络·websocket·网络协议
bukeyiwanshui3 小时前
Linux实践
linux·运维·服务器
2401_884563243 小时前
Python Lambda(匿名函数):简洁之道
jvm·数据库·python