liblogging 0.1.13__tar.gz → 0.1.16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- liblogging-0.1.16/PKG-INFO +206 -0
- liblogging-0.1.16/README.md +180 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging/logger.py +41 -18
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging/sending/log_collector.py +3 -2
- liblogging-0.1.16/liblogging.egg-info/PKG-INFO +206 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/setup.py +1 -1
- liblogging-0.1.13/PKG-INFO +0 -122
- liblogging-0.1.13/README.md +0 -96
- liblogging-0.1.13/liblogging.egg-info/PKG-INFO +0 -122
- {liblogging-0.1.13 → liblogging-0.1.16}/LICENSE +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging/__init__.py +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging/sending/__init__.py +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging/sending/kafka_service.py +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging/util.py +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging.egg-info/SOURCES.txt +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging.egg-info/dependency_links.txt +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging.egg-info/entry_points.txt +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging.egg-info/requires.txt +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging.egg-info/top_level.txt +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/liblogging.egg-info/zip-safe +0 -0
- {liblogging-0.1.13 → liblogging-0.1.16}/setup.cfg +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: liblogging
|
|
3
|
+
Version: 0.1.16
|
|
4
|
+
Summary: Utilities for logging and sending logs.
|
|
5
|
+
Home-page: https://github.com/XoriieInpottn/liblogging
|
|
6
|
+
Author: xi
|
|
7
|
+
Author-email: gylv@mail.ustc.edu.cn, huangfuyb@163.com
|
|
8
|
+
License: Apache-2.0 license
|
|
9
|
+
Platform: any
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Provides-Extra: collector
|
|
14
|
+
Requires-Dist: kafka-python==2.0.2; extra == "collector"
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: platform
|
|
24
|
+
Dynamic: provides-extra
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
# liblogging
|
|
28
|
+
[](https://deepwiki.com/XoriieInpottn/liblogging)
|
|
29
|
+
|
|
30
|
+
Utilities for logging and sending logs.
|
|
31
|
+
```shell
|
|
32
|
+
pip install liblogging
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🌟Feature
|
|
36
|
+
### 统一日志格式记录
|
|
37
|
+
统一了当前agent的日志记录格式,也可自己基于默认格式进行拓展。
|
|
38
|
+
当前记录的信息和对应的key如下:
|
|
39
|
+
```python
|
|
40
|
+
{
|
|
41
|
+
"create_time": "时间戳,默认和mysql列datatime(3)保持一致",
|
|
42
|
+
"level": "like INFO, ERROR, WARNING",
|
|
43
|
+
# 通过上下文变量保存trace_id
|
|
44
|
+
"trace_id": "trace_id for 追溯不同服务的调用链路",
|
|
45
|
+
"line_info": "{record.filename}:{record.lineno}:{record.funcName}",
|
|
46
|
+
"message": message,
|
|
47
|
+
# 通过上下文变量区分不同源, 方便接收不同服务源信息, 比如Chat, Welcome, Planning等
|
|
48
|
+
"message_source": context.get("message_source", "chat_log"),
|
|
49
|
+
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
50
|
+
"message_type": message_type,
|
|
51
|
+
# 可以根据自己需求加入其他的字段
|
|
52
|
+
**extra_message
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
上述日志信息均以json字符串的形式记录下来,方便存储及后续处理。
|
|
56
|
+
|
|
57
|
+
### 配置上下文变量,无须重复传参显示记录
|
|
58
|
+
通过装饰器形式, 指定需要配置的全局上下文变量, 仅需在整个程序/服务入口配置一次即可。
|
|
59
|
+
|
|
60
|
+
需要注意的是配置的全局上下文变量,根据加入装饰器下的函数入参名称匹配进行更新,推荐函数参数定义使用`BaseModel`。
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
主程序/服务: service1.py
|
|
64
|
+
from pydantic import BaseModel
|
|
65
|
+
|
|
66
|
+
from liblogging import log_request,logger
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Request(BaseModel):
|
|
70
|
+
name: str
|
|
71
|
+
trace_id: str
|
|
72
|
+
|
|
73
|
+
#在主程序入口配置了trace_id这一全局上下文变量,会通过函数入参对该字段进行赋值,后续在该服务下的其他程序logger.info时会读取这一变量并记录下来。
|
|
74
|
+
#同时也支持默认参数配置,比如message_source设置了默认值,后续使用logger会记录message_source为"demo"。
|
|
75
|
+
@log_request("trace_id", message_source="demo")
|
|
76
|
+
def your_service_entry(request: Request):
|
|
77
|
+
logger.info("Processing request")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
该服务下的其他程序: function1.py,可直接logger.info(). trace_id, message_source均会记录下来。
|
|
82
|
+
from liblogging import logger
|
|
83
|
+
|
|
84
|
+
def test(name):
|
|
85
|
+
logger.info(f"Testing {name}")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 重定向并发送到消息队列
|
|
89
|
+
以默认集成的kafka为例,可将上述统一日志格式记录的形式发送至kafka。
|
|
90
|
+
|
|
91
|
+
kafka 配置文件格式:
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"{cluster_name}": {
|
|
95
|
+
"{env_name}": {
|
|
96
|
+
"bootstrap_servers": "server1, server2, server3",
|
|
97
|
+
"username": "username",
|
|
98
|
+
"password": "******",
|
|
99
|
+
"topic": "your topic",
|
|
100
|
+
"...": "..."
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
使用形式:
|
|
107
|
+
```shell
|
|
108
|
+
python -u service 2>&1 | tee {log_file_path} | liblogging_collector --config-path {your_kafka_path} --ssl-cafile {your_ssl_cafile_path} --send-kafka
|
|
109
|
+
```
|
|
110
|
+
tee {log_file_path} 可以将你的程序记录(输出+错误)重定向到文件中(可选)。
|
|
111
|
+
|
|
112
|
+
[log_collector.py](liblogging/sending/log_collector.py)为`liblogging_collector`的源代码地址。
|
|
113
|
+
|
|
114
|
+
`env_name`不指定的话,默认读取`os.environ.get("CHAT_ENV", "dev")`.
|
|
115
|
+
|
|
116
|
+
## 📋Example
|
|
117
|
+
增加额外记录字段信息,以及搭配[libentry](https://github.com/XoriieInpottn/libentry)使用的样例见 [example](example)。
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
## 💡Tips
|
|
121
|
+
|
|
122
|
+
1. If using Kafka to send messages, please use `pip install liblogging[collector]`.
|
|
123
|
+
2. 如果需要数据持久化,推荐日志消息都写在message列中,维护一列节省内存空间。需要后续进行查询的,以字典形式记录,比如logger.info({"key": "value"}), 便于后续查找。
|
|
124
|
+
|
|
125
|
+
3. 当前默认的trace_id,推荐使用[liblogging/util.py](liblogging/util.py)中的`get_trace_id`函数,该函数会根据请求对象的`uid`, `session_id`, `turn`等字段生成trace_id,默认的[liblogging/sending/log_collector.py](liblogging/sending/log_collector.py)也会根据trace_id拆解`uid`, `session_id`, `turn`,根据`create_time`拆解`create_date`,方便后续进行追溯以及数据存储。以下是构建trace_id的在整个服务入口的示例:
|
|
126
|
+
```python
|
|
127
|
+
from liblogging.util import get_trace_id
|
|
128
|
+
|
|
129
|
+
class Request(BaseModel):
|
|
130
|
+
uid: str = Field(..., description="用户id")
|
|
131
|
+
session_id: str = Field(..., description="会话id")
|
|
132
|
+
turn: int = Field(..., description="轮次")
|
|
133
|
+
trace_id: str = Field(..., description="trace_id")
|
|
134
|
+
|
|
135
|
+
@log_request("trace_id", "message_source")
|
|
136
|
+
def set_logger_global_vars(trace_id: str, message_source: str):
|
|
137
|
+
print(f"setting global vars: trace_id={trace_id}, message_source={message_source}")
|
|
138
|
+
|
|
139
|
+
def run():
|
|
140
|
+
trace_id = get_trace_id(request)
|
|
141
|
+
# 设置全局上下文变量, 这里注意需要以trace_id=xxx, message_source=xxx形式显式传入
|
|
142
|
+
set_logger_global_vars(trace_id=trace_id, message_source="demo")
|
|
143
|
+
request.trace_id = trace_id
|
|
144
|
+
# 可以直接给其他服务传入request对象,后续的logger.info会自动记录trace_id,其他服务需要在服务入口使用@log_request装饰器配置trace_id, message_source等全局上下文变量。可见example/service.py
|
|
145
|
+
your_service_entry(request)
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
run()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
4. liblogging提供了一些常用的,比如logger.tool_start, logger.tool_end, logger.track_start, logger.track_end等。
|
|
152
|
+
|
|
153
|
+
(1) 默认message列就是当使用`logger.info(<message>)`时,message的值。
|
|
154
|
+
|
|
155
|
+
(2) 从本质上可以理解为当info的内容是字典时,字典的key就是表中的列名,value就是列的值,而使用liblogging默认这一套 `trace_id`, ``create_time`, `create_date`, `uid`, `session_id`, `turn`等字段会自动添加.
|
|
156
|
+
|
|
157
|
+
(3) 如果需要统计相应的字段推荐这种方式,方便后续进行查询。
|
|
158
|
+
```python
|
|
159
|
+
logger.info({
|
|
160
|
+
"message": {"key1": "value1", "key2": "value2"}, # message列的内容,liblogging将json序列化后存储
|
|
161
|
+
"message_type": "<your message_type>" # message_type列方便后续进行查询
|
|
162
|
+
})
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
由log_collector.py默认的数据表结构如下(如果有额外的字段,创建表时和log时的key保持一致即可):
|
|
167
|
+
```sql
|
|
168
|
+
CREATE TABLE `agent_log`.`your_table_name(需要和message_source一致)` (
|
|
169
|
+
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
|
170
|
+
`uid` varchar(64) NOT NULL DEFAULT '',
|
|
171
|
+
`session_id` varchar(128) NOT NULL DEFAULT '',
|
|
172
|
+
`turn` smallint NOT NULL DEFAULT '0',
|
|
173
|
+
`trace_id` varchar(255) NOT NULL DEFAULT '',
|
|
174
|
+
`create_date` date NOT NULL,
|
|
175
|
+
`create_time` datetime(3) NOT NULL,
|
|
176
|
+
`insert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
|
|
177
|
+
`line_info` varchar(255) NOT NULL DEFAULT '' COMMENT '对应代码行信息',
|
|
178
|
+
`message_source` varchar(64) NOT NULL DEFAULT '' COMMENT '消息来源:plan, memory, intent, guess question等,对应表名',
|
|
179
|
+
`message_type` varchar(32) NOT NULL DEFAULT '' COMMENT '消息类型, 可以筛选该key获取相关指标信息',
|
|
180
|
+
`message` text,
|
|
181
|
+
`level` varchar(32) NOT NULL DEFAULT '' COMMENT 'info, warning, error等',
|
|
182
|
+
PRIMARY KEY (`id`,`create_date`),
|
|
183
|
+
KEY `session_id_index` (`session_id`)
|
|
184
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
|
|
185
|
+
PARTITION BY RANGE (TO_DAYS(create_date)) (
|
|
186
|
+
PARTITION p202507 VALUES LESS THAN (TO_DAYS('2025-08-01')),
|
|
187
|
+
PARTITION p202508 VALUES LESS THAN (TO_DAYS('2025-09-01')),
|
|
188
|
+
PARTITION p202509 VALUES LESS THAN (TO_DAYS('2025-10-01')),
|
|
189
|
+
PARTITION p202510 VALUES LESS THAN (TO_DAYS('2025-11-01')),
|
|
190
|
+
PARTITION p202511 VALUES LESS THAN (TO_DAYS('2025-12-01')),
|
|
191
|
+
PARTITION p202512 VALUES LESS THAN (TO_DAYS('2026-01-01')),
|
|
192
|
+
PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')),
|
|
193
|
+
PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')),
|
|
194
|
+
PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')),
|
|
195
|
+
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
|
|
196
|
+
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')),
|
|
197
|
+
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
|
|
198
|
+
PARTITION p202607 VALUES LESS THAN (TO_DAYS('2026-08-01')),
|
|
199
|
+
PARTITION p202608 VALUES LESS THAN (TO_DAYS('2026-09-01')),
|
|
200
|
+
PARTITION p202609 VALUES LESS THAN (TO_DAYS('2026-10-01')),
|
|
201
|
+
PARTITION p202610 VALUES LESS THAN (TO_DAYS('2026-11-01')),
|
|
202
|
+
PARTITION p202611 VALUES LESS THAN (TO_DAYS('2026-12-01')),
|
|
203
|
+
PARTITION p202612 VALUES LESS THAN (TO_DAYS('2027-01-01')),
|
|
204
|
+
PARTITION pMaxRange VALUES LESS THAN MAXVALUE
|
|
205
|
+
);
|
|
206
|
+
```
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# liblogging
|
|
2
|
+
[](https://deepwiki.com/XoriieInpottn/liblogging)
|
|
3
|
+
|
|
4
|
+
Utilities for logging and sending logs.
|
|
5
|
+
```shell
|
|
6
|
+
pip install liblogging
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## 🌟Feature
|
|
10
|
+
### 统一日志格式记录
|
|
11
|
+
统一了当前agent的日志记录格式,也可自己基于默认格式进行拓展。
|
|
12
|
+
当前记录的信息和对应的key如下:
|
|
13
|
+
```python
|
|
14
|
+
{
|
|
15
|
+
"create_time": "时间戳,默认和mysql列datatime(3)保持一致",
|
|
16
|
+
"level": "like INFO, ERROR, WARNING",
|
|
17
|
+
# 通过上下文变量保存trace_id
|
|
18
|
+
"trace_id": "trace_id for 追溯不同服务的调用链路",
|
|
19
|
+
"line_info": "{record.filename}:{record.lineno}:{record.funcName}",
|
|
20
|
+
"message": message,
|
|
21
|
+
# 通过上下文变量区分不同源, 方便接收不同服务源信息, 比如Chat, Welcome, Planning等
|
|
22
|
+
"message_source": context.get("message_source", "chat_log"),
|
|
23
|
+
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
24
|
+
"message_type": message_type,
|
|
25
|
+
# 可以根据自己需求加入其他的字段
|
|
26
|
+
**extra_message
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
上述日志信息均以json字符串的形式记录下来,方便存储及后续处理。
|
|
30
|
+
|
|
31
|
+
### 配置上下文变量,无须重复传参显示记录
|
|
32
|
+
通过装饰器形式, 指定需要配置的全局上下文变量, 仅需在整个程序/服务入口配置一次即可。
|
|
33
|
+
|
|
34
|
+
需要注意的是配置的全局上下文变量,根据加入装饰器下的函数入参名称匹配进行更新,推荐函数参数定义使用`BaseModel`。
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
主程序/服务: service1.py
|
|
38
|
+
from pydantic import BaseModel
|
|
39
|
+
|
|
40
|
+
from liblogging import log_request,logger
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Request(BaseModel):
|
|
44
|
+
name: str
|
|
45
|
+
trace_id: str
|
|
46
|
+
|
|
47
|
+
#在主程序入口配置了trace_id这一全局上下文变量,会通过函数入参对该字段进行赋值,后续在该服务下的其他程序logger.info时会读取这一变量并记录下来。
|
|
48
|
+
#同时也支持默认参数配置,比如message_source设置了默认值,后续使用logger会记录message_source为"demo"。
|
|
49
|
+
@log_request("trace_id", message_source="demo")
|
|
50
|
+
def your_service_entry(request: Request):
|
|
51
|
+
logger.info("Processing request")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
该服务下的其他程序: function1.py,可直接logger.info(). trace_id, message_source均会记录下来。
|
|
56
|
+
from liblogging import logger
|
|
57
|
+
|
|
58
|
+
def test(name):
|
|
59
|
+
logger.info(f"Testing {name}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 重定向并发送到消息队列
|
|
63
|
+
以默认集成的kafka为例,可将上述统一日志格式记录的形式发送至kafka。
|
|
64
|
+
|
|
65
|
+
kafka 配置文件格式:
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"{cluster_name}": {
|
|
69
|
+
"{env_name}": {
|
|
70
|
+
"bootstrap_servers": "server1, server2, server3",
|
|
71
|
+
"username": "username",
|
|
72
|
+
"password": "******",
|
|
73
|
+
"topic": "your topic",
|
|
74
|
+
"...": "..."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
使用形式:
|
|
81
|
+
```shell
|
|
82
|
+
python -u service 2>&1 | tee {log_file_path} | liblogging_collector --config-path {your_kafka_path} --ssl-cafile {your_ssl_cafile_path} --send-kafka
|
|
83
|
+
```
|
|
84
|
+
tee {log_file_path} 可以将你的程序记录(输出+错误)重定向到文件中(可选)。
|
|
85
|
+
|
|
86
|
+
[log_collector.py](liblogging/sending/log_collector.py)为`liblogging_collector`的源代码地址。
|
|
87
|
+
|
|
88
|
+
`env_name`不指定的话,默认读取`os.environ.get("CHAT_ENV", "dev")`.
|
|
89
|
+
|
|
90
|
+
## 📋Example
|
|
91
|
+
增加额外记录字段信息,以及搭配[libentry](https://github.com/XoriieInpottn/libentry)使用的样例见 [example](example)。
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
## 💡Tips
|
|
95
|
+
|
|
96
|
+
1. If using Kafka to send messages, please use `pip install liblogging[collector]`.
|
|
97
|
+
2. 如果需要数据持久化,推荐日志消息都写在message列中,维护一列节省内存空间。需要后续进行查询的,以字典形式记录,比如logger.info({"key": "value"}), 便于后续查找。
|
|
98
|
+
|
|
99
|
+
3. 当前默认的trace_id,推荐使用[liblogging/util.py](liblogging/util.py)中的`get_trace_id`函数,该函数会根据请求对象的`uid`, `session_id`, `turn`等字段生成trace_id,默认的[liblogging/sending/log_collector.py](liblogging/sending/log_collector.py)也会根据trace_id拆解`uid`, `session_id`, `turn`,根据`create_time`拆解`create_date`,方便后续进行追溯以及数据存储。以下是构建trace_id的在整个服务入口的示例:
|
|
100
|
+
```python
|
|
101
|
+
from liblogging.util import get_trace_id
|
|
102
|
+
|
|
103
|
+
class Request(BaseModel):
|
|
104
|
+
uid: str = Field(..., description="用户id")
|
|
105
|
+
session_id: str = Field(..., description="会话id")
|
|
106
|
+
turn: int = Field(..., description="轮次")
|
|
107
|
+
trace_id: str = Field(..., description="trace_id")
|
|
108
|
+
|
|
109
|
+
@log_request("trace_id", "message_source")
|
|
110
|
+
def set_logger_global_vars(trace_id: str, message_source: str):
|
|
111
|
+
print(f"setting global vars: trace_id={trace_id}, message_source={message_source}")
|
|
112
|
+
|
|
113
|
+
def run():
|
|
114
|
+
trace_id = get_trace_id(request)
|
|
115
|
+
# 设置全局上下文变量, 这里注意需要以trace_id=xxx, message_source=xxx形式显式传入
|
|
116
|
+
set_logger_global_vars(trace_id=trace_id, message_source="demo")
|
|
117
|
+
request.trace_id = trace_id
|
|
118
|
+
# 可以直接给其他服务传入request对象,后续的logger.info会自动记录trace_id,其他服务需要在服务入口使用@log_request装饰器配置trace_id, message_source等全局上下文变量。可见example/service.py
|
|
119
|
+
your_service_entry(request)
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
run()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
4. liblogging提供了一些常用的,比如logger.tool_start, logger.tool_end, logger.track_start, logger.track_end等。
|
|
126
|
+
|
|
127
|
+
(1) 默认message列就是当使用`logger.info(<message>)`时,message的值。
|
|
128
|
+
|
|
129
|
+
(2) 从本质上可以理解为当info的内容是字典时,字典的key就是表中的列名,value就是列的值,而使用liblogging默认这一套 `trace_id`, ``create_time`, `create_date`, `uid`, `session_id`, `turn`等字段会自动添加.
|
|
130
|
+
|
|
131
|
+
(3) 如果需要统计相应的字段推荐这种方式,方便后续进行查询。
|
|
132
|
+
```python
|
|
133
|
+
logger.info({
|
|
134
|
+
"message": {"key1": "value1", "key2": "value2"}, # message列的内容,liblogging将json序列化后存储
|
|
135
|
+
"message_type": "<your message_type>" # message_type列方便后续进行查询
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
由log_collector.py默认的数据表结构如下(如果有额外的字段,创建表时和log时的key保持一致即可):
|
|
141
|
+
```sql
|
|
142
|
+
CREATE TABLE `agent_log`.`your_table_name(需要和message_source一致)` (
|
|
143
|
+
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
|
144
|
+
`uid` varchar(64) NOT NULL DEFAULT '',
|
|
145
|
+
`session_id` varchar(128) NOT NULL DEFAULT '',
|
|
146
|
+
`turn` smallint NOT NULL DEFAULT '0',
|
|
147
|
+
`trace_id` varchar(255) NOT NULL DEFAULT '',
|
|
148
|
+
`create_date` date NOT NULL,
|
|
149
|
+
`create_time` datetime(3) NOT NULL,
|
|
150
|
+
`insert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
|
|
151
|
+
`line_info` varchar(255) NOT NULL DEFAULT '' COMMENT '对应代码行信息',
|
|
152
|
+
`message_source` varchar(64) NOT NULL DEFAULT '' COMMENT '消息来源:plan, memory, intent, guess question等,对应表名',
|
|
153
|
+
`message_type` varchar(32) NOT NULL DEFAULT '' COMMENT '消息类型, 可以筛选该key获取相关指标信息',
|
|
154
|
+
`message` text,
|
|
155
|
+
`level` varchar(32) NOT NULL DEFAULT '' COMMENT 'info, warning, error等',
|
|
156
|
+
PRIMARY KEY (`id`,`create_date`),
|
|
157
|
+
KEY `session_id_index` (`session_id`)
|
|
158
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
|
|
159
|
+
PARTITION BY RANGE (TO_DAYS(create_date)) (
|
|
160
|
+
PARTITION p202507 VALUES LESS THAN (TO_DAYS('2025-08-01')),
|
|
161
|
+
PARTITION p202508 VALUES LESS THAN (TO_DAYS('2025-09-01')),
|
|
162
|
+
PARTITION p202509 VALUES LESS THAN (TO_DAYS('2025-10-01')),
|
|
163
|
+
PARTITION p202510 VALUES LESS THAN (TO_DAYS('2025-11-01')),
|
|
164
|
+
PARTITION p202511 VALUES LESS THAN (TO_DAYS('2025-12-01')),
|
|
165
|
+
PARTITION p202512 VALUES LESS THAN (TO_DAYS('2026-01-01')),
|
|
166
|
+
PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')),
|
|
167
|
+
PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')),
|
|
168
|
+
PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')),
|
|
169
|
+
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
|
|
170
|
+
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')),
|
|
171
|
+
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
|
|
172
|
+
PARTITION p202607 VALUES LESS THAN (TO_DAYS('2026-08-01')),
|
|
173
|
+
PARTITION p202608 VALUES LESS THAN (TO_DAYS('2026-09-01')),
|
|
174
|
+
PARTITION p202609 VALUES LESS THAN (TO_DAYS('2026-10-01')),
|
|
175
|
+
PARTITION p202610 VALUES LESS THAN (TO_DAYS('2026-11-01')),
|
|
176
|
+
PARTITION p202611 VALUES LESS THAN (TO_DAYS('2026-12-01')),
|
|
177
|
+
PARTITION p202612 VALUES LESS THAN (TO_DAYS('2027-01-01')),
|
|
178
|
+
PARTITION pMaxRange VALUES LESS THAN MAXVALUE
|
|
179
|
+
);
|
|
180
|
+
```
|
|
@@ -48,12 +48,29 @@ except ImportError:
|
|
|
48
48
|
tqdm = None
|
|
49
49
|
from logging import StreamHandler
|
|
50
50
|
|
|
51
|
+
_old_thread_init = threading.Thread.__init__
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _wrapped_thread_init(self, *args, **kwargs):
|
|
55
|
+
co_local = thread_local._co_local.get()
|
|
56
|
+
if co_local is not None:
|
|
57
|
+
setattr(self, "_dict_for_logging", {**co_local})
|
|
58
|
+
return _old_thread_init(self, *args, **kwargs)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
threading.Thread.__init__ = _wrapped_thread_init
|
|
62
|
+
|
|
51
63
|
|
|
52
64
|
class ThreadCoroutineLocal(threading.local):
|
|
53
65
|
|
|
54
66
|
def __init__(self):
|
|
55
67
|
super().__init__()
|
|
56
68
|
self._co_local = ContextVar[Optional[Dict]]("_co_local", default=None)
|
|
69
|
+
ct = threading.current_thread()
|
|
70
|
+
if hasattr(ct, "_dict_for_logging"):
|
|
71
|
+
co_local = self.co_local
|
|
72
|
+
for k, v in getattr(ct, "_dict_for_logging").items():
|
|
73
|
+
co_local[k] = v
|
|
57
74
|
|
|
58
75
|
@property
|
|
59
76
|
def co_local(self):
|
|
@@ -133,12 +150,18 @@ class ContextJSONFormatter(Formatter):
|
|
|
133
150
|
"line_info": f"{record.filename}:{record.lineno}:{record.funcName}",
|
|
134
151
|
# 日志消息
|
|
135
152
|
"message": message,
|
|
136
|
-
# 通过上下文变量控制不同源,
|
|
153
|
+
# 通过上下文变量控制不同源, 比如Intent,Planning等,写入不同的表
|
|
137
154
|
"message_source": context.get("message_source", "chat_log"),
|
|
138
155
|
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
139
156
|
"message_type": message_type,
|
|
140
157
|
**extra_message
|
|
141
158
|
}
|
|
159
|
+
# 自动将 context 里未出现在 log_data/extra_message 的 key 加入 extra_message
|
|
160
|
+
for k, v in context.items():
|
|
161
|
+
if k not in log_data and k not in extra_message:
|
|
162
|
+
extra_message[k] = v
|
|
163
|
+
# 重新组装 log_data,确保 extra_message 最新
|
|
164
|
+
log_data.update(extra_message)
|
|
142
165
|
try:
|
|
143
166
|
output_log = json.dumps(log_data, ensure_ascii=False)
|
|
144
167
|
except TypeError:
|
|
@@ -186,14 +209,14 @@ class Logger(logging.Logger):
|
|
|
186
209
|
self.addHandler(console_handler)
|
|
187
210
|
|
|
188
211
|
def track_start(
|
|
189
|
-
|
|
212
|
+
self, message: Union[str, Mapping], message_type: str = "on_track_start", stacklevel: int = 2, **kwargs
|
|
190
213
|
):
|
|
191
214
|
self._log(
|
|
192
215
|
logging.INFO, {"message": message, "message_type": message_type, **kwargs}, (), stacklevel=stacklevel
|
|
193
216
|
)
|
|
194
217
|
|
|
195
218
|
def track_end(
|
|
196
|
-
|
|
219
|
+
self, message: Union[str, Mapping], message_type: str = "on_track_end", stacklevel: int = 2, **kwargs
|
|
197
220
|
):
|
|
198
221
|
self._log(
|
|
199
222
|
logging.INFO, {"message": message, "message_type": message_type, **kwargs}, (), stacklevel=stacklevel
|
|
@@ -228,12 +251,12 @@ class Logger(logging.Logger):
|
|
|
228
251
|
)
|
|
229
252
|
|
|
230
253
|
def llm_start(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
254
|
+
self,
|
|
255
|
+
llm_chain_name: str,
|
|
256
|
+
messages: Sequence[Mapping],
|
|
257
|
+
template_info: Mapping,
|
|
258
|
+
model_kwargs: Mapping = None,
|
|
259
|
+
**kwargs
|
|
237
260
|
):
|
|
238
261
|
log_info_dict = {
|
|
239
262
|
"func_name": llm_chain_name,
|
|
@@ -249,19 +272,19 @@ class Logger(logging.Logger):
|
|
|
249
272
|
)
|
|
250
273
|
|
|
251
274
|
def llm_end(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
275
|
+
self,
|
|
276
|
+
llm_name: str,
|
|
277
|
+
content: str,
|
|
278
|
+
execute_time: float,
|
|
279
|
+
completion_tokens: int = None,
|
|
280
|
+
prompt_tokens: int = None,
|
|
281
|
+
role: str = "assistant",
|
|
282
|
+
**kwargs
|
|
260
283
|
):
|
|
261
284
|
log_info_dict = {
|
|
262
285
|
"func_name": llm_name,
|
|
263
286
|
"response": {"role": role, "content": content},
|
|
264
|
-
"
|
|
287
|
+
"completion_tokens": completion_tokens,
|
|
265
288
|
"prompt_tokens": prompt_tokens,
|
|
266
289
|
"duration": round(execute_time, 3)
|
|
267
290
|
}
|
|
@@ -53,9 +53,10 @@ class LogCollector:
|
|
|
53
53
|
):
|
|
54
54
|
while True:
|
|
55
55
|
try:
|
|
56
|
-
line = sys.stdin.readline()
|
|
56
|
+
line = sys.stdin.readline()
|
|
57
57
|
if not line:
|
|
58
|
-
|
|
58
|
+
break
|
|
59
|
+
line = line.strip()
|
|
59
60
|
try:
|
|
60
61
|
if use_default_process:
|
|
61
62
|
trace_id, message = process_message(line)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: liblogging
|
|
3
|
+
Version: 0.1.16
|
|
4
|
+
Summary: Utilities for logging and sending logs.
|
|
5
|
+
Home-page: https://github.com/XoriieInpottn/liblogging
|
|
6
|
+
Author: xi
|
|
7
|
+
Author-email: gylv@mail.ustc.edu.cn, huangfuyb@163.com
|
|
8
|
+
License: Apache-2.0 license
|
|
9
|
+
Platform: any
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Provides-Extra: collector
|
|
14
|
+
Requires-Dist: kafka-python==2.0.2; extra == "collector"
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: platform
|
|
24
|
+
Dynamic: provides-extra
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
# liblogging
|
|
28
|
+
[](https://deepwiki.com/XoriieInpottn/liblogging)
|
|
29
|
+
|
|
30
|
+
Utilities for logging and sending logs.
|
|
31
|
+
```shell
|
|
32
|
+
pip install liblogging
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🌟Feature
|
|
36
|
+
### 统一日志格式记录
|
|
37
|
+
统一了当前agent的日志记录格式,也可自己基于默认格式进行拓展。
|
|
38
|
+
当前记录的信息和对应的key如下:
|
|
39
|
+
```python
|
|
40
|
+
{
|
|
41
|
+
"create_time": "时间戳,默认和mysql列datatime(3)保持一致",
|
|
42
|
+
"level": "like INFO, ERROR, WARNING",
|
|
43
|
+
# 通过上下文变量保存trace_id
|
|
44
|
+
"trace_id": "trace_id for 追溯不同服务的调用链路",
|
|
45
|
+
"line_info": "{record.filename}:{record.lineno}:{record.funcName}",
|
|
46
|
+
"message": message,
|
|
47
|
+
# 通过上下文变量区分不同源, 方便接收不同服务源信息, 比如Chat, Welcome, Planning等
|
|
48
|
+
"message_source": context.get("message_source", "chat_log"),
|
|
49
|
+
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
50
|
+
"message_type": message_type,
|
|
51
|
+
# 可以根据自己需求加入其他的字段
|
|
52
|
+
**extra_message
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
上述日志信息均以json字符串的形式记录下来,方便存储及后续处理。
|
|
56
|
+
|
|
57
|
+
### 配置上下文变量,无须重复传参显示记录
|
|
58
|
+
通过装饰器形式, 指定需要配置的全局上下文变量, 仅需在整个程序/服务入口配置一次即可。
|
|
59
|
+
|
|
60
|
+
需要注意的是配置的全局上下文变量,根据加入装饰器下的函数入参名称匹配进行更新,推荐函数参数定义使用`BaseModel`。
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
主程序/服务: service1.py
|
|
64
|
+
from pydantic import BaseModel
|
|
65
|
+
|
|
66
|
+
from liblogging import log_request,logger
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Request(BaseModel):
|
|
70
|
+
name: str
|
|
71
|
+
trace_id: str
|
|
72
|
+
|
|
73
|
+
#在主程序入口配置了trace_id这一全局上下文变量,会通过函数入参对该字段进行赋值,后续在该服务下的其他程序logger.info时会读取这一变量并记录下来。
|
|
74
|
+
#同时也支持默认参数配置,比如message_source设置了默认值,后续使用logger会记录message_source为"demo"。
|
|
75
|
+
@log_request("trace_id", message_source="demo")
|
|
76
|
+
def your_service_entry(request: Request):
|
|
77
|
+
logger.info("Processing request")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
该服务下的其他程序: function1.py,可直接logger.info(). trace_id, message_source均会记录下来。
|
|
82
|
+
from liblogging import logger
|
|
83
|
+
|
|
84
|
+
def test(name):
|
|
85
|
+
logger.info(f"Testing {name}")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 重定向并发送到消息队列
|
|
89
|
+
以默认集成的kafka为例,可将上述统一日志格式记录的形式发送至kafka。
|
|
90
|
+
|
|
91
|
+
kafka 配置文件格式:
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"{cluster_name}": {
|
|
95
|
+
"{env_name}": {
|
|
96
|
+
"bootstrap_servers": "server1, server2, server3",
|
|
97
|
+
"username": "username",
|
|
98
|
+
"password": "******",
|
|
99
|
+
"topic": "your topic",
|
|
100
|
+
"...": "..."
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
使用形式:
|
|
107
|
+
```shell
|
|
108
|
+
python -u service 2>&1 | tee {log_file_path} | liblogging_collector --config-path {your_kafka_path} --ssl-cafile {your_ssl_cafile_path} --send-kafka
|
|
109
|
+
```
|
|
110
|
+
tee {log_file_path} 可以将你的程序记录(输出+错误)重定向到文件中(可选)。
|
|
111
|
+
|
|
112
|
+
[log_collector.py](liblogging/sending/log_collector.py)为`liblogging_collector`的源代码地址。
|
|
113
|
+
|
|
114
|
+
`env_name`不指定的话,默认读取`os.environ.get("CHAT_ENV", "dev")`.
|
|
115
|
+
|
|
116
|
+
## 📋Example
|
|
117
|
+
增加额外记录字段信息,以及搭配[libentry](https://github.com/XoriieInpottn/libentry)使用的样例见 [example](example)。
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
## 💡Tips
|
|
121
|
+
|
|
122
|
+
1. If using Kafka to send messages, please use `pip install liblogging[collector]`.
|
|
123
|
+
2. 如果需要数据持久化,推荐日志消息都写在message列中,维护一列节省内存空间。需要后续进行查询的,以字典形式记录,比如logger.info({"key": "value"}), 便于后续查找。
|
|
124
|
+
|
|
125
|
+
3. 当前默认的trace_id,推荐使用[liblogging/util.py](liblogging/util.py)中的`get_trace_id`函数,该函数会根据请求对象的`uid`, `session_id`, `turn`等字段生成trace_id,默认的[liblogging/sending/log_collector.py](liblogging/sending/log_collector.py)也会根据trace_id拆解`uid`, `session_id`, `turn`,根据`create_time`拆解`create_date`,方便后续进行追溯以及数据存储。以下是构建trace_id的在整个服务入口的示例:
|
|
126
|
+
```python
|
|
127
|
+
from liblogging.util import get_trace_id
|
|
128
|
+
|
|
129
|
+
class Request(BaseModel):
|
|
130
|
+
uid: str = Field(..., description="用户id")
|
|
131
|
+
session_id: str = Field(..., description="会话id")
|
|
132
|
+
turn: int = Field(..., description="轮次")
|
|
133
|
+
trace_id: str = Field(..., description="trace_id")
|
|
134
|
+
|
|
135
|
+
@log_request("trace_id", "message_source")
|
|
136
|
+
def set_logger_global_vars(trace_id: str, message_source: str):
|
|
137
|
+
print(f"setting global vars: trace_id={trace_id}, message_source={message_source}")
|
|
138
|
+
|
|
139
|
+
def run():
|
|
140
|
+
trace_id = get_trace_id(request)
|
|
141
|
+
# 设置全局上下文变量, 这里注意需要以trace_id=xxx, message_source=xxx形式显式传入
|
|
142
|
+
set_logger_global_vars(trace_id=trace_id, message_source="demo")
|
|
143
|
+
request.trace_id = trace_id
|
|
144
|
+
# 可以直接给其他服务传入request对象,后续的logger.info会自动记录trace_id,其他服务需要在服务入口使用@log_request装饰器配置trace_id, message_source等全局上下文变量。可见example/service.py
|
|
145
|
+
your_service_entry(request)
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
run()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
4. liblogging提供了一些常用的,比如logger.tool_start, logger.tool_end, logger.track_start, logger.track_end等。
|
|
152
|
+
|
|
153
|
+
(1) 默认message列就是当使用`logger.info(<message>)`时,message的值。
|
|
154
|
+
|
|
155
|
+
(2) 从本质上可以理解为当info的内容是字典时,字典的key就是表中的列名,value就是列的值,而使用liblogging默认这一套 `trace_id`, ``create_time`, `create_date`, `uid`, `session_id`, `turn`等字段会自动添加.
|
|
156
|
+
|
|
157
|
+
(3) 如果需要统计相应的字段推荐这种方式,方便后续进行查询。
|
|
158
|
+
```python
|
|
159
|
+
logger.info({
|
|
160
|
+
"message": {"key1": "value1", "key2": "value2"}, # message列的内容,liblogging将json序列化后存储
|
|
161
|
+
"message_type": "<your message_type>" # message_type列方便后续进行查询
|
|
162
|
+
})
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
由log_collector.py默认的数据表结构如下(如果有额外的字段,创建表时和log时的key保持一致即可):
|
|
167
|
+
```sql
|
|
168
|
+
CREATE TABLE `agent_log`.`your_table_name(需要和message_source一致)` (
|
|
169
|
+
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
|
170
|
+
`uid` varchar(64) NOT NULL DEFAULT '',
|
|
171
|
+
`session_id` varchar(128) NOT NULL DEFAULT '',
|
|
172
|
+
`turn` smallint NOT NULL DEFAULT '0',
|
|
173
|
+
`trace_id` varchar(255) NOT NULL DEFAULT '',
|
|
174
|
+
`create_date` date NOT NULL,
|
|
175
|
+
`create_time` datetime(3) NOT NULL,
|
|
176
|
+
`insert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
|
|
177
|
+
`line_info` varchar(255) NOT NULL DEFAULT '' COMMENT '对应代码行信息',
|
|
178
|
+
`message_source` varchar(64) NOT NULL DEFAULT '' COMMENT '消息来源:plan, memory, intent, guess question等,对应表名',
|
|
179
|
+
`message_type` varchar(32) NOT NULL DEFAULT '' COMMENT '消息类型, 可以筛选该key获取相关指标信息',
|
|
180
|
+
`message` text,
|
|
181
|
+
`level` varchar(32) NOT NULL DEFAULT '' COMMENT 'info, warning, error等',
|
|
182
|
+
PRIMARY KEY (`id`,`create_date`),
|
|
183
|
+
KEY `session_id_index` (`session_id`)
|
|
184
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
|
|
185
|
+
PARTITION BY RANGE (TO_DAYS(create_date)) (
|
|
186
|
+
PARTITION p202507 VALUES LESS THAN (TO_DAYS('2025-08-01')),
|
|
187
|
+
PARTITION p202508 VALUES LESS THAN (TO_DAYS('2025-09-01')),
|
|
188
|
+
PARTITION p202509 VALUES LESS THAN (TO_DAYS('2025-10-01')),
|
|
189
|
+
PARTITION p202510 VALUES LESS THAN (TO_DAYS('2025-11-01')),
|
|
190
|
+
PARTITION p202511 VALUES LESS THAN (TO_DAYS('2025-12-01')),
|
|
191
|
+
PARTITION p202512 VALUES LESS THAN (TO_DAYS('2026-01-01')),
|
|
192
|
+
PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')),
|
|
193
|
+
PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01')),
|
|
194
|
+
PARTITION p202603 VALUES LESS THAN (TO_DAYS('2026-04-01')),
|
|
195
|
+
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
|
|
196
|
+
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01')),
|
|
197
|
+
PARTITION p202606 VALUES LESS THAN (TO_DAYS('2026-07-01')),
|
|
198
|
+
PARTITION p202607 VALUES LESS THAN (TO_DAYS('2026-08-01')),
|
|
199
|
+
PARTITION p202608 VALUES LESS THAN (TO_DAYS('2026-09-01')),
|
|
200
|
+
PARTITION p202609 VALUES LESS THAN (TO_DAYS('2026-10-01')),
|
|
201
|
+
PARTITION p202610 VALUES LESS THAN (TO_DAYS('2026-11-01')),
|
|
202
|
+
PARTITION p202611 VALUES LESS THAN (TO_DAYS('2026-12-01')),
|
|
203
|
+
PARTITION p202612 VALUES LESS THAN (TO_DAYS('2027-01-01')),
|
|
204
|
+
PARTITION pMaxRange VALUES LESS THAN MAXVALUE
|
|
205
|
+
);
|
|
206
|
+
```
|
|
@@ -18,7 +18,7 @@ if __name__ == '__main__':
|
|
|
18
18
|
'liblogging_collector = liblogging.sending.log_collector:main'
|
|
19
19
|
]
|
|
20
20
|
},
|
|
21
|
-
version='0.1.
|
|
21
|
+
version='0.1.16',
|
|
22
22
|
description='Utilities for logging and sending logs.',
|
|
23
23
|
long_description_content_type='text/markdown',
|
|
24
24
|
long_description=long_description,
|
liblogging-0.1.13/PKG-INFO
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: liblogging
|
|
3
|
-
Version: 0.1.13
|
|
4
|
-
Summary: Utilities for logging and sending logs.
|
|
5
|
-
Home-page: https://github.com/XoriieInpottn/liblogging
|
|
6
|
-
Author: xi
|
|
7
|
-
Author-email: gylv@mail.ustc.edu.cn, huangfuyb@163.com
|
|
8
|
-
License: Apache-2.0 license
|
|
9
|
-
Platform: any
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Provides-Extra: collector
|
|
14
|
-
Requires-Dist: kafka-python==2.0.2; extra == "collector"
|
|
15
|
-
Dynamic: author
|
|
16
|
-
Dynamic: author-email
|
|
17
|
-
Dynamic: classifier
|
|
18
|
-
Dynamic: description
|
|
19
|
-
Dynamic: description-content-type
|
|
20
|
-
Dynamic: home-page
|
|
21
|
-
Dynamic: license
|
|
22
|
-
Dynamic: license-file
|
|
23
|
-
Dynamic: platform
|
|
24
|
-
Dynamic: provides-extra
|
|
25
|
-
Dynamic: summary
|
|
26
|
-
|
|
27
|
-
# liblogging
|
|
28
|
-
|
|
29
|
-
Utilities for logging and sending logs.
|
|
30
|
-
```shell
|
|
31
|
-
pip install liblogging
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 🌟Feature
|
|
35
|
-
### 统一日志格式记录
|
|
36
|
-
统一了当前agent的日志记录格式,也可自己基于默认格式进行拓展。
|
|
37
|
-
当前记录的信息和对应的key如下:
|
|
38
|
-
```python
|
|
39
|
-
{
|
|
40
|
-
"create_time": "时间戳,默认和mysql列datatime(3)保持一致",
|
|
41
|
-
"level": "like INFO, ERROR, WARNING",
|
|
42
|
-
# 通过上下文变量保存trace_id
|
|
43
|
-
"trace_id": "trace_id for 追溯不同服务的调用链路",
|
|
44
|
-
"line_info": "{record.filename}:{record.lineno}:{record.funcName}",
|
|
45
|
-
"message": message,
|
|
46
|
-
# 通过上下文变量区分不同源, 方便接收不同服务源信息, 比如Chat, Welcome, Planning等
|
|
47
|
-
"message_source": context.get("message_source", "chat_log"),
|
|
48
|
-
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
49
|
-
"message_type": message_type,
|
|
50
|
-
# 可以根据自己需求加入其他的字段
|
|
51
|
-
**extra_message
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
上述日志信息均以json字符串的形式记录下来,方便存储及后续处理。
|
|
55
|
-
|
|
56
|
-
### 配置上下文变量,无须重复传参显示记录
|
|
57
|
-
通过装饰器形式, 指定需要配置的全局上下文变量, 仅需在整个程序/服务入口配置一次即可。
|
|
58
|
-
|
|
59
|
-
需要注意的是配置的全局上下文变量,根据加入装饰器下的函数入参名称匹配进行更新,推荐函数参数定义使用`BaseModel`。
|
|
60
|
-
|
|
61
|
-
```python
|
|
62
|
-
主程序/服务: service1.py
|
|
63
|
-
from pydantic import BaseModel
|
|
64
|
-
|
|
65
|
-
from liblogging import log_request,logger
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class Request(BaseModel):
|
|
69
|
-
name: str
|
|
70
|
-
trace_id: str
|
|
71
|
-
|
|
72
|
-
#在主程序入口配置了trace_id这一全局上下文变量,会通过函数入参对该字段进行赋值,后续在该服务下的其他程序logger.info时会读取这一变量并记录下来。
|
|
73
|
-
#同时也支持默认参数配置,比如message_source设置了默认值,后续使用logger会记录message_source为"demo"。
|
|
74
|
-
@log_request("trace_id", message_source="demo")
|
|
75
|
-
def your_service_entry(request: Request):
|
|
76
|
-
logger.info("Processing request")
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
```python
|
|
80
|
-
该服务下的其他程序: function1.py,可直接logger.info(). trace_id, message_source均会记录下来。
|
|
81
|
-
from liblogging import logger
|
|
82
|
-
|
|
83
|
-
def test(name):
|
|
84
|
-
logger.info(f"Testing {name}")
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 重定向并发送到消息队列
|
|
88
|
-
以默认集成的kafka为例,可将上述统一日志格式记录的形式发送至kafka。
|
|
89
|
-
|
|
90
|
-
kafka 配置文件格式:
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"{cluster_name}": {
|
|
94
|
-
"{env_name}": {
|
|
95
|
-
"bootstrap_servers": "server1, server2, server3",
|
|
96
|
-
"username": "username",
|
|
97
|
-
"password": "******",
|
|
98
|
-
"topic": "your topic",
|
|
99
|
-
"...": "..."
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
使用形式:
|
|
106
|
-
```shell
|
|
107
|
-
python service 2>&1 | tee {log_file_path} | liblogging_collector --config-path {your_kafka_path} --ssl-cafile {your_ssl_cafile_path} --send-kafka
|
|
108
|
-
```
|
|
109
|
-
tee {log_file_path} 可以将你的程序记录(输出+错误)重定向到文件中(可选)。
|
|
110
|
-
|
|
111
|
-
[log_collector.py](liblogging/sending/log_collector.py)为`liblogging_collector`的源代码地址。
|
|
112
|
-
|
|
113
|
-
`env_name`不指定的话,默认读取`os.environ.get("CHAT_ENV", "dev")`.
|
|
114
|
-
|
|
115
|
-
## 📋Example
|
|
116
|
-
增加额外记录字段信息,以及搭配[libentry](https://github.com/XoriieInpottn/libentry)使用的样例见 [example](example)。
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
## 💡Tips
|
|
120
|
-
|
|
121
|
-
1. If using Kafka to send messages, please use `pip install liblogging[collector]`.
|
|
122
|
-
2. 如果需要数据持久化,推荐日志消息都写在message列中,维护一列节省内存空间。需要后续进行查询的,以字典形式记录,比如logger.info({"key": "value"}), 便于后续查找。
|
liblogging-0.1.13/README.md
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# liblogging
|
|
2
|
-
|
|
3
|
-
Utilities for logging and sending logs.
|
|
4
|
-
```shell
|
|
5
|
-
pip install liblogging
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
## 🌟Feature
|
|
9
|
-
### 统一日志格式记录
|
|
10
|
-
统一了当前agent的日志记录格式,也可自己基于默认格式进行拓展。
|
|
11
|
-
当前记录的信息和对应的key如下:
|
|
12
|
-
```python
|
|
13
|
-
{
|
|
14
|
-
"create_time": "时间戳,默认和mysql列datatime(3)保持一致",
|
|
15
|
-
"level": "like INFO, ERROR, WARNING",
|
|
16
|
-
# 通过上下文变量保存trace_id
|
|
17
|
-
"trace_id": "trace_id for 追溯不同服务的调用链路",
|
|
18
|
-
"line_info": "{record.filename}:{record.lineno}:{record.funcName}",
|
|
19
|
-
"message": message,
|
|
20
|
-
# 通过上下文变量区分不同源, 方便接收不同服务源信息, 比如Chat, Welcome, Planning等
|
|
21
|
-
"message_source": context.get("message_source", "chat_log"),
|
|
22
|
-
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
23
|
-
"message_type": message_type,
|
|
24
|
-
# 可以根据自己需求加入其他的字段
|
|
25
|
-
**extra_message
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
上述日志信息均以json字符串的形式记录下来,方便存储及后续处理。
|
|
29
|
-
|
|
30
|
-
### 配置上下文变量,无须重复传参显示记录
|
|
31
|
-
通过装饰器形式, 指定需要配置的全局上下文变量, 仅需在整个程序/服务入口配置一次即可。
|
|
32
|
-
|
|
33
|
-
需要注意的是配置的全局上下文变量,根据加入装饰器下的函数入参名称匹配进行更新,推荐函数参数定义使用`BaseModel`。
|
|
34
|
-
|
|
35
|
-
```python
|
|
36
|
-
主程序/服务: service1.py
|
|
37
|
-
from pydantic import BaseModel
|
|
38
|
-
|
|
39
|
-
from liblogging import log_request,logger
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class Request(BaseModel):
|
|
43
|
-
name: str
|
|
44
|
-
trace_id: str
|
|
45
|
-
|
|
46
|
-
#在主程序入口配置了trace_id这一全局上下文变量,会通过函数入参对该字段进行赋值,后续在该服务下的其他程序logger.info时会读取这一变量并记录下来。
|
|
47
|
-
#同时也支持默认参数配置,比如message_source设置了默认值,后续使用logger会记录message_source为"demo"。
|
|
48
|
-
@log_request("trace_id", message_source="demo")
|
|
49
|
-
def your_service_entry(request: Request):
|
|
50
|
-
logger.info("Processing request")
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
```python
|
|
54
|
-
该服务下的其他程序: function1.py,可直接logger.info(). trace_id, message_source均会记录下来。
|
|
55
|
-
from liblogging import logger
|
|
56
|
-
|
|
57
|
-
def test(name):
|
|
58
|
-
logger.info(f"Testing {name}")
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 重定向并发送到消息队列
|
|
62
|
-
以默认集成的kafka为例,可将上述统一日志格式记录的形式发送至kafka。
|
|
63
|
-
|
|
64
|
-
kafka 配置文件格式:
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"{cluster_name}": {
|
|
68
|
-
"{env_name}": {
|
|
69
|
-
"bootstrap_servers": "server1, server2, server3",
|
|
70
|
-
"username": "username",
|
|
71
|
-
"password": "******",
|
|
72
|
-
"topic": "your topic",
|
|
73
|
-
"...": "..."
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
使用形式:
|
|
80
|
-
```shell
|
|
81
|
-
python service 2>&1 | tee {log_file_path} | liblogging_collector --config-path {your_kafka_path} --ssl-cafile {your_ssl_cafile_path} --send-kafka
|
|
82
|
-
```
|
|
83
|
-
tee {log_file_path} 可以将你的程序记录(输出+错误)重定向到文件中(可选)。
|
|
84
|
-
|
|
85
|
-
[log_collector.py](liblogging/sending/log_collector.py)为`liblogging_collector`的源代码地址。
|
|
86
|
-
|
|
87
|
-
`env_name`不指定的话,默认读取`os.environ.get("CHAT_ENV", "dev")`.
|
|
88
|
-
|
|
89
|
-
## 📋Example
|
|
90
|
-
增加额外记录字段信息,以及搭配[libentry](https://github.com/XoriieInpottn/libentry)使用的样例见 [example](example)。
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
## 💡Tips
|
|
94
|
-
|
|
95
|
-
1. If using Kafka to send messages, please use `pip install liblogging[collector]`.
|
|
96
|
-
2. 如果需要数据持久化,推荐日志消息都写在message列中,维护一列节省内存空间。需要后续进行查询的,以字典形式记录,比如logger.info({"key": "value"}), 便于后续查找。
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: liblogging
|
|
3
|
-
Version: 0.1.13
|
|
4
|
-
Summary: Utilities for logging and sending logs.
|
|
5
|
-
Home-page: https://github.com/XoriieInpottn/liblogging
|
|
6
|
-
Author: xi
|
|
7
|
-
Author-email: gylv@mail.ustc.edu.cn, huangfuyb@163.com
|
|
8
|
-
License: Apache-2.0 license
|
|
9
|
-
Platform: any
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Provides-Extra: collector
|
|
14
|
-
Requires-Dist: kafka-python==2.0.2; extra == "collector"
|
|
15
|
-
Dynamic: author
|
|
16
|
-
Dynamic: author-email
|
|
17
|
-
Dynamic: classifier
|
|
18
|
-
Dynamic: description
|
|
19
|
-
Dynamic: description-content-type
|
|
20
|
-
Dynamic: home-page
|
|
21
|
-
Dynamic: license
|
|
22
|
-
Dynamic: license-file
|
|
23
|
-
Dynamic: platform
|
|
24
|
-
Dynamic: provides-extra
|
|
25
|
-
Dynamic: summary
|
|
26
|
-
|
|
27
|
-
# liblogging
|
|
28
|
-
|
|
29
|
-
Utilities for logging and sending logs.
|
|
30
|
-
```shell
|
|
31
|
-
pip install liblogging
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 🌟Feature
|
|
35
|
-
### 统一日志格式记录
|
|
36
|
-
统一了当前agent的日志记录格式,也可自己基于默认格式进行拓展。
|
|
37
|
-
当前记录的信息和对应的key如下:
|
|
38
|
-
```python
|
|
39
|
-
{
|
|
40
|
-
"create_time": "时间戳,默认和mysql列datatime(3)保持一致",
|
|
41
|
-
"level": "like INFO, ERROR, WARNING",
|
|
42
|
-
# 通过上下文变量保存trace_id
|
|
43
|
-
"trace_id": "trace_id for 追溯不同服务的调用链路",
|
|
44
|
-
"line_info": "{record.filename}:{record.lineno}:{record.funcName}",
|
|
45
|
-
"message": message,
|
|
46
|
-
# 通过上下文变量区分不同源, 方便接收不同服务源信息, 比如Chat, Welcome, Planning等
|
|
47
|
-
"message_source": context.get("message_source", "chat_log"),
|
|
48
|
-
# 控制不同log类型,便于筛选日志数据, 比如tool, llm, turn等
|
|
49
|
-
"message_type": message_type,
|
|
50
|
-
# 可以根据自己需求加入其他的字段
|
|
51
|
-
**extra_message
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
上述日志信息均以json字符串的形式记录下来,方便存储及后续处理。
|
|
55
|
-
|
|
56
|
-
### 配置上下文变量,无须重复传参显示记录
|
|
57
|
-
通过装饰器形式, 指定需要配置的全局上下文变量, 仅需在整个程序/服务入口配置一次即可。
|
|
58
|
-
|
|
59
|
-
需要注意的是配置的全局上下文变量,根据加入装饰器下的函数入参名称匹配进行更新,推荐函数参数定义使用`BaseModel`。
|
|
60
|
-
|
|
61
|
-
```python
|
|
62
|
-
主程序/服务: service1.py
|
|
63
|
-
from pydantic import BaseModel
|
|
64
|
-
|
|
65
|
-
from liblogging import log_request,logger
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class Request(BaseModel):
|
|
69
|
-
name: str
|
|
70
|
-
trace_id: str
|
|
71
|
-
|
|
72
|
-
#在主程序入口配置了trace_id这一全局上下文变量,会通过函数入参对该字段进行赋值,后续在该服务下的其他程序logger.info时会读取这一变量并记录下来。
|
|
73
|
-
#同时也支持默认参数配置,比如message_source设置了默认值,后续使用logger会记录message_source为"demo"。
|
|
74
|
-
@log_request("trace_id", message_source="demo")
|
|
75
|
-
def your_service_entry(request: Request):
|
|
76
|
-
logger.info("Processing request")
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
```python
|
|
80
|
-
该服务下的其他程序: function1.py,可直接logger.info(). trace_id, message_source均会记录下来。
|
|
81
|
-
from liblogging import logger
|
|
82
|
-
|
|
83
|
-
def test(name):
|
|
84
|
-
logger.info(f"Testing {name}")
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 重定向并发送到消息队列
|
|
88
|
-
以默认集成的kafka为例,可将上述统一日志格式记录的形式发送至kafka。
|
|
89
|
-
|
|
90
|
-
kafka 配置文件格式:
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"{cluster_name}": {
|
|
94
|
-
"{env_name}": {
|
|
95
|
-
"bootstrap_servers": "server1, server2, server3",
|
|
96
|
-
"username": "username",
|
|
97
|
-
"password": "******",
|
|
98
|
-
"topic": "your topic",
|
|
99
|
-
"...": "..."
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
使用形式:
|
|
106
|
-
```shell
|
|
107
|
-
python service 2>&1 | tee {log_file_path} | liblogging_collector --config-path {your_kafka_path} --ssl-cafile {your_ssl_cafile_path} --send-kafka
|
|
108
|
-
```
|
|
109
|
-
tee {log_file_path} 可以将你的程序记录(输出+错误)重定向到文件中(可选)。
|
|
110
|
-
|
|
111
|
-
[log_collector.py](liblogging/sending/log_collector.py)为`liblogging_collector`的源代码地址。
|
|
112
|
-
|
|
113
|
-
`env_name`不指定的话,默认读取`os.environ.get("CHAT_ENV", "dev")`.
|
|
114
|
-
|
|
115
|
-
## 📋Example
|
|
116
|
-
增加额外记录字段信息,以及搭配[libentry](https://github.com/XoriieInpottn/libentry)使用的样例见 [example](example)。
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
## 💡Tips
|
|
120
|
-
|
|
121
|
-
1. If using Kafka to send messages, please use `pip install liblogging[collector]`.
|
|
122
|
-
2. 如果需要数据持久化,推荐日志消息都写在message列中,维护一列节省内存空间。需要后续进行查询的,以字典形式记录,比如logger.info({"key": "value"}), 便于后续查找。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|