apppublic/aidocs/app_logger.md
2025-10-05 11:23:33 +08:00

278 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AppLogger 技术文档
## 概述
`AppLogger` 是一个基于 Python 标准库 `logging` 模块封装的日志工具模块,旨在简化日志系统的初始化与使用。它提供全局日志实例、便捷的函数式接口以及面向对象的日志类,支持控制台输出和文件输出,并可自定义日志级别与格式。
---
## 功能特性
- 支持常见的日志级别:`debug`, `info`, `warning`, `error`, `critical`
- 可选日志输出方式:控制台(默认)或文件
- 全局单例模式管理日志器,避免重复创建
- 提供函数式调用接口(如 `info()`, `debug()` 等)
- 提供面向对象的 `AppLogger` 类,便于在项目中集成
- 自定义日志格式和时间戳
---
## 依赖说明
### 外部依赖
```python
import os
import sys
import logging
from functools import partial
```
### 内部依赖
```python
from appPublic.timeUtils import timestampstr
```
> 注意:`timestampstr` 在当前代码中未被实际调用,可能是预留功能或冗余导入。
---
## 配置常量
### 日志级别映射表
```python
levels = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR, # 原始代码有误,应为 logging.ERROR 而非 logging.error
"critical": logging.CRITICAL
}
```
将字符串级别的名称映射为 `logging` 模块对应的标准级别常量。
> ⚠️ Bug 提示:原始代码中 `"error": logging.error` 是错误的!`logging.error` 是一个方法,不是常量。正确应为 `logging.ERROR`。
---
### 默认日志格式
```python
defaultfmt = '%(asctime)s[%(name)s][%(levelname)s][%(filename)s:%(lineno)s]%(message)s'
```
#### 格式说明:
| 占位符 | 含义 |
|--------|------|
| `%(asctime)s` | 时间戳(自动格式化) |
| `%(name)s` | Logger 名称 |
| `%(levelname)s` | 日志级别(如 INFO, DEBUG |
| `%(filename)s` | 发出日志的源文件名 |
| `%(lineno)s` | 发出日志的行号 |
| `%(message)s` | 日志内容 |
示例输出:
```
2025-04-05 10:23:45,123[MyApp][INFO][main.py:42]Application started successfully.
```
---
### 全局变量
| 变量名 | 类型 | 初始值 | 说明 |
|-------------|----------|----------------|------|
| `logfile` | str / None / int | `-1` | 记录日志文件路径;`-1` 表示尚未设置,`None` 表示输出到控制台 |
| `logger` | Logger or None | `None` | 全局 logger 实例 |
| `g_levelname` | str | `'info'` | 当前日志级别名称(字符串) |
| `level` | int | `logging.INFO` | 对应的日志级别数值 |
---
## 核心函数
### `create_logger(name, formater=defaultfmt, levelname=None, file=None)`
创建并返回一个配置好的 `Logger` 实例。采用单例模式,确保多次调用只创建一次。
#### 参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `name` | str | 是 | 无 | 日志记录器名称,通常为模块或类名 |
| `formater` | str | 否 | `defaultfmt` | 日志输出格式字符串 |
| `levelname` | str | 否 | `None` | 指定日志级别(如 `'debug'`, `'warning'`),若不传则使用全局 `g_levelname` |
| `file` | str or None | 否 | `None` | 日志输出文件路径。若为 `None`,则输出到控制台 |
#### 返回值
- `logging.Logger`:已配置的日志记录器实例
#### 行为逻辑
1.`logfile == -1`(首次调用),则设置 `logfile = file`
2.`logger` 已存在,则直接返回,防止重复初始化
3. 创建 `Logger` 实例
4. 设置日志级别:
- 若传入 `levelname`,更新全局 `g_levelname``level`
- 否则使用当前全局级别
5. 创建 `Formatter` 使用指定格式
6. 创建处理器:
-`logfile` 不为 `None` → 使用 `FileHandler`
- 否则 → 使用 `StreamHandler`(标准输出)
7. 为处理器设置格式并添加到 logger
8. 返回 logger
> ✅ 支持热切换日志文件路径(仅限第一次)
---
### 函数式日志接口
提供顶层函数用于快速写日志,无需显式获取 logger。
| 函数 | 说明 |
|------|------|
| `info(*args, **kw)` | 输出 `INFO` 级别日志 |
| `debug(*args, **kw)` | 输出 `DEBUG` 级别日志 |
| `warning(*args, **kw)` | 输出 `WARNING` 级别日志 |
| `error(*args, **kw)` | 输出 `ERROR` 级别日志 |
| `critical(*args, **kw)` | 输出 `CRITICAL` 级别日志 |
| `exception(*args, **kw)` | 输出异常堆栈信息(等价于 `logger.exception()` |
> ⚠️ Bug 提示:`warning()` 函数中参数拼错:`*aegs` 应为 `*args`
#### 示例
```python
from your_module import info, error
info("程序启动")
error("发生错误", exc_info=True)
```
> 注:所有函数内部检查 `if logger is None`,若未初始化则静默忽略。
---
## 类:`AppLogger`
面向对象风格的日志封装类,每个实例拥有独立但共享配置的 logger。
### 初始化
```python
def __init__(self):
self.logger = create_logger(self.__class__.__name__)
self.debug = self.logger.debug
self.info = self.logger.info
self.warning = self.logger.warning
self.error = self.logger.error
self.critical = self.logger.critical
self.exception = self.logger.exception
```
#### 特性
- 使用类名作为 logger 名称(例如 `AppLogger` 实例的日志名为 `"AppLogger"`
- 将 logger 的方法绑定到自身属性,实现链式调用
- 所有实例共用同一个底层 logger`create_logger` 是单例)
### 使用示例
```python
class MyApp:
def __init__(self):
self.log = AppLogger()
def run(self):
self.log.info("应用正在运行")
try:
1 / 0
except Exception as e:
self.log.exception("捕获异常")
app = MyApp()
app.run()
```
输出示例:
```
2025-04-05 10:30:12,456[AppLogger][ERROR][myapp.py:15]捕获异常
Traceback (most recent call last):
File "myapp.py", line 14, in run
1 / 0
ZeroDivisionError: division by zero
```
---
## 已知问题Bug与改进建议
| 问题 | 描述 | 建议修复 |
|------|------|---------|
| ❌ `levels["error"]` 错误 | 使用了 `logging.error` 方法而非常量 `logging.ERROR` | 改为 `"error": logging.ERROR` |
| ❌ `warning()` 函数参数拼写错误 | `*aegs` 应为 `*args` | 修正拼写 |
| ⚠️ `exception()` 参数错误 | 调用时写成 `logger.exception(**args, **kw)` | 应为 `logger.exception(*args, **kw)`,且通常只需 `exc_info=True` |
| ⚠️ 全局状态耦合 | 多次调用 `create_logger` 无法更改 `file``format` | 可考虑增加重置机制或移除单例限制 |
| 💡 缺少关闭资源接口 | 未提供关闭 handler 的方法 | 建议添加 `close_logger()` 清理文件句柄 |
---
## 使用示例
### 示例 1基础使用控制台输出
```python
from your_module import create_logger, info, debug
# 初始化 logger
create_logger("MyApp", levelname="debug")
# 使用函数接口
info("这是信息")
debug("这是调试消息")
```
### 示例 2输出到文件
```python
from your_module import create_logger, error
create_logger("MyService", levelname="warning", file="logs/app.log")
error("发生严重错误!")
```
### 示例 3使用 AppLogger 类
```python
from your_module import AppLogger
class DataProcessor:
def __init__(self):
self.log = AppLogger()
def process(self):
self.log.info("开始处理数据")
self.log.warning("发现可疑数据点")
dp = DataProcessor()
dp.process()
```
---
## 总结
本模块通过封装 `logging` 模块,提供了简洁易用的日志接口,适用于中小型项目的快速开发。虽然存在少量 bug 和设计局限,但整体结构清晰,扩展性强。
建议在正式使用前修复已知问题,并根据需要增强配置灵活性(如支持多 handler、动态调整级别等
---
📌 **版本建议**v1.0.1(需修复 bug 后发布)
📅 **最后更新**2025年4月5日