sycommon-python-lib 0.1.56__py3-none-any.whl → 0.1.56b2__py3-none-any.whl
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.
- sycommon/config/Config.py +3 -24
- sycommon/llm/embedding.py +23 -78
- sycommon/llm/get_llm.py +164 -24
- sycommon/logging/kafka_log.py +433 -187
- sycommon/middleware/exception.py +16 -10
- sycommon/middleware/timeout.py +1 -2
- sycommon/middleware/traceid.py +76 -81
- sycommon/rabbitmq/rabbitmq_client.py +242 -232
- sycommon/rabbitmq/rabbitmq_pool.py +218 -278
- sycommon/rabbitmq/rabbitmq_service.py +843 -25
- sycommon/services.py +96 -122
- sycommon/synacos/nacos_service.py +779 -63
- sycommon/tools/merge_headers.py +0 -20
- sycommon/tools/snowflake.py +153 -101
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/METADATA +8 -10
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/RECORD +19 -40
- sycommon/config/LangfuseConfig.py +0 -15
- sycommon/config/SentryConfig.py +0 -13
- sycommon/llm/llm_tokens.py +0 -119
- sycommon/llm/struct_token.py +0 -192
- sycommon/llm/sy_langfuse.py +0 -103
- sycommon/llm/usage_token.py +0 -117
- sycommon/notice/__init__.py +0 -0
- sycommon/notice/uvicorn_monitor.py +0 -200
- sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -206
- sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -73
- sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -285
- sycommon/rabbitmq/rabbitmq_service_core.py +0 -117
- sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -238
- sycommon/sentry/__init__.py +0 -0
- sycommon/sentry/sy_sentry.py +0 -35
- sycommon/synacos/nacos_client_base.py +0 -119
- sycommon/synacos/nacos_config_manager.py +0 -107
- sycommon/synacos/nacos_heartbeat_manager.py +0 -144
- sycommon/synacos/nacos_service_discovery.py +0 -157
- sycommon/synacos/nacos_service_registration.py +0 -270
- sycommon/tools/env.py +0 -62
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.56.dist-info → sycommon_python_lib-0.1.56b2.dist-info}/top_level.txt +0 -0
sycommon/middleware/exception.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from fastapi import Request, HTTPException
|
|
2
2
|
from fastapi.responses import JSONResponse
|
|
3
3
|
from pydantic import ValidationError
|
|
4
|
-
|
|
4
|
+
import traceback
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def setup_exception_handler(app, config: dict):
|
|
@@ -15,7 +15,7 @@ def setup_exception_handler(app, config: dict):
|
|
|
15
15
|
int_MaxBytes = int(MaxBytes) / 1024 / 1024
|
|
16
16
|
return JSONResponse(
|
|
17
17
|
content={
|
|
18
|
-
'code': 413, 'error': f'File size exceeds the allowed limit of {int_MaxBytes}MB.'
|
|
18
|
+
'code': 413, 'error': f'File size exceeds the allowed limit of {int_MaxBytes}MB.'},
|
|
19
19
|
status_code=413
|
|
20
20
|
)
|
|
21
21
|
|
|
@@ -27,8 +27,7 @@ def setup_exception_handler(app, config: dict):
|
|
|
27
27
|
content={
|
|
28
28
|
"code": exc.status_code,
|
|
29
29
|
"message": exc.detail,
|
|
30
|
-
"path": str(request.url.path)
|
|
31
|
-
"traceId": SYLogger.get_trace_id()
|
|
30
|
+
"path": str(request.url.path)
|
|
32
31
|
}
|
|
33
32
|
)
|
|
34
33
|
|
|
@@ -40,8 +39,7 @@ def setup_exception_handler(app, config: dict):
|
|
|
40
39
|
content={
|
|
41
40
|
"code": 400,
|
|
42
41
|
"message": "参数验证失败",
|
|
43
|
-
"details": exc.errors()
|
|
44
|
-
"traceId": SYLogger.get_trace_id()
|
|
42
|
+
"details": exc.errors()
|
|
45
43
|
}
|
|
46
44
|
)
|
|
47
45
|
|
|
@@ -57,22 +55,30 @@ def setup_exception_handler(app, config: dict):
|
|
|
57
55
|
status_code=exc.code,
|
|
58
56
|
content={
|
|
59
57
|
"code": exc.code,
|
|
60
|
-
"message": exc.message
|
|
61
|
-
"traceId": SYLogger.get_trace_id()
|
|
58
|
+
"message": exc.message
|
|
62
59
|
}
|
|
63
60
|
)
|
|
64
61
|
|
|
65
62
|
# 5. 全局异常处理器(捕获所有未处理的异常)
|
|
66
63
|
@app.exception_handler(Exception)
|
|
67
64
|
async def global_exception_handler(request: Request, exc: Exception):
|
|
65
|
+
# 记录详细错误信息
|
|
66
|
+
error_msg = f"请求路径: {request.url}\n"
|
|
67
|
+
error_msg += f"错误类型: {type(exc).__name__}\n"
|
|
68
|
+
error_msg += f"错误信息: {str(exc)}\n"
|
|
69
|
+
error_msg += f"堆栈信息: {traceback.format_exc()}"
|
|
70
|
+
|
|
71
|
+
# 使用你的日志服务记录错误
|
|
72
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
73
|
+
SYLogger.error(error_msg)
|
|
74
|
+
|
|
68
75
|
# 返回统一格式的错误响应(生产环境可选择不返回详细信息)
|
|
69
76
|
return JSONResponse(
|
|
70
77
|
status_code=500,
|
|
71
78
|
content={
|
|
72
79
|
"code": 500,
|
|
73
80
|
"message": "服务器内部错误,请稍后重试",
|
|
74
|
-
"detail": str(exc) if config.get('DEBUG', False) else "Internal Server Error"
|
|
75
|
-
"traceId": SYLogger.get_trace_id()
|
|
81
|
+
"detail": str(exc) if config.get('DEBUG', False) else "Internal Server Error"
|
|
76
82
|
}
|
|
77
83
|
)
|
|
78
84
|
|
sycommon/middleware/timeout.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import time
|
|
3
3
|
from fastapi import Request
|
|
4
4
|
from fastapi.responses import JSONResponse
|
|
5
|
-
from sycommon.logging.kafka_log import SYLogger
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def setup_request_timeout_middleware(app, config: dict):
|
|
@@ -15,6 +14,6 @@ def setup_request_timeout_middleware(app, config: dict):
|
|
|
15
14
|
response = await call_next(request)
|
|
16
15
|
duration = time.time() - request.state.start_time
|
|
17
16
|
if duration > REQUEST_TIMEOUT:
|
|
18
|
-
return JSONResponse(content={'code': 1, 'error': 'Request timed out'
|
|
17
|
+
return JSONResponse(content={'code': 1, 'error': 'Request timed out'}, status_code=504)
|
|
19
18
|
return response
|
|
20
19
|
return app
|
sycommon/middleware/traceid.py
CHANGED
|
@@ -10,8 +10,11 @@ from sycommon.tools.snowflake import Snowflake
|
|
|
10
10
|
def setup_trace_id_handler(app):
|
|
11
11
|
@app.middleware("http")
|
|
12
12
|
async def trace_id_and_log_middleware(request: Request, call_next):
|
|
13
|
-
# ========== 1.
|
|
14
|
-
|
|
13
|
+
# ========== 1. 请求阶段:确保获取/生成 x-traceId-header ==========
|
|
14
|
+
# 优先从请求头读取(兼容任意大小写)
|
|
15
|
+
trace_id = request.headers.get(
|
|
16
|
+
"x-traceId-header") or request.headers.get("x-traceid-header")
|
|
17
|
+
# 无则生成雪花ID
|
|
15
18
|
if not trace_id:
|
|
16
19
|
trace_id = Snowflake.id
|
|
17
20
|
|
|
@@ -34,30 +37,38 @@ def setup_trace_id_handler(app):
|
|
|
34
37
|
|
|
35
38
|
if is_json_content and request.method in ["POST", "PUT", "PATCH"]:
|
|
36
39
|
try:
|
|
37
|
-
# 兼容纯文本格式的 JSON
|
|
40
|
+
# 兼容纯文本格式的 JSON(先读文本再解析)
|
|
38
41
|
if "text/plain" in content_type:
|
|
39
42
|
raw_text = await request.text(encoding="utf-8")
|
|
40
43
|
request_body = json.loads(raw_text)
|
|
41
44
|
else:
|
|
45
|
+
# application/json 直接解析
|
|
42
46
|
request_body = await request.json()
|
|
43
|
-
except Exception:
|
|
47
|
+
except Exception as e:
|
|
44
48
|
try:
|
|
45
49
|
request_body = await request.json()
|
|
46
50
|
except Exception as e:
|
|
51
|
+
# 精准捕获 JSON 解析错误(而非泛 Exception)
|
|
47
52
|
request_body = {"error": f"JSON parse failed: {str(e)}"}
|
|
48
53
|
|
|
49
54
|
elif "multipart/form-data" in content_type and request.method in ["POST", "PUT"]:
|
|
50
55
|
try:
|
|
56
|
+
# 从请求头中提取boundary
|
|
51
57
|
boundary = None
|
|
52
58
|
if "boundary=" in content_type:
|
|
53
59
|
boundary = content_type.split("boundary=")[1].strip()
|
|
54
60
|
boundary = boundary.encode('ascii')
|
|
55
61
|
|
|
56
62
|
if boundary:
|
|
63
|
+
# 读取原始请求体
|
|
57
64
|
body = await request.body()
|
|
65
|
+
|
|
66
|
+
# 尝试从原始请求体中提取文件名
|
|
58
67
|
parts = body.split(boundary)
|
|
59
68
|
for part in parts:
|
|
60
69
|
part_str = part.decode('utf-8', errors='ignore')
|
|
70
|
+
|
|
71
|
+
# 使用正则表达式查找文件名
|
|
61
72
|
filename_match = re.search(
|
|
62
73
|
r'filename="([^"]+)"', part_str)
|
|
63
74
|
if filename_match:
|
|
@@ -71,69 +82,62 @@ def setup_trace_id_handler(app):
|
|
|
71
82
|
request_body = {
|
|
72
83
|
"error": f"Failed to process form data: {str(e)}"}
|
|
73
84
|
|
|
74
|
-
#
|
|
85
|
+
# 构建请求日志(包含 traceId)
|
|
75
86
|
request_message = {
|
|
76
|
-
"traceId": trace_id,
|
|
87
|
+
"traceId": trace_id, # 请求日志中加入 traceId
|
|
77
88
|
"method": request.method,
|
|
78
89
|
"url": str(request.url),
|
|
79
90
|
"query_params": query_params,
|
|
80
91
|
"request_body": request_body,
|
|
81
92
|
"uploaded_files": files_info if files_info else None
|
|
82
93
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
# 标记位:默认认为会发生异常
|
|
86
|
-
# 这样如果中途代码报错跳转到 except,finally 就不会 reset,保留 trace_id 给 Exception Handler
|
|
87
|
-
had_exception = True
|
|
94
|
+
request_message_str = json.dumps(request_message, ensure_ascii=False)
|
|
95
|
+
SYLogger.info(request_message_str)
|
|
88
96
|
|
|
89
97
|
try:
|
|
90
|
-
#
|
|
98
|
+
# 处理请求
|
|
91
99
|
response = await call_next(request)
|
|
92
100
|
|
|
93
|
-
#
|
|
94
|
-
|
|
95
|
-
# 从而保证 trace_id 不被清除,能够透传
|
|
96
|
-
|
|
97
|
-
response_content_type = response.headers.get(
|
|
98
|
-
"content-type", "").lower()
|
|
101
|
+
# 获取响应Content-Type(统一小写)
|
|
102
|
+
content_type = response.headers.get("content-type", "").lower()
|
|
99
103
|
|
|
100
|
-
#
|
|
101
|
-
if "text/event-stream" in
|
|
104
|
+
# ========== 2. SSE 响应:仅设置 x-traceId-header,不修改其他头 ==========
|
|
105
|
+
if "text/event-stream" in content_type:
|
|
102
106
|
try:
|
|
103
|
-
|
|
107
|
+
# 强制写入 x-traceId-header 到响应头
|
|
108
|
+
response.headers["x-traceId-header"] = trace_id
|
|
109
|
+
# 确保前端能读取(仅补充暴露头,不覆盖原有值)
|
|
104
110
|
expose_headers = response.headers.get(
|
|
105
111
|
"access-control-expose-headers", "")
|
|
106
112
|
if expose_headers:
|
|
107
|
-
if "x-
|
|
113
|
+
if "x-traceId-header" not in expose_headers.lower():
|
|
108
114
|
response.headers[
|
|
109
|
-
"access-control-expose-headers"] = f"{expose_headers}, x-
|
|
115
|
+
"access-control-expose-headers"] = f"{expose_headers}, x-traceId-header"
|
|
110
116
|
else:
|
|
111
|
-
response.headers["access-control-expose-headers"] = "x-
|
|
112
|
-
|
|
113
|
-
# SSE 必须移除 Content-Length
|
|
117
|
+
response.headers["access-control-expose-headers"] = "x-traceId-header"
|
|
118
|
+
# SSE 必须移除 Content-Length(仅这一个额外操作)
|
|
114
119
|
headers_lower = {
|
|
115
120
|
k.lower(): k for k in response.headers.keys()}
|
|
116
121
|
if "content-length" in headers_lower:
|
|
117
122
|
del response.headers[headers_lower["content-length"]]
|
|
118
123
|
except AttributeError:
|
|
119
|
-
#
|
|
124
|
+
# 流式响应头只读:初始化时仅加入 traceId 和必要暴露头
|
|
120
125
|
new_headers = dict(response.headers) if hasattr(
|
|
121
126
|
response.headers, 'items') else {}
|
|
122
|
-
new_headers["x-
|
|
127
|
+
new_headers["x-traceId-header"] = trace_id # 强制加入
|
|
128
|
+
# 保留原有暴露头,补充 traceId
|
|
123
129
|
if "access-control-expose-headers" in new_headers:
|
|
124
|
-
if "x-
|
|
125
|
-
new_headers["access-control-expose-headers"] += ", x-
|
|
130
|
+
if "x-traceId-header" not in new_headers["access-control-expose-headers"].lower():
|
|
131
|
+
new_headers["access-control-expose-headers"] += ", x-traceId-header"
|
|
126
132
|
else:
|
|
127
|
-
new_headers["access-control-expose-headers"] = "x-
|
|
133
|
+
new_headers["access-control-expose-headers"] = "x-traceId-header"
|
|
134
|
+
# 移除 Content-Length
|
|
128
135
|
new_headers.pop("content-length", None)
|
|
129
136
|
response.init_headers(new_headers)
|
|
130
|
-
|
|
131
|
-
# SSE 不处理 Body,直接返回
|
|
132
|
-
had_exception = False
|
|
133
137
|
return response
|
|
134
138
|
|
|
135
|
-
#
|
|
136
|
-
# 备份 CORS
|
|
139
|
+
# ========== 3. 非 SSE 响应:强制写入 x-traceId-header,保留 CORS ==========
|
|
140
|
+
# 备份 CORS 头(防止丢失)
|
|
137
141
|
cors_headers = {}
|
|
138
142
|
cors_header_keys = [
|
|
139
143
|
"access-control-allow-origin",
|
|
@@ -149,7 +153,7 @@ def setup_trace_id_handler(app):
|
|
|
149
153
|
cors_headers[key] = response.headers[k]
|
|
150
154
|
break
|
|
151
155
|
|
|
152
|
-
# 合并
|
|
156
|
+
# 合并 headers(非 SSE 场景)
|
|
153
157
|
merged_headers = merge_headers(
|
|
154
158
|
source_headers=request.headers,
|
|
155
159
|
target_headers=response.headers,
|
|
@@ -157,20 +161,19 @@ def setup_trace_id_handler(app):
|
|
|
157
161
|
delete_keys={'content-length', 'accept', 'content-type'}
|
|
158
162
|
)
|
|
159
163
|
|
|
160
|
-
# 强制加入 x-
|
|
161
|
-
merged_headers["x-
|
|
164
|
+
# 强制加入 x-traceId-header(优先级最高)
|
|
165
|
+
merged_headers["x-traceId-header"] = trace_id
|
|
166
|
+
# 恢复 CORS 头 + 补充 traceId 到暴露头
|
|
162
167
|
merged_headers.update(cors_headers)
|
|
163
|
-
|
|
164
|
-
# 更新暴露头
|
|
165
168
|
expose_headers = merged_headers.get(
|
|
166
169
|
"access-control-expose-headers", "")
|
|
167
170
|
if expose_headers:
|
|
168
|
-
if "x-
|
|
169
|
-
merged_headers["access-control-expose-headers"] = f"{expose_headers}, x-
|
|
171
|
+
if "x-traceId-header" not in expose_headers.lower():
|
|
172
|
+
merged_headers["access-control-expose-headers"] = f"{expose_headers}, x-traceId-header"
|
|
170
173
|
else:
|
|
171
|
-
merged_headers["access-control-expose-headers"] = "x-
|
|
174
|
+
merged_headers["access-control-expose-headers"] = "x-traceId-header"
|
|
172
175
|
|
|
173
|
-
#
|
|
176
|
+
# 更新响应头
|
|
174
177
|
if hasattr(response.headers, 'clear'):
|
|
175
178
|
response.headers.clear()
|
|
176
179
|
for k, v in merged_headers.items():
|
|
@@ -184,26 +187,27 @@ def setup_trace_id_handler(app):
|
|
|
184
187
|
except (AttributeError, KeyError):
|
|
185
188
|
pass
|
|
186
189
|
|
|
187
|
-
#
|
|
190
|
+
# 处理普通响应体(JSON 加入 traceId)
|
|
188
191
|
response_body = b""
|
|
189
192
|
try:
|
|
190
193
|
async for chunk in response.body_iterator:
|
|
191
194
|
response_body += chunk
|
|
192
195
|
|
|
196
|
+
# 获取 Content-Disposition(统一小写)
|
|
193
197
|
content_disposition = response.headers.get(
|
|
194
198
|
"content-disposition", "").lower()
|
|
195
199
|
|
|
196
|
-
# JSON
|
|
197
|
-
if "application/json" in
|
|
200
|
+
# JSON 响应体加入 traceId
|
|
201
|
+
if "application/json" in content_type and not content_disposition.startswith("attachment"):
|
|
198
202
|
try:
|
|
199
203
|
data = json.loads(response_body)
|
|
200
204
|
new_body = response_body
|
|
201
|
-
if
|
|
202
|
-
data["traceId"] = trace_id
|
|
205
|
+
if data:
|
|
206
|
+
data["traceId"] = trace_id # 响应体也加入
|
|
203
207
|
new_body = json.dumps(
|
|
204
208
|
data, ensure_ascii=False).encode()
|
|
205
209
|
|
|
206
|
-
#
|
|
210
|
+
# 重建响应,确保 header 包含 x-traceId-header
|
|
207
211
|
response = Response(
|
|
208
212
|
content=new_body,
|
|
209
213
|
status_code=response.status_code,
|
|
@@ -211,12 +215,12 @@ def setup_trace_id_handler(app):
|
|
|
211
215
|
media_type=response.media_type
|
|
212
216
|
)
|
|
213
217
|
response.headers["content-length"] = str(len(new_body))
|
|
214
|
-
response.headers["x-
|
|
215
|
-
# 恢复 CORS
|
|
218
|
+
response.headers["x-traceId-header"] = trace_id # 再次兜底
|
|
219
|
+
# 恢复 CORS 头
|
|
216
220
|
for k, v in cors_headers.items():
|
|
217
221
|
response.headers[k] = v
|
|
218
222
|
except json.JSONDecodeError:
|
|
219
|
-
# 非 JSON
|
|
223
|
+
# 非 JSON 响应:仅更新长度,强制加入 traceId
|
|
220
224
|
response = Response(
|
|
221
225
|
content=response_body,
|
|
222
226
|
status_code=response.status_code,
|
|
@@ -225,11 +229,11 @@ def setup_trace_id_handler(app):
|
|
|
225
229
|
)
|
|
226
230
|
response.headers["content-length"] = str(
|
|
227
231
|
len(response_body))
|
|
228
|
-
response.headers["x-
|
|
232
|
+
response.headers["x-traceId-header"] = trace_id # 强制加入
|
|
229
233
|
for k, v in cors_headers.items():
|
|
230
234
|
response.headers[k] = v
|
|
231
235
|
else:
|
|
232
|
-
# 非 JSON
|
|
236
|
+
# 非 JSON 响应:强制加入 traceId
|
|
233
237
|
response = Response(
|
|
234
238
|
content=response_body,
|
|
235
239
|
status_code=response.status_code,
|
|
@@ -238,57 +242,48 @@ def setup_trace_id_handler(app):
|
|
|
238
242
|
)
|
|
239
243
|
response.headers["content-length"] = str(
|
|
240
244
|
len(response_body))
|
|
241
|
-
response.headers["x-
|
|
245
|
+
response.headers["x-traceId-header"] = trace_id # 强制加入
|
|
242
246
|
for k, v in cors_headers.items():
|
|
243
247
|
response.headers[k] = v
|
|
244
248
|
except StopAsyncIteration:
|
|
245
249
|
pass
|
|
246
250
|
|
|
247
|
-
#
|
|
251
|
+
# 构建响应日志(包含 traceId)
|
|
248
252
|
response_message = {
|
|
249
|
-
"traceId": trace_id,
|
|
253
|
+
"traceId": trace_id, # 响应日志加入 traceId
|
|
250
254
|
"status_code": response.status_code,
|
|
251
255
|
"response_body": response_body.decode('utf-8', errors='ignore'),
|
|
252
256
|
}
|
|
253
|
-
|
|
257
|
+
response_message_str = json.dumps(
|
|
258
|
+
response_message, ensure_ascii=False)
|
|
259
|
+
SYLogger.info(response_message_str)
|
|
254
260
|
|
|
255
|
-
#
|
|
261
|
+
# ========== 最终兜底:确保响应头必有 x-traceId-header ==========
|
|
256
262
|
try:
|
|
257
|
-
response.headers["x-
|
|
263
|
+
response.headers["x-traceId-header"] = trace_id
|
|
258
264
|
except AttributeError:
|
|
259
265
|
new_headers = dict(response.headers) if hasattr(
|
|
260
266
|
response.headers, 'items') else {}
|
|
261
|
-
new_headers["x-
|
|
267
|
+
new_headers["x-traceId-header"] = trace_id
|
|
262
268
|
if hasattr(response, "init_headers"):
|
|
263
269
|
response.init_headers(new_headers)
|
|
264
270
|
|
|
265
|
-
# 如果执行到这里,说明一切正常,标记为无异常
|
|
266
|
-
had_exception = False
|
|
267
271
|
return response
|
|
268
|
-
|
|
269
272
|
except Exception as e:
|
|
270
|
-
#
|
|
271
|
-
# 记录中间件层面的异常日志
|
|
273
|
+
# 异常日志也加入 traceId
|
|
272
274
|
error_message = {
|
|
273
275
|
"traceId": trace_id,
|
|
274
|
-
"error":
|
|
276
|
+
"error": str(e),
|
|
275
277
|
"query_params": query_params,
|
|
276
278
|
"request_body": request_body,
|
|
277
279
|
"uploaded_files": files_info if files_info else None
|
|
278
280
|
}
|
|
279
|
-
|
|
280
|
-
SYLogger.error(
|
|
281
|
-
|
|
282
|
-
# 关键:重新抛出异常,让 Global Exception Handler 接管
|
|
283
|
-
# 此时 had_exception 仍为 True,finally 不会 reset,trace_id 得以保留
|
|
281
|
+
error_message_str = json.dumps(error_message, ensure_ascii=False)
|
|
282
|
+
SYLogger.error(error_message_str)
|
|
284
283
|
raise
|
|
285
|
-
|
|
286
284
|
finally:
|
|
287
|
-
#
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
SYLogger.reset_trace_id(token)
|
|
291
|
-
SYLogger.reset_headers(header_token)
|
|
292
|
-
# 如果 had_exception 为 True,这里什么都不做,保留 ContextVar 供 Exception Handler 读取
|
|
285
|
+
# 清理上下文变量
|
|
286
|
+
SYLogger.reset_trace_id(token)
|
|
287
|
+
SYLogger.reset_headers(header_token)
|
|
293
288
|
|
|
294
289
|
return app
|