Skip to content

Commit 56c3a8d

Browse files
committed
Staging commit
Change-Id: Iba33588aedef449bc1691210bbc51879ca6e1caa Co-developed-by: Cursor <noreply@cursor.com>
1 parent 06901c2 commit 56c3a8d

3 files changed

Lines changed: 412 additions & 135 deletions

File tree

instrumentation-loongsuite/loongsuite-instrumentation-agentscope/src/opentelemetry/instrumentation/agentscope/utils.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -432,14 +432,7 @@ def convert_agentscope_messages_to_genai_format(
432432
if isinstance(msg, Msg):
433433
msg_dict = _format_msg_to_parts(msg)
434434
elif isinstance(msg, dict):
435-
if provider_name:
436-
try:
437-
converted = get_message_converter(provider_name)([msg])
438-
msg_dict = converted[0] if converted else msg
439-
except Exception:
440-
msg_dict = msg
441-
else:
442-
msg_dict = msg
435+
msg_dict = msg
443436
else:
444437
continue
445438

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
# bootstrap.py 流程梳理与优化建议
2+
3+
## 一、基本流程梳理
4+
5+
### 1. 安装流程 (`install_from_tar`)
6+
7+
```
8+
main()
9+
└─> install_from_tar()
10+
├─> resolve_tar_path() # 解析 tar 路径,可能需要下载
11+
├─> extract_tar() # 解压 tar 文件,获取所有 .whl 文件
12+
├─> filter_packages() # 过滤包(核心逻辑)
13+
│ ├─> get_package_name_from_whl() # 从 whl 文件名提取包名
14+
│ ├─> _is_instrumentation_in_bootstrap_gen() # 检查是否为 instrumentation
15+
│ ├─> check_python_version_compatibility() # 检查 Python 版本兼容性
16+
│ ├─> check_dependency_compatibility() # 检查依赖版本兼容性
17+
│ └─> get_target_libraries_from_bootstrap_gen() + _is_library_installed() # 自动检测
18+
└─> install_packages() # 使用 pip 安装
19+
```
20+
21+
### 2. 卸载流程 (`uninstall_loongsuite_packages`)
22+
23+
```
24+
main()
25+
└─> uninstall_loongsuite_packages()
26+
├─> get_installed_loongsuite_packages() # 获取已安装的包列表
27+
└─> uninstall_packages() # 使用 pip 卸载
28+
```
29+
30+
### 3. 核心辅助函数
31+
32+
- **包名处理**
33+
- `get_package_name_from_whl()`: 从 whl 文件名提取包名
34+
- `get_installed_package_version()`: 获取已安装包的版本(处理下划线/连字符变体)
35+
36+
- **元数据提取**
37+
- `get_metadata_from_whl()`: 从 whl 文件提取 METADATA
38+
- `get_python_requirement_from_whl()`: 提取 Python 版本要求
39+
40+
- **兼容性检查**
41+
- `check_python_version_compatibility()`: 检查 Python 版本
42+
- `check_dependency_compatibility()`: 检查依赖版本
43+
44+
- **bootstrap_gen 查询**
45+
- `_is_instrumentation_in_bootstrap_gen()`: 检查是否为 instrumentation
46+
- `get_target_libraries_from_bootstrap_gen()`: 获取目标库列表
47+
48+
- **库检测**
49+
- `_is_library_installed()`: 检查库是否已安装
50+
51+
## 二、发现的问题和优化建议
52+
53+
### 1. 🔴 包名规范化逻辑重复
54+
55+
**问题**
56+
- `get_installed_package_version()` 中三次尝试(原始名、下划线→连字符、连字符→下划线)
57+
- `_is_library_installed()` 中也有类似逻辑
58+
- 多个地方都有 `normalized_name = package_name.replace("_", "-")` 的重复
59+
60+
**建议**
61+
```python
62+
def normalize_package_name(package_name: str) -> str:
63+
"""统一规范化包名:将下划线转换为连字符"""
64+
return package_name.replace("_", "-")
65+
66+
def get_package_name_variants(package_name: str) -> List[str]:
67+
"""获取包名的所有可能变体(用于查找)"""
68+
normalized = normalize_package_name(package_name)
69+
variants = [package_name]
70+
if normalized != package_name:
71+
variants.append(normalized)
72+
# 如果需要,也可以添加反向变体
73+
return variants
74+
```
75+
76+
### 2. 🔴 从 requirement 字符串提取包名的逻辑重复
77+
78+
**问题**
79+
`_is_instrumentation_in_bootstrap_gen()``get_target_libraries_from_bootstrap_gen()` 中都有:
80+
```python
81+
default_pkg_name = (
82+
default_instr.split("==")[0]
83+
.split(">=")[0]
84+
.split("<=")[0]
85+
.split("~=")[0]
86+
.split("!=")[0]
87+
.strip()
88+
)
89+
```
90+
91+
**建议**
92+
```python
93+
def extract_package_name_from_requirement(req_str: str) -> str:
94+
"""从 requirement 字符串中提取包名"""
95+
try:
96+
return Requirement(req_str).name
97+
except Exception:
98+
# Fallback: 手动解析
99+
for op in ["==", ">=", "<=", "~=", "!=", ">", "<"]:
100+
if op in req_str:
101+
return req_str.split(op)[0].strip()
102+
return req_str.strip()
103+
```
104+
105+
### 3. 🟡 get_installed_package_version 中的重复代码
106+
107+
**问题**
108+
三个几乎相同的 try-except 块,只是包名不同。
109+
110+
**建议**
111+
```python
112+
def get_installed_package_version(package_name: str) -> Optional[str]:
113+
"""获取已安装包的版本"""
114+
variants = get_package_name_variants(package_name)
115+
116+
for variant in variants:
117+
version = _try_get_version(variant)
118+
if version:
119+
return version
120+
return None
121+
122+
def _try_get_version(package_name: str) -> Optional[str]:
123+
"""尝试获取单个包名变体的版本"""
124+
cmd = [sys.executable, "-m", "pip", "show", package_name]
125+
try:
126+
result = subprocess.run(
127+
cmd, capture_output=True, text=True, check=True, timeout=5
128+
)
129+
for line in result.stdout.splitlines():
130+
if line.startswith("Version:"):
131+
return line.split(":", 1)[1].strip()
132+
except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
133+
pass
134+
return None
135+
```
136+
137+
### 4. 🟡 filter_packages 函数过长
138+
139+
**问题**
140+
`filter_packages()` 函数有 130+ 行,包含太多逻辑,可读性差。
141+
142+
**建议**
143+
拆分为多个小函数:
144+
```python
145+
def filter_packages(...):
146+
"""主函数,协调各个过滤步骤"""
147+
base_packages = []
148+
instrumentation_packages = []
149+
150+
for whl_file in whl_files:
151+
package_name = get_package_name_from_whl(whl_file)
152+
153+
if _should_skip_package(package_name, whl_file, blacklist, whitelist,
154+
skip_version_check, auto_detect):
155+
continue
156+
157+
if package_name in BASE_DEPENDENCIES:
158+
base_packages.append(whl_file)
159+
else:
160+
if _should_install_instrumentation(package_name, whl_file, auto_detect):
161+
instrumentation_packages.append(whl_file)
162+
163+
return base_packages, instrumentation_packages
164+
165+
def _should_skip_package(...) -> bool:
166+
"""检查是否应该跳过该包"""
167+
# 黑名单/白名单检查
168+
# Python 版本检查
169+
# 依赖版本检查
170+
pass
171+
172+
def _should_install_instrumentation(...) -> bool:
173+
"""检查是否应该安装该 instrumentation"""
174+
# auto-detect 逻辑
175+
pass
176+
```
177+
178+
### 5. 🟡 包名匹配逻辑重复
179+
180+
**问题**
181+
多处都有 `normalized_name == package_name or default_pkg_name == package_name` 这样的匹配。
182+
183+
**建议**
184+
```python
185+
def package_names_match(name1: str, name2: str) -> bool:
186+
"""检查两个包名是否匹配(考虑规范化)"""
187+
normalized1 = normalize_package_name(name1)
188+
normalized2 = normalize_package_name(name2)
189+
return (normalized1 == normalized2 or
190+
name1 == name2 or
191+
normalized1 == name2 or
192+
name1 == normalized2)
193+
```
194+
195+
### 6. 🟢 常量提取
196+
197+
**问题**
198+
`EXCLUDED_PACKAGES` 在函数内部定义,应该移到模块级别。
199+
200+
**建议**
201+
```python
202+
# 在模块级别定义
203+
UNINSTALL_EXCLUDED_PACKAGES = {
204+
"loongsuite-distro",
205+
"opentelemetry-api",
206+
"opentelemetry-sdk",
207+
"opentelemetry-instrumentation",
208+
}
209+
```
210+
211+
### 7. 🟢 错误处理改进
212+
213+
**问题**
214+
多处使用 `except Exception: pass`,可能隐藏重要错误。
215+
216+
**建议**
217+
更具体地捕获异常,至少记录警告:
218+
```python
219+
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
220+
logger.debug(f"Failed to get version for {package_name}: {e}")
221+
return None
222+
except Exception as e:
223+
logger.warning(f"Unexpected error getting version for {package_name}: {e}")
224+
return None
225+
```
226+
227+
### 8. 🟢 使用 packaging 库解析 requirement
228+
229+
**问题**
230+
手动解析 requirement 字符串(split("==")[0]...)不够健壮。
231+
232+
**建议**
233+
统一使用 `packaging.requirements.Requirement` 解析(已经在用,但有些地方还在手动解析)。
234+
235+
### 9. 🟡 模块化建议
236+
237+
**建议**将代码拆分为多个模块**
238+
239+
```
240+
loongsuite/distro/
241+
├── bootstrap.py # 主入口和 CLI
242+
├── package_utils.py # 包名处理、版本获取等工具函数
243+
├── metadata.py # whl 元数据提取
244+
├── compatibility.py # 兼容性检查
245+
└── bootstrap_gen.py # bootstrap_gen 查询(已存在)
246+
```
247+
248+
## 三、优先级建议
249+
250+
### 高优先级(立即优化)
251+
1. ✅ 提取包名规范化函数(减少重复,提高一致性)
252+
2. ✅ 提取 requirement 解析函数(多处使用,容易出错)
253+
3. ✅ 简化 `get_installed_package_version()`(消除重复代码)
254+
255+
### 中优先级(后续优化)
256+
4. ⚠️ 拆分 `filter_packages()` 函数(提高可读性)
257+
5. ⚠️ 提取包名匹配函数(统一匹配逻辑)
258+
6. ⚠️ 改进错误处理(更好的调试体验)
259+
260+
### 低优先级(可选)
261+
7. 💡 模块化拆分(如果文件继续增长)
262+
8. 💡 使用更专业的 metadata 解析库(如果遇到解析问题)
263+
264+
## 四、总结
265+
266+
当前代码功能完整,但存在以下主要问题:
267+
1. **代码重复**:包名规范化、requirement 解析等逻辑在多处重复
268+
2. **函数过长**`filter_packages()` 函数包含太多逻辑
269+
3. **错误处理**:过于宽泛的异常捕获可能隐藏问题
270+
271+
建议优先解决代码重复问题,这将提高代码的可维护性和一致性。
272+

0 commit comments

Comments
 (0)