Metadata-Version: 2.3
Name: mingx-v2
Version: 0.1.3
Summary: Mingx tracing SDK - OpenTelemetry-based tracing compatible with any OTLP backend
Author: 627289120@qq.com
Author-email: 627289120@qq.com <627289120@qq.com>
Requires-Dist: opentelemetry-api>=1.33.0
Requires-Dist: opentelemetry-sdk>=1.33.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.33.0
Requires-Dist: pytest>=8.0.0 ; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0 ; extra == 'dev'
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.33.0 ; extra == 'grpc'
Requires-Dist: langchain-core>=0.3.0 ; extra == 'langchain'
Requires-Dist: langgraph>=0.2.0 ; extra == 'langgraph'
Requires-Dist: langchain-core>=0.3.0 ; extra == 'langgraph'
Requires-Dist: openai>=2.0.0 ; extra == 'openai'
Requires-Python: >=3.10
Provides-Extra: dev
Provides-Extra: grpc
Provides-Extra: langchain
Provides-Extra: langgraph
Provides-Extra: openai
Description-Content-Type: text/markdown

# Mingx Tracing SDK

基于 **OpenTelemetry** 的 Python 跟踪库，数据通过标准 OTLP 导出，可对接任意兼容后端（Jaeger、Grafana Tempo、Langfuse OTel、自建 Collector 等）。API 设计参考 [Langfuse Python SDK](https://github.com/langfuse/langfuse-python)，便于迁移。

- **要求**：Python 3.10+，推荐 [uv](https://docs.astral.sh/uv/) 管理依赖
- **包名**：`mingx-v2`（安装后仍 `from mingx import ...`）

## 安装

```bash
uv add mingx-v2
# 或
pip install mingx-v2
```

可选依赖：`mingx-v2[langchain]`、`mingx-v2[langgraph,langchain]`、`mingx-v2[openai]`、`mingx-v2[grpc]`。

## 配置

| 环境变量 | 说明 |
|----------|------|
| `MINGX_TRACING_ENABLED` | 设为 `false` 或 `0` 关闭跟踪 |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | 轨迹导出地址，如 `http://localhost:4318/v1/traces` |
| `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | 可选，如 `Authorization=Bearer xxx` |
| `OTEL_SERVICE_NAME` | 可选，服务名，默认 `mingx` |

或在代码中（优先于环境变量）：

```python
from mingx import get_client

get_client(
    endpoint="https://ingest.example.com/v1/traces",
    token="your-api-token",  # 或 "username:password" 做 Basic 认证
)
```

## 使用

### 手动 Span / Observation

```python
from mingx import get_client

mingx = get_client()

with mingx.start_as_current_span(name="request") as span:
    result = do_work()
    span.update(output=result)

with mingx.start_as_current_observation(
    name="llm-call", as_type="generation", model="gpt-4", input={"prompt": "Hi"},
) as gen:
    response = call_llm()
    gen.update(output=response, usage_details={"prompt_tokens": 1, "completion_tokens": 2})
```

### metadata 与 trace 约定（全项目统一）

- 任一层级通过 **metadata** 传参（手动用 `metadata=`，LangChain 用 `config["metadata"]`，OpenAI 用 `mingx_metadata`）。
- **四个约定 key**：`user_id`、`session_id`、`thread_id`、`trace_from` 会单独落库；其余 key 落在 `*.metadata` 下。
- **根 span**：若 metadata 含上述 key，SDK 会**自动写入 mingx.trace 顶层**（如 `mingx.trace.thread_id`），其余写入 `mingx.trace.metadata.*`。
- **子 span**：若子 span 传了 metadata，其中 `user_id`、`session_id`、`thread_id` 写入 **mingx.observation 顶层**；`trace_from` 仅保留在 trace，不落 observation 顶层；其余写入 `mingx.observation.metadata.*`。**mingx.trace 不因子 span 而改变。**

因此只需传好 metadata，根由 SDK 自动识别并写 trace；`mingx.version` 会**自动**上送为当前 SDK 版本，无需手填。

### 装饰器

```python
from mingx import observe, get_client

@observe(name="my-op", as_type="span")
def process(data: str) -> str:
    return data.upper()

@observe(as_type="generation", name="answer")
async def answer(query: str) -> str:
    return await llm.achat(query)
```

### 更新当前 trace / span

```python
mingx.update_current_trace(user_id="u1", session_id="s1", metadata={"thread_id": "req-1", "trace_from": "API"})
mingx.update_current_span(output=result)
```

### 事件（瞬时点）

```python
mingx.create_event(name="button-click", metadata={"id": "submit"})
```

### LangChain / LangGraph

安装：`pip install mingx-v2[langchain]`（LangGraph 再加 `mingx-v2[langgraph,langchain]`）。

```python
from mingx.langchain import CallbackHandler

handler = CallbackHandler()
config = {
    "callbacks": [handler],
    "metadata": {"user_id": "u1", "session_id": "s1", "thread_id": "req-1", "trace_from": "API"},
}
chain.invoke({"question": "..."}, config=config)
```

示例：`examples/langchain_tracing.py`、`examples/langgraph_tracing.py`、`examples/langchain_agent_tracing.py`、`examples/langchain_react_agent.py`。

### OpenAI SDK

安装：`pip install mingx-v2[openai]`。仅改 import，用法与官方一致，调用自动上送 trace。

```python
from mingx.openai import openai

client = openai.OpenAI()
r = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello"}],
    mingx_name="my-chat",
    mingx_metadata={"user_id": "u1", "session_id": "s1", "thread_id": "req-1", "trace_from": "API"},
)
```

示例：`examples/openai_tracing.py`。支持 chat.completions（含流式）与 embeddings。

## 数据出口与 Flush

- 数据经 **OpenTelemetry OTLP** 发出；属性使用 `mingx.*` 命名空间。
- 首次 `get_client()` 会注册 **atexit**，进程正常退出前自动 flush；长驻进程可在关键逻辑后手动 `get_client().flush()`。

## 上送属性速查

| 层级 | 属性 |
|------|------|
| **Trace** | `mingx.trace.name`、`mingx.trace.user_id`、`mingx.trace.session_id`、`mingx.trace.thread_id`、`mingx.trace.trace_from`、`mingx.trace.tags`、`mingx.trace.metadata.<key>` |
| **Observation** | `mingx.observation.type`、`mingx.observation.user_id`、`mingx.observation.session_id`、`mingx.observation.thread_id`、`mingx.observation.input`、`mingx.observation.output`、`mingx.observation.metadata.<key>`、`mingx.observation.level`、`mingx.observation.status_message`（子 span 可重设三键 user_id/session_id/thread_id；trace_from 仅 trace） |
| **Generation** | `mingx.observation.model`、`mingx.observation.model_parameters`、`mingx.observation.usage_details`、`mingx.observation.cost_details` 等 |
| **通用** | `mingx.environment`、`mingx.version`（**自动上送为 SDK 版本**，无需手填） |

观测类型（`mingx.observation.type`）与 Langfuse 对齐：`span`、`generation`、`event`、`agent`、`tool`、`chain`、`retriever`、`embedding`、`evaluator`、`guardrail`。详见 `docs/SDK用户使用文档.md`。

## 示例索引

| 场景 | 文件 |
|------|------|
| 基础 Span + Generation | `examples/basic_tracing.py` |
| 装饰器 | `examples/decorator_example.py` |
| 请求级 trace（metadata 自动写 trace） | `examples/integration_example.py` |
| OpenAI | `examples/openai_tracing.py` |
| LangChain Chain | `examples/langchain_tracing.py` |
| LangGraph StateGraph | `examples/langgraph_tracing.py` |
| LangChain create_agent / ReAct | `examples/langchain_agent_tracing.py`、`examples/langchain_react_agent.py` |

运行前设置 `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` 或代码中 `get_client(endpoint=..., token=...)`；无后端时可设 `MINGX_TRACING_ENABLED=false`。

## 开发与发布

```bash
uv sync --all-extras
uv run pytest
uv build
# twine upload --config-file .pypirc -r pypi dist/*
```

## License

MIT
