数据分析agent(十):loguru日志输出优化 和es 启动流程

1,log.py

复制代码
pip install loguru
python 复制代码
from loguru import logger

logger.debug("测试日志")
logger.info("普通日志")
logger.warning("警告日志")
logger.error("错误日志")
python 复制代码
2026-07-26 10:18:55.570 | DEBUG    | __main__:<module>:4 - 测试日志
2026-07-26 10:18:55.570 | INFO     | __main__:<module>:5 - 普通日志
2026-07-26 10:18:55.570 | WARNING  | __main__:<module>:6 - 警告日志
2026-07-26 10:18:55.570 | ERROR    | __main__:<module>:7 - 错误日志
DEBUG > INFO > WARNING > ERROR
当加入 logger.remove() 控制台输出为空
python 复制代码
from loguru import logger

logger.remove()

logger.debug("测试日志")
logger.info("普通日志")
logger.warning("警告日志")
logger.error("错误日志")

2, 丰富的日志级别

复制代码
Loguru 提供了 7 个独特的日志级别,涵盖了从底层诊断到严重故障的各种场景:

TRACE (5):记录程序执行路径的极细粒度细节,用于深度诊断。

DEBUG (10):开发人员日常调试使用的信息。

INFO (20):记录程序正常操作的关键节点信息。

SUCCESS (25):Loguru 特有级别,用于明确指示某个操作已成功完成。

WARNING (30):提示发生了不寻常的事件,但程序仍可继续运行。

ERROR (40):记录导致特定操作失败的错误条件。

CRITICAL (50):记录阻止核心功能正常工作的严重错误

3,eg_1:

python 复制代码
import sys
import time
from loguru import logger

# 1. 移除默认的控制台输出,避免重复日志
logger.remove()

# 2. 添加带颜色的控制台输出(仅显示 INFO 及以上级别)
logger.add(
    sys.stderr,
    colorize=True,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
           "<level>{level: <8}</level> | "
           "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
           "<level>{message}</level>",
    level="INFO"
)

# 3. 配置文件输出(记录 DEBUG 及以上级别,支持轮转和压缩)
logger.add(
    "logs/app_{time:YYYY-MM-DD}.log",
    rotation="100 MB",
    retention="30 days",
    compression="zip",
    level="DEBUG",
    backtrace=True,
    diagnose=True
)


# 4. 定义业务处理函数
@logger.catch
def process_user(user_id: str, action: str):
    """处理用户操作,使用 @logger.catch 自动捕获异常"""
    logger.info(f"用户 {user_id} 执行操作: {action}")

    if action == "dangerous":
        raise ValueError(f"用户 {user_id} 尝试执行危险操作!")

    time.sleep(0.1)  # 模拟业务处理
    logger.success(f"用户 {user_id} 操作成功完成: {action}")


# 5. 测试代码
process_user("user_001", "login")
process_user("user_002", "dangerous")  # 触发异常,自动记录详细堆栈
```

```shell
2026-07-26 10:35:23 | INFO     | __main__:process_user:35 - 用户 user_001 执行操作: login
2026-07-26 10:35:23 | SUCCESS  | __main__:process_user:41 - 用户 user_001 操作成功完成: login
2026-07-26 10:35:23 | INFO     | __main__:process_user:35 - 用户 user_002 执行操作: dangerous
2026-07-26 10:35:23 | ERROR    | __main__:<module>:46 - An error has been caught in function '<module>', process 'MainProcess' (14048), thread 'MainThread' (18204):
Traceback (most recent call last):

> File "F:\0026_Car_Pro\data_agent\v0\day02_loguru\1.py", line 46, in <module>
    process_user("user_002", "dangerous")  # 触发异常,自动记录详细堆栈
    └ <function process_user at 0x00000180B18A3E20>

  File "F:\0026_Car_Pro\data_agent\v0\day02_loguru\1.py", line 38, in process_user
    raise ValueError(f"用户 {user_id} 尝试执行危险操作!")
                           └ 'user_002'

ValueError: 用户 user_002 尝试执行危险操作!
复制代码

4,eg_2:

python 复制代码
import sys
from pathlib import Path
from loguru import logger

# 1. 自动创建日志目录,避免路径不存在导致报错
LOG_DIR = Path("logs")
LOG_DIR.mkdir(parents=True, exist_ok=True)

# 2. 移除默认的日志输出(避免控制台和文件重复打印)
logger.remove()

# 3. 配置控制台输出(仅显示 INFO 及以上级别,带颜色)
logger.add(
    sys.stdout,
    level="INFO",
    colorize=True,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <level>{message}</level>"
)

# 4. 配置文件输出:普通日志 (INFO 及以上)
logger.add(
    LOG_DIR / "app_{time:YYYY-MM-DD}.log",
    level="INFO",
    rotation="10 MB",  # 文件大小超过 10MB 自动切割
    retention="7 days",  # 保留 7 天
    encoding="utf-8",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}"
)

# 5. 配置文件输出:专门记录报错 (ERROR 及以上)
logger.add(
    LOG_DIR / "error_{time:YYYY-MM-DD}.log",
    level="ERROR",
    rotation="10 MB",
    retention="30 days",  # 报错日志保留更长时间
    backtrace=True,  # 记录完整的调用栈
    diagnose=True,  # 自动诊断变量值
    encoding="utf-8"
)


# 6. 业务代码测试
@logger.catch  # 自动捕获函数内未处理的异常,并写入 error.log
def divide(a, b):
    return a / b


if __name__ == "__main__":
    logger.info("程序启动,开始执行业务逻辑...")

    try:
        # 模拟业务处理
        logger.info("正在处理数据...")
        result = divide(10, 0)  # 触发 ZeroDivisionError
    except Exception as e:
        # 在 except 块中使用 exception() 记录完整堆栈
        logger.exception("业务处理过程中发生严重错误")

    logger.warning("这是一条警告信息,会写入 app.log 但不会写入 error.log")
python 复制代码
2026-07-26 10:40:41 | INFO     | 程序启动,开始执行业务逻辑...
2026-07-26 10:40:41 | INFO     | 正在处理数据...
2026-07-26 10:40:41 | ERROR    | An error has been caught in function '<module>', process 'MainProcess' (6036), thread 'MainThread' (18412):
Traceback (most recent call last):

> File "F:\0026_Car_Pro\data_agent\v0\day02_loguru\2.py", line 54, in <module>
    result = divide(10, 0)  # 触发 ZeroDivisionError
             └ <function divide at 0x0000028ED4D89940>

  File "F:\0026_Car_Pro\data_agent\v0\day02_loguru\2.py", line 45, in divide
    return a / b
           │   └ 0
           └ 10
复制代码

context.py

python 复制代码
​


​from contextvars import ContextVar

request_id_ctx_var = ContextVar("request_id", default="1")

print(request_id_ctx_var)
复制代码

示例3:

python 复制代码
import asyncio
import sys
from pathlib import Path
from loguru import logger

#from app.app_config import app_config
from app.context import request_id_ctx_var



# 配置日志格式
log_format = (
    "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
    "<level>{level: <8}</level> | "
    "<magenta>request_id - {extra[request_id]}</magenta> | "
    "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
    "<level>{message}</level>"
)


# 注入request_id到日志记录中
def inject_request_id(record):
    request_id = request_id_ctx_var.get()
    record["extra"]["request_id"] = request_id


logger.remove()

# 给日志打补丁,使其支持注入request_id
logger = logger.patch(inject_request_id)

# 控制台日志(保持原有逻辑)
# if app_config.logging.console.enable:
#     logger.add(sink=sys.stdout, level=app_config.logging.console.level, format=log_format)

if True:
    logger.add(sink=sys.stdout, level="INFO", format=log_format)


# 文件日志:修改为项目根目录下的 logs 文件夹
#if app_config.logging.file.enable:
if True:
    # 1. 获取项目根目录(当前文件所在目录的上层/上层,根据实际结构调整)
    # 核心逻辑:__file__ 是当前文件路径,.parent 向上找根目录
    # 如果你不确定层级,可以打印调试:print(Path(__file__).absolute())
    PROJECT_ROOT = Path(__file__).parents[2]  # 根据实际项目结构调整

    # 2. 拼接日志路径:项目根目录 / logs / app.log
    LOG_DIR = PROJECT_ROOT / "logs"
    LOG_FILE = LOG_DIR / "app.log"

    # 3. 创建日志目录(确保存在)
    LOG_DIR.mkdir(parents=True, exist_ok=True)

    # 4. 添加文件日志处理器
    logger.add(
        sink=LOG_FILE,
        level="DEBUG",
        format=log_format,
        rotation="10 MB",
        retention="7 days",
        encoding="utf-8"
    )

if __name__ == '__main__':
    async def print_log(request: str):
        # 打印日志
        logger.info(request)


    async def test1():
        # 接收到请求
        request_id_ctx_var.set("request-1")
        # 模拟处理
        await asyncio.sleep(1)
        await print_log("request-1")


    async def test2():
        # 接收到请求
        request_id_ctx_var.set("request-2")

        # 模拟处理
        await asyncio.sleep(1)
        await print_log("request-2")


    async def main():
        await asyncio.gather(test1(), test2())


    asyncio.run(main())
    
'''
<ContextVar name='request_id' default='1' at 0x000002364675DDA0>
1
2026-07-26 10:58:06.697 | INFO     | request_id - request-1 | __main__:print_log:68 - request-1
2026-07-26 10:58:06.698 | INFO     | request_id - request-2 | __main__:print_log:68 - request-2
'''
复制代码
相关推荐
减瓦1 小时前
Gradle 版本演进全景:构建工具的进化密码
java·gradle
玛丽莲茼蒿1 小时前
很难出错的Spring5(十)—— IOC进阶
java·开发语言·jvm
减瓦1 小时前
Jackson 使用指南
java·spring boot·json
Devin~Y1 小时前
互联网大厂 Java 面试实录:Spring Boot、MyBatis、Redis、Kafka、Spring Security、RAG 与 MCP 全链路问答
java·redis·kafka·mybatis·spring security·spring mvc·sprint boot
weixin_437662981 小时前
redisson
java
码农进化录1 小时前
Java 程序员的 AI 进化论 | AI 加 Postman 跑接口测试,省了三天活
java·后端·openai
阿米亚波2 小时前
【C++ STL】std::array
java·开发语言·c++
奶糖 肥晨2 小时前
mac系统中Java项目环境配置与问题解决全记录| 项目构建篇:Maven编译与打包
java·macos·maven
万亿少女的梦1682 小时前
基于Spring Boot的乐助在线助农系统设计与实现
java·spring boot·mysql·敏感词过滤·助农系统