Metadata-Version: 2.4
Name: ms_service_metric
Version: 0.0.1a1
Summary: 一个轻量级的 Python 服务指标采集库，支持动态 Hook 和 Prometheus 指标输出
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: pyyaml
Requires-Dist: prometheus-client
Requires-Dist: posix_ipc; sys_platform == "linux"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: flake8; extra == "dev"

# ms_service_metric

一个轻量级的 Python 服务指标采集库，支持动态 Hook 和 Prometheus 指标输出。

## 特性

- 🔧 **动态 Hook**: 基于 YAML 配置动态 Hook 目标函数
- 📊 **Prometheus 集成**: 支持 Timer、Counter、Gauge、Histogram 等指标类型
- 🔄 **动态开关**: 通过共享内存和信号实现运行时开关控制
- 🏗️ **框架适配**: 内置 vLLM、SGLang 等框架适配器
- 🔍 **Locals 访问**: 通过字节码注入访问函数局部变量

## 安装

```bash
pip install ms_service_metric
```

### 依赖

- Python >= 3.10
- pyyaml
- prometheus-client
- posix_ipc (Linux 平台)

## 快速开始

### 1. vLLM 集成

1. 通过vllm的插件机制自动集成，无需额外修改代码
2. 启动vllm 的多进程metric 采集环境变量

```bash
export PROMETHEUS_MULTIPROC_DIR=/dev/shm/vllm_metrics
mkdir -p $PROMETHEUS_MULTIPROC_DIR && rm -rf $PROMETHEUS_MULTIPROC_DIR/*
```

### 2. 控制指标采集

```bash
# 开启指标采集
ms-service-metric on

# 关闭指标采集
ms-service-metric off

# 重启（重新加载配置）
ms-service-metric restart

# 查看状态
ms-service-metric status
```

## 配置

### 配置文件格式

创建 YAML 配置文件：

```yaml
# 使用默认 timer handler
- symbol: my_module:MyClass.my_method
  metrics:
    - name: my_method_duration
      type: timer
      label:
        - name: status
          expr: "ret.status if hasattr(ret, 'status') else 'unknown'"

# 使用自定义 handler
- symbol: my_module:process_request
  handler: my_handlers:request_handler
  need_locals: false
  metrics:
    - name: request_count
      type: counter
      expr: "1"
```

### 配置项说明

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| symbol | string | 是 | 目标符号路径，格式：`module.path:ClassName.method_name` |
| handler | string | 否 | 自定义 handler 路径，格式：`module.path:function_name` |
| min_version | string | 否 | 最小版本要求 |
| max_version | string | 否 | 最大版本要求 |
| need_locals | bool | 否 | 是否需要访问局部变量，默认 false |
| metrics | list | 否 | 指标配置列表 |

### Metrics 配置

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 指标名称 |
| type | string | 是 | 指标类型：timer/counter/gauge/histogram |
| expr | string | 否 | 表达式（非 timer 类型必填） |
| label | list | 否 | 标签配置 |
| buckets | list | 否 | 直方图分桶（histogram 类型） |

### 环境变量

| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| MS_SERVICE_METRIC_CONFIG_PATH | 配置文件路径 | 无 |
| MS_SERVICE_METRIC_SHM_PREFIX | 共享内存前缀 | /ms_service_metric |
| MS_SERVICE_METRIC_MAX_PROCS | 最大进程数 | 1000 |
| PROMETHEUS_MULTIPROC_DIR | 多进程指标目录 | 无 |

## Handler 类型

### Wrap Handler

包装函数类型，需要手动调用原函数：

```python
def my_wrap_handler(ori_func, *args, **kwargs):
    # 前置处理
    start_time = time.time()
    
    # 调用原函数
    result = ori_func(*args, **kwargs)
    
    # 后置处理
    duration = time.time() - start_time
    print(f"Duration: {duration}")
    
    return result
```

### Context Handler

上下文管理器类型，使用 yield 控制执行流程。根据参数签名自动判断是否需要访问局部变量：

**不需要 locals（1个参数）：**

```python
def simple_context_handler(ctx):
    # ctx: FunctionContext 对象
    # ctx.return_value: 返回值（yield 后可用）
    
    # 前置处理
    start_time = time.time()
    
    yield  # 原函数在这里执行
    
    # 后置处理
    duration = time.time() - start_time
    print(f"Duration: {duration}")
    print(f"Result: {ctx.return_value}")
```

**需要 locals（2个参数）：**

```python
def advanced_context_handler(ctx, local_values):
    # ctx: FunctionContext 对象
    # local_values: 函数的locals字典
    
    # 前置处理
    print(f"Locals before: {local_values}")
    
    yield  # 原函数在这里执行
    
    # 后置处理
    print(f"Result: {ctx.return_value}")
    print(f"Locals after: {local_values}")
```

### 自动检测 need_locals

系统通过检查 handler 函数的参数签名自动判断是否需要 locals：

| 参数个数 | 含义 | 处理方式 |
|----------|------|----------|
| 1个参数 (ctx) | 不需要 locals | 封装成 wrap handler |
| 2个参数 (ctx, local_values) | 需要 locals | 走字节码注入 |

**默认 Handler：** 根据配置中是否存在 `expr` 字段自动决定：
- 有 `expr`：创建 2 参数 handler（需要 locals）
- 无 `expr`：创建 1 参数 handler（不需要 locals）

**配置示例：**

```yaml
# 不需要 locals（自动检测）
- symbol: my_module:simple_function
  handler: my_handlers:simple_handler  # 1个参数

# 需要 locals（自动检测）
- symbol: my_module:complex_function
  handler: my_handlers:advanced_handler  # 2个参数，第二个参数名包含"local"
  metrics:
    - name: processed_items
      type: counter
      expr: "len(items)"  # items 是函数内的局部变量

# 默认 handler 自动检测（有 expr，需要 locals）
- symbol: my_module:another_function
  metrics:
    - name: item_count
      type: counter
      expr: "len(items)"  # 存在 expr，自动创建 2 参数 handler
```

## 多 Handler 组合

同一个 symbol 可以配置多个 handler，按洋葱模型执行：

```yaml
- symbol: my_module:process
  handler: handlers:auth_check
- symbol: my_module:process
  handler: handlers:timing
  metrics:
    - name: process_duration
      type: timer
```

执行顺序：`auth_check -> timing -> 原函数 -> timing -> auth_check`

## 框架适配

### vLLM

```python
from ms_service_metric.adapters.vllm import initialize_vllm_metric

# 初始化
initialize_vllm_metric()
```

内置 V1 版本配置，自动 hook vLLM 关键函数。

### SGLang

```python
from ms_service_metric.adapters.sglang import initialize_sglang_metric

# 初始化
initialize_sglang_metric()
```

### 自定义适配器

```python
from ms_service_metric.core import SymbolHandlerManager

class MyAdapter:
    def __init__(self):
        self._manager = SymbolHandlerManager()
        
    def initialize(self, config_path: str):
        self._manager.initialize(config_path)
        
    def shutdown(self):
        self._manager.shutdown()
```

## API 参考

### 核心模块

#### SymbolHandlerManager

核心管理类，管理所有 Symbol 和 Handler。

```python
from ms_service_metric.core import SymbolHandlerManager

manager = SymbolHandlerManager()
manager.initialize(config_path="path/to/config.yaml")

# 检查状态
if manager.is_enabled():
    print("Metrics collection is enabled")

# 获取统计信息
stats = manager.get_stats()
print(f"Symbols: {stats['symbol_count']}")
print(f"Handlers: {stats['handler_count']}")

# 关闭
manager.shutdown()
```

#### Handler

Handler 包装类，表示一个 Hook 处理函数。

```python
from ms_service_metric.core import MetricHandler

# 从配置创建MetricHandler
handler = MetricHandler.from_config({
    'name': 'my_handler',
    'handler': 'my_module:my_func',
    'metrics': [{'name': 'duration', 'type': 'timer'}]
}, 'module.path:Class.method')

# 获取属性
print(handler.id)           # 唯一标识符
print(handler.name)         # 名称

# 获取hook函数
target = some_function  # 目标函数
handler_type, hook_func = handler.get_hook_func(target)
print(handler_type)         # 类型 (WRAP/CONTEXT)
```

#### MetricsManager

Prometheus 指标管理器。

```python
from ms_service_metric.core import get_metrics_manager, MetricType

manager = get_metrics_manager()

# 设置前缀
manager.metric_prefix = "my_app"

# 注册指标
manager.register_metric(
    name="request_duration",
    metric_type=MetricType.TIMER,
    description="Request duration in seconds",
    label_names=["method", "status"]
)

# 记录指标
manager.record_metric(
    name="request_duration",
    value=0.5,
    labels={"method": "GET", "status": "200"}
)
```

### 工具模块

#### ExprEval

表达式求值器，支持在运行时计算表达式。

```python
from ms_service_metric.utils import ExprEval

evaluator = ExprEval("len(items) * 2")
result = evaluator({"items": [1, 2, 3]})  # 返回 6
```

支持的变量：
- `ret`: 函数返回值
- `duration`: 执行耗时（秒）
- 函数局部变量（通过 `need_locals` 获取）

## 开发

### 安装开发依赖

```bash
pip install -e ".[dev]"
```

### 运行测试

```bash
pytest tests/
```

### 代码风格

```bash
black ms_service_metric/
flake8 ms_service_metric/
```

## 架构

```
┌─────────────────────────────────────────────────────────────┐
│                    SymbolHandlerManager                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │ SymbolConfig│  │SymbolWatcher│  │ MetricConfigWatch   │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
│                          │                                   │
│                          ▼                                   │
│                    ┌───────────┐                             │
│                    │  Symbol   │                             │
│                    └───────────┘                             │
│                          │                                   │
│              ┌───────────┼───────────┐                       │
│              ▼           ▼           ▼                       │
│         ┌────────┐ ┌────────┐ ┌────────┐                    │
│         │Handler │ │Handler │ │Handler │                    │
│         └────────┘ └────────┘ └────────┘                    │
│              │           │           │                       │
│              └───────────┼───────────┘                       │
│                          ▼                                   │
│                    ┌───────────┐                             │
│                  HookHelper   │                             │
│                    └───────────┘                             │
│                          │                                   │
│                          ▼                                   │
│                    ┌───────────┐                             │
│                 Target Func   │                             │
│                    └───────────┘                             │
└─────────────────────────────────────────────────────────────┘
```

详细设计请参考 [DESIGN.md](DESIGN.md)。

## 许可证

Apache License 2.0

## 贡献

欢迎提交 Issue 和 Pull Request。
