Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .env.example
Empty file.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ wheels/

# Virtual environments
.venv

# Config
.env

# Log
logs/*
12 changes: 1 addition & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ repos:
- id: check-merge-conflict # 检查合并冲突标记
- id: debug-statements # 检查调试语句

# Python代码格式化:black
- repo: https://github.com/psf/black
rev: 25.1.0 # 稳定版本
hooks:
- id: black
args: ['--line-length=120'] # 行长度适配AI项目长函数参数

# 整理import顺序:isort
- repo: https://github.com/PyCQA/isort
rev: 5.13.2 # 稳定版本
Expand All @@ -32,10 +25,7 @@ repos:
rev: v0.14.14
hooks:
- id: ruff
args:
- --line-length=120
- --select=E,W,F,I,N,UP,YTT,B,SIM,COM,C4,DTZ,T10,EM,EXE,FA,ISC,ICN,G,INP,PIE,Q003,RET,RSE,SLF,SIM,T20,TID,TRY
- --ignore=E203,W503,COM812 # 忽略和black冲突的规则
args: [--fix, --exit-non-zero-on-fix, --no-cache]

# 检测硬编码密钥:detect-secrets (暂时禁用,基线文件问题)
# - repo: https://github.com/Yelp/detect-secrets
Expand Down
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[dependency-groups]
dev = [
"pre-commit>=4.5.1"
"pre-commit>=4.5.1",
"pytest>=9.0.2"
]

[project]
Expand All @@ -10,5 +11,6 @@ description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"detect-secrets>=1.5.0"
"detect-secrets>=1.5.0",
"loguru>=0.7.3"
]
Empty file added src/comp_synth/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions src/comp_synth/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# -------------------------- Log ----------------------
LOG_DIR = "D:\CompSynth\logs"
3 changes: 3 additions & 0 deletions src/comp_synth/logging/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from comp_synth.logging.logger_config import logger

__all__ = [logger]
43 changes: 43 additions & 0 deletions src/comp_synth/logging/logger_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from pathlib import Path

from loguru import logger

from comp_synth import config

LOG_DIR = Path(config.LOG_DIR)
LOG_DIR.mkdir(parents=True, exist_ok=True)

# 定义日志格式
# 控制台彩色格式(含上下文绑定字段:request_id/user_id)
CONSOLE_FMT = (
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
"<level>{level: <8}</level> | "
"<cyan>{module}</cyan>:<cyan>{line}</cyan> | "
"<level>{message}</level>"
)
# 文件纯文本格式(含进程/线程ID,便于多进程调试)
FILE_FMT = "{time:YYYY-MM-DD HH:mm:ss.SSS} | " "{level: <8} | " "{module}:{line} | " "{message}"
# 错误日志格式(含异常堆栈)
ERROR_FMT = "{time:YYYY-MM-DD HH:mm:ss.SSS} | " "{level: <8} | " "{module}:{line} | " "{message}"

logger.remove()

logger.add(
sink=LOG_DIR / "app_{time:YYYYMMDD}.log",
level="DEBUG",
format=FILE_FMT,
encoding="utf-8",
enqueue=True,
backtrace=False,
diagnose=False,
)

logger.add(
sink=LOG_DIR / "error_{time:YYYYMMDD}.log",
level="ERROR",
format=ERROR_FMT,
encoding="utf-8",
enqueue=True,
backtrace=True,
diagnose=False,
)
116 changes: 116 additions & 0 deletions tests/test_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from comp_synth.logging import logger

# from loguru import logger
#
# logger.remove()
#
# # 1. 控制台输出(INFO及以上,彩色格式)
# logger.add(
# sys.stdout,
# level="INFO", # 最低日志级别
# format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{module}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>"
# )
#
# # 2. 文件输出(DEBUG及以上,纯文本格式,自动创建文件)默认使用追加模式
# logger.add(
# sink="../logs/app.log", # 日志文件路径,目录不存在会自动创建
# level="DEBUG",
# format="{time:YYYY HH:mm:ss} | {level: <8} | {module}:{line} - {message}",
# encoding="utf-8" # 指定编码,避免中文乱码(必配)
# )
#
# logger.add(
# sink="../logs/app.log", # 不幂等
# level="DEBUG",
# format="{time:YYYY HH:mm:ss} | {level: <8} | {module}:{line} - {message}",
# encoding="utf-8"
# )
#
# # 过滤1:仅输出来自 user 模块的日志(通配符*匹配子模块)
# logger.add(
# sys.stdout,
# format="{time:YYYY HH:mm:ss} | {level: <8} | {module}:{line} - {message}",
# filter="user.*" # 仅匹配 logger 名称为 user、user.utils、user.service 等的日志
# )
#
# # 过滤2:仅输出 ERROR 和 CRITICAL 级别日志(字典格式)
# logger.add(
# "../logs/error.log",
# format="{time:YYYY HH:mm:ss} | {level: <8} | {module}:{line} - {message}",
# filter=lambda record: record["level"].name in ["ERROR", "CRITICAL"]
# )
#
# # 生产环境标配:50MB轮转+保留30天+zip压缩+中文防乱码
# logger.add(
# sink="../logs/app_{time:YYYYMMDD}.log", # 文件名带日期,便于查找
# level="DEBUG",
# format="{time:YYYY HH:mm:ss} | {level: <8} | {module}:{line} - {message}",
# encoding="utf-8",
# rotation="50 MB", # 单个文件50MB,自动轮转
# retention="30 days", # 仅保留最近30天的日志文件
# compression="zip", # 过期日志自动压缩为zip格式
# enqueue=True, # 多进程安全写入(避免多进程下日志乱序/丢失)
# backtrace=True, # 捕获异常时,显示完整的堆栈回溯(包括第三方库)
# diagnose=True # 捕获异常时,显示变量值等诊断信息(开发/测试环境开启)
# )
#
# logger.debug("调试信息:仅写入文件,控制台不显示")
# logger.info("信息:控制台+文件均显示")
# logger.info("根模块日志:不会被输出") # 过滤1不匹配,无输出
# logger.error("根模块错误:会写入error.log") # 过滤2匹配,正常输出
#
# try:
# # 模拟异常
# 1 / 0
# except ZeroDivisionError:
# # exc_info=True:自动记录完整的异常堆栈
# logger.error("除零错误发生,业务执行失败", exc_info=True)
#
#
# # 装饰器方式:捕获函数内所有异常
# @logger.catch # 关键:添加该装饰器
# def divide(a, b):
# return a / b
#
#
#
# logger.remove()
# # 格式中添加绑定的字段占位符:{request_id}、{user_id}
# console_fmt = "<green>{time:HH:mm:ss}</green> | {level: <8} | request_id={request_id} | user_id={user_id} | {message}"
# logger.add(sys.stdout, format=console_fmt, level="INFO")
#
# # 1. 基础绑定:绑定固定字段
# logger = logger.bind(request_id="req-123456", user_id=1001)
# logger.info("用户发起登录请求")
# logger.info("用户密码验证通过")
# logger.warning("用户登录次数超过阈值")
#
# # 2. 动态绑定:针对不同请求生成唯一request_id(Web场景标配)
# def handle_request(user_id):
# # 为每个请求生成唯一request_id
# req_id = str(uuid.uuid4())[:8]
# # 动态绑定上下文
# req_logger = logger.bind(request_id=req_id, user_id=user_id)
# req_logger.info("请求开始:/api/user/info")
# req_logger.info("查询用户信息完成")
# return {"code": 200, "msg": "success"}
#
# # 模拟两个不同请求
# handle_request(1002)
# handle_request(1003)


def test_logger():
logger.debug("agent调用工具失败")
logger.info("agent调用add工具中")


@logger.catch(reraise=True)
def divide(a, b):
return a / b

def test_logger_reraise():
try:
divide(1, 0)
except Exception:
print("process catch error")
95 changes: 93 additions & 2 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.