Metadata-Version: 2.1
Name: insightoslog
Version: 1.0.15
Summary: InsightOS Log SDK - Unified log collection SDK
Home-page: https://git.insightos.cn/hzh/InsightOSLogSDK-Python
Author: InsightOS Team
Author-email: team@insightos.org
License: UNKNOWN
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.7
Description-Content-Type: text/markdown

# InsightOS Log SDK - Python 语言指南

本文档详细介绍 InsightOS Log SDK for Python 的使用方法、配置字段和所有功能特性。

---

## 目录

- [快速开始](#快速开始)
- [完整配置参数表](#完整配置参数表)
- [日志级别](#日志级别)
- [日志记录方式](#日志记录方式)
- [输出模式](#输出模式)
- [日志结构](#日志结构)
- [链路追踪](#链路追踪)
- [上下文管理器](#上下文管理器)
- [建造者模式](#建造者模式)
- [HTTP Header 传播](#http-header-传播)
- [敏感信息过滤](#敏感信息过滤)
- [完整配置示例](#完整配置示例)

---

## 快速开始

### 安装

```bash
# 基础安装
pip install insightoslog

```

### 使用示例

```python
import insightoslog as log

# 初始化
log.init({"service_name": "MyService", "level": "info", "output": "stdout"})

# 记录日志
log.info("服务启动成功")
log.info("用户 {} 登录了系统".format("alice"))
log.warn("警告：value={} 超过阈值".format(100))
log.error("错误码: {}, 错误信息: {}".format(5001, "Connection refused"))

# 关闭
log.shutdown()
```

### 依赖

- Python 3.8+
- pyyaml（可选，仅配置文件加载时需要）

---

## 完整配置参数表

`init()` 函数接受一个字典作为配置参数：

### 基础参数

| 参数名 | 类型 | 默认值 | 必填 | 说明 |
|--------|------|--------|------|------|
| `level` | `str` | `"info"` | 否 | 全局最小日志等级 |
| `service_type` | `str` | `""` | 否 | 系统角色类型，如 `ability` |
| `service_name` | `str` | `""` | **是** | 实例名称，用于标识日志来源 |
| `instance_id` | `str` | `""` | 否 | 实例 ID |

### 输出参数

| 参数名 | 类型 | 默认值 | 必填 | 说明 |
|--------|------|--------|------|------|
| `output` | `str` | `"stdout"` | 否 | 输出目标：`stdout` / `rotate_file` / `dual` |
| `log_root` | `str` | 当前工作目录 | 否 | 日志文件根目录（未设置时使用默认值） |
| `stdout_fields` | `list[str]` | `["event", "caller"]` | 否 | stdout 输出的 JSON 字段 |

### 默认日志目录优先级

当 `log_root` 未设置时，按以下优先级确定默认目录：

1. **当前工作目录（CWD）**：执行命令时的目录
2. **脚本所在目录**：Python 脚本所在的目录
3. **`/tmp/insightoslog`**：最终回退目录

### 异步参数

| 参数名 | 类型 | 默认值 | 必填 | 说明 |
|--------|------|--------|------|------|
| `buffer_size` | `int` | `4096` | 否 | 异步队列缓冲区大小（字节） |
| `flush_interval` | `int` | `2` | 否 | 异步刷新间隔（秒） |

### 文件滚动参数

| 参数名 | 类型 | 默认值 | 必填 | 说明 |
|--------|------|--------|------|------|
| `file.path` | `str` | `""` | 否 | 自定义日志文件路径 |
| `file.max_size` | `int` | `5242880` (5MB) | 否 | 单个日志文件最大字节数 |
| `file.max_files` | `int` | `3` | 否 | 保留的旧日志文件数量 |

兼容说明：
`dict` / YAML 配置仍兼容旧别名 `path`、`max_bytes`、`backup_count`，但推荐统一使用 `file.path` / `file.max_size` / `file.max_files`。

### 链路追踪参数

| 参数名 | 类型 | 默认值 | 必填 | 说明 |
|--------|------|--------|------|------|
| `enable_tracing` | `bool` | `True` | 否 | 是否启用 Trace/Span 链路追踪 |

### StdoutFields 可选字段

| 字段值 | 说明 |
|--------|------|
| `meta` | 元信息（level、time） |
| `resource` | 资源信息（service_type、service_name 等） |
| `context` | 链路上下文（trace_id、span_id 等） |
| `event` | 事件信息（msg、request） |
| `data` | 数据信息（param、res、latency_ms） |
| `error` | 错误信息（type、message、stacktrace） |
| `caller` | 调用位置（file、line、function） |

---

## 日志级别

SDK 定义了 6 个日志级别，按从低到高排序：

| 级别常量 | 值 | 字符串 | 说明 |
|----------|----|--------|------|
| `LogLevel.TRACE` | `10` | `trace` | 最细粒度的调试信息（默认关闭） |
| `LogLevel.DEBUG` | `20` | `debug` | 开发调试时启用 |
| `LogLevel.INFO` | `30` | `info` | **默认级别** 接口成功、关键路径 |
| `LogLevel.WARN` | `40` | `warn` | 非预期但可恢复的情况 |
| `LogLevel.ERROR` | `50` | `error` | 预期失败、不影响主流程 |
| `LogLevel.FATAL` | `60` | `fatal` | 会导致进程终止的错误 |

**级别控制：**

```python
# 初始化时设置
log.init({"level": "debug", "service_name": "MyService"})

# 动态调整
log.set_level("warn")
level = log.get_level()
```

---

## 日志记录方式

SDK 提供三种日志记录方式：

### 方式一：便捷函数（推荐）

支持 Python 格式化风格：

```python
log.trace("这是一条 Trace 日志")
log.debug("这是一条 Debug 日志")
log.info("服务启动成功")
log.info("用户 {} 登录了系统".format("alice"))
log.warn("警告：value={} 超过阈值".format(100))
log.error("错误码: {}, 错误信息: {}".format(5001, "连接失败"))
log.fatal("致命错误，程序即将退出")
```

### 方式二：Logger2/Trace2 类封装（面向对象风格）

```python
# 初始化
log.Logger2.init({"service_name": "MyService", "level": "info"})

# 记录日志
log.Logger2.trace("Trace 日志")
log.Logger2.debug("Debug 日志")
log.Logger2.info("Info 日志")
log.Logger2.warn("Warn 日志")
log.Logger2.error("Error 日志")
log.Logger2.fatal("Fatal 日志")

# 获取/设置级别
log.Logger2.set_level("debug")
```

### 方式三：ContextLog 链式调用

```python
ctx = log.current_context()
ctx.info("处理请求") \
    .with_params({"user_id": 12345}) \
    .with_result({"status": "ok"}) \
    .latency(50) \
    .send()
```

---

## 输出模式

SDK 支持三种输出模式：

### 模式对比

| 模式 | 值 | 终端输出 | 文件输出 | 颜色高亮 | 使用场景 |
|------|----|---------|---------|---------|----------|
| stdout | 仅终端 | ✅ 紧凑格式 | ❌ | ✅ | 开发调试 |
| rotate_file | 仅文件 | ❌ | ✅ JSON | ❌ | 生产环境 |
| dual | 终端+文件 | ✅ 紧凑格式 | ✅ JSON | ✅ | **推荐** |

### stdout 模式

```python
log.init({
    "service_name": "MyService",
    "output": "stdout"
})
```

**输出示例：**
```
INFO 2026-04-10T14:30:00.000+08:00 [12345] {"event":{"msg":"服务启动成功"},"caller":{"file":"main.py","line":25}}
```

### rotate_file 模式

```python
log.init({
    "service_name": "MyService",
    "output": "rotate_file",
    "file": {
        "path": "./logs",
        "max_size": 10 * 1024 * 1024,  # 10MB
        "max_files": 5,
    }
})
```

**日志文件名：** `insightos-YYYY-MM-DD-HHMMSS.log`

### dual 模式

```python
log.init({
    "service_name": "MyService",
    "output": "dual",
    "log_root": "./logs"
})
```

同时输出到终端（带颜色）和文件（完整 JSON）。

---

## 日志结构

### 完整 JSON 结构

```json
{
  "meta": {
    "level": "INFO",
    "time": "2026-04-10T14:30:00.000+08:00"
  },
  "resource": {
    "service_type": "ability",
    "service_name": "MyService",
    "instance_id": "instance-001",
    "host": "server01",
    "pid": 12345
  },
  "caller": {
    "file": "main.py",
    "line": 42,
    "function": "main"
  },
  "event": {
    "msg": "用户登录成功",
    "request": {
      "method": "POST",
      "path": "/api/login",
      "latency_ms": 150,
      "status": 200
    }
  },
  "data": {
    "param": {"username": "alice"},
    "res": {"token": "xxx"},
    "latency_ms": 150,
    "truncated": false
  },
  "context": {
    "trace_id": "550436d474944d77a6833ba578d53e6d",
    "span_id": "767461a9d8ea41f29c3defe40a755ede",
    "parent_span_id": ""
  },
  "error": {
    "type": "NullPointerException",
    "message": "user is null",
    "stacktrace": "at UserService.create..."
  }
}
```

### 各字段详情

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| **meta** | object | 是 | 元信息 |
| `meta.level` | string | 是 | 日志级别 |
| `meta.time` | string | 是 | RFC3339 格式时间 |
| **resource** | object | 是 | 资源信息 |
| `resource.service_type` | string | 否 | 系统角色类型 |
| `resource.service_name` | string | 是 | 服务名称 |
| `resource.instance_id` | string | 否 | 实例 ID |
| `resource.host` | string | 否 | 主机名 |
| `resource.pid` | int | 否 | 进程 ID |
| **context** | object | 是 | 链路追踪上下文 |
| `context.trace_id` | string | 是 | 全链路唯一 ID |
| `context.span_id` | string | 否 | 当前执行单元 ID |
| `context.parent_span_id` | string | 否 | 父 span ID |
| **event** | object | 是 | 事件信息 |
| `event.msg` | string | 是 | 可读日志消息 |
| `event.request` | object | 否 | HTTP/RPC 请求信息 |
| **data** | object | 否 | 请求参数和返回结果 |
| `data.param` | json | 否 | 输入参数 |
| `data.res` | json | 否 | 返回结果 |
| `data.latency_ms` | int | 否 | 延迟时间 |
| `data.truncated` | bool | 否 | 是否截断 |
| **error** | object | 否 | 错误信息 |
| `error.type` | string | 是 | 异常类型 |
| `error.message` | string | 是 | 异常信息 |
| `error.stacktrace` | string | 否 | 堆栈跟踪 |
| **caller** | object | 否 | 调用位置信息 |
| `caller.file` | string | 是 | 文件名 |
| `caller.line` | int | 是 | 行号 |
| `caller.function` | string | 是 | 函数名 |

---

## 链路追踪

### 开启新链路

```python
# 开启新链路，自动生成 trace_id 和 span_id
log.start_new_trace()

log.info("这是链路开始")
```

### 继续已有链路

```python
# 从外部注入 trace_id 和 span_id
log.continue_trace("existing-trace-id", "existing-span-id")

log.info("继续已有链路")
```

### 注入完整上下文

```python
# 注入完整的链路上下文（包括 parent_span_id）
log.inject("trace-id", "span-id", "parent-span-id")
```

### 获取链路信息

```python
# 获取当前上下文
ctx = log.current_context()
print(ctx.trace_id)
print(ctx.span_id)

# 获取链路 ID
trace_id = log.get_trace_id()
span_id = log.get_span_id()

# 获取传播用的 HTTP Header
headers = log.get_propagation_headers()
# headers["trace_id"]
# headers["span_id"]
# headers["parent_span_id"]  # 通常为空，保留字段
```

`log.continue_trace(...)` 和 `log.extract_from_headers(...)` 都会为当前服务生成新的本地 `span_id`，并把上游 `span_id` 写入当前 `parent_span_id`。

### 从 Header 提取

```python
# 从 HTTP Header 提取链路信息
headers = {
    "X-InsightOSLog-TraceID": request.headers.get("X-InsightOSLog-TraceID"),
    "X-InsightOSLog-SpanID": request.headers.get("X-InsightOSLog-SpanID"),
    "X-InsightOSLog-ParentSpanID": request.headers.get("X-InsightOSLog-ParentSpanID")
}
log.extract_from_headers(headers)
```

### Trace2 类封装

```python
# 开启新链路
log.Trace2.start_new_trace()

# 注入上下文
log.Trace2.inject("tid", "sid", "psid")

# 获取传播 Header
log.Trace2.get_propagation_headers()

# 清除上下文
log.Trace2.clear_context()
```

---

## 上下文管理器

SDK 支持 RAII 风格的上下文管理器，自动保存和恢复上下文。

### with_context（手动释放）

```python
# 创建临时上下文
guard = log.with_context("custom-trace-id", "custom-span-id")
log.info("在临时上下文中记录的日志")
del guard  # 显式释放，自动恢复旧上下文
```

### with_context（with 语句）

```python
# 使用 with 语句自动管理
with log.with_context("custom-trace-id", "custom-span-id"):
    log.info("请求开始")
    # ... 业务逻辑 ...
    log.info("请求结束")
```

### with_context_from_ctx（从已有 Context 创建）

```python
# 从已有 Context 创建
existing_ctx = log.current_context()
guard = log.with_context_from_ctx(existing_ctx)
log.info("从已有上下文创建的日志")
del guard
```

### 嵌套 with_context

```python
guard1 = log.with_context("trace-1", "span-1")
log.info("第一层上下文")

with log.with_context("trace-2", "span-2"):
    log.info("第二层嵌套上下文")
# 自动恢复是第一层

log.info("回到第一层上下文")

del guard1
```

---

## 建造者模式

### 基本链式调用

```python
ctx = log.current_context()

ctx.info("处理请求") \
    .on_request({"method": "POST", "path": "/api/users", "latency_ms": 50}) \
    .with_data({"user_id": 12345}, {"status": "ok"}) \
    .send()
```

### 带错误日志

```python
ctx.error("请求失败") \
    .with_params({"endpoint": "/api/users"}) \
    .with_error(log.LogError("NullPointerException", "user repository is nil")) \
    .send()
```

### 建造者方法一览

| 方法 | 说明 | 参数示例 |
|------|------|----------|
| `on_request(req)` | 设置请求信息 | `{"method": "POST", "path": "/api"}` |
| `with_params(params)` | 设置请求参数 | `{"key": "value"}` |
| `with_result(result)` | 设置返回结果 | `{"status": "ok"}` |
| `with_data(params, result)` | 同时设置参数和结果 | - |
| `with_error(err)` | 设置错误信息 | `LogError(type, message, stacktrace)` |
| `latency(ms)` | 设置延迟时间（毫秒） | `50` |
| `truncate(b)` | 设置是否截断 | `True` |
| `send()` | 发送日志 | - |

---

## HTTP Header 传播

### Flask 框架示例

```python
from flask import Flask, request, make_response
import insightoslog as log

app = Flask(__name__)

@app.route("/api/users")
def handle_request():
    # 从 Header 提取链路信息
    headers = {
        log.HEADER_TRACE_ID: request.headers.get(log.HEADER_TRACE_ID),
        log.HEADER_SPAN_ID: request.headers.get(log.HEADER_SPAN_ID),
        log.HEADER_PARENT_SPAN_ID: request.headers.get(log.HEADER_PARENT_SPAN_ID)
    }
    log.extract_from_headers(headers)

    # 业务逻辑
    log.info("处理请求")
    result = do_something()

    # 传递给下游
    response = make_response(result)
    response.headers[log.HEADER_TRACE_ID] = log.get_trace_id()
    response.headers[log.HEADER_SPAN_ID] = log.get_span_id()
    return response
```

### 跨线程传播

```python
import threading
import insightoslog as log

# 主线程开启链路
log.start_new_trace()

# 准备子线程
log.prepare_for_child_thread()

# 在新线程中继承
def worker():
    log.inherit_from_prepared()
    log.info("子线程中的日志")

thread = threading.Thread(target=worker)
thread.start()
thread.join()
```

---

## 敏感信息过滤

SDK 自动过滤以下敏感字段：

| 字段名（不区分大小写） | 过滤效果 |
|----------------------|---------|
| password | 显示为 `***` |
| passwd | 显示为 `***` |
| token | 显示为 `***` |
| api_key | 显示为 `***` |
| apiKey | 显示为 `***` |
| secret | 显示为 `***` |
| credential | 显示为 `***` |
| private_key | 显示为 `***` |
| access_token | 显示为 `***` |

**示例：**

```python
log.info("用户登录: {}, 密码: {}".format("alice", "secret123"))
# 输出: 用户登录: alice, 密码: ***
```

---

## 完整配置示例

### 最小配置（仅必需字段）

```python
log.init({"service_name": "MyService"})
```

### 开发调试配置

```python
log.init({
    "level": "debug",              # 开启 Debug 级别
    "service_name": "MyService",
    "output": "stdout",            # 仅终端输出
    "enable_tracing": True         # 启用链路追踪
})
```

### 生产环境配置

```python
log.init({
    "level": "info",
    "service_type": "ability",
    "service_name": "user-service",
    "instance_id": "instance-001",
    "output": "dual",              # 终端+文件
    "log_root": "/var/log/insightos",
    "buffer_size": 8192,
    "flush_interval": 2,
    "enable_tracing": True,
    "file": {
        "max_size": 10 * 1024 * 1024, # 10MB
        "max_files": 10,
    }
})
```

### 高性能配置（大流量场景）

```python
log.init({
    "level": "info",
    "service_name": "high-perf-service",
    "output": "rotate_file",       # 仅文件
    "log_root": "./logs",
    "buffer_size": 65536,          # 64KB 大缓冲区
    "flush_interval": 5,           # 5秒刷新一次
    "file": {
        "max_size": 50 * 1024 * 1024, # 50MB 大文件
        "max_files": 20,
    }
})
```

### 自定义 stdout 字段

```python
log.init({
    "service_name": "my-service",
    "output": "stdout",
    "stdout_fields": ["event", "context"]  # 只输出 event 和 context
})
```

### 配置文件加载

```yaml
# InsightOSLogConfig.yaml
level: INFO
service_type: ability
service_name: MyService
instance_id: instance-001
output: dual
log_root: ./logs
buffer_size: 8192
flush_interval: 2
enable_tracing: true
file:
  max_size: 10485760
  max_files: 10
```

```python
log.init_from_config("InsightOSLogConfig.yaml")
```

---

## API 参考速查

### 初始化与关闭

| 函数 | 说明 |
|------|------|
| `init(param)` | 初始化日志系统 |
| `init_from_config(path)` | 从配置文件加载 |
| `shutdown()` | 关闭日志系统 |
| `flush()` | 刷新缓冲区 |
| `refresh_pid()` | 刷新 PID |
| `is_initialized()` | 检查是否已初始化 |

### 级别控制

| 函数 | 说明 |
|------|------|
| `set_level(level)` | 设置日志级别 |
| `get_level()` | 获取当前级别 |

### 日志记录

| 函数 | 说明 |
|------|------|
| `trace(msg)` | 记录 Trace 级别 |
| `debug(msg)` | 记录 Debug 级别 |
| `info(msg)` | 记录 Info 级别 |
| `warn(msg)` | 记录 Warn 级别 |
| `error(msg)` | 记录 Error 级别 |
| `fatal(msg)` | 记录 Fatal 级别并退出 |

### Logger2/Trace2 类

| 方法 | 说明 |
|------|------|
| `Logger2.init(param)` | 初始化 |
| `Logger2.info(msg)` | 记录日志 |
| `Trace2.start_new_trace()` | 开启新链路 |
| `Trace2.inject(tid, sid, psid)` | 注入上下文 |
| `Trace2.get_propagation_headers()` | 获取传播 Header |
| `Trace2.clear_context()` | 清除上下文 |

### 链路追踪

| 函数 | 说明 |
|------|------|
| `start_new_trace()` | 开启新链路 |
| `continue_trace(tid, sid)` | 继续已有链路 |
| `inject(tid, sid, psid)` | 注入完整上下文 |
| `get_trace_id()` | 获取 TraceID |
| `get_span_id()` | 获取 SpanID |
| `get_parent_span_id()` | 获取 ParentSpanID |
| `get_propagation_headers()` | 获取传播 Header |
| `extract_from_headers(h)` | 从 Header 容器提取 |
| `extract_from_headers(tid, sid, psid)` | 从 Header 值提取 |
| `generate_trace_id()` | 生成 TraceID |
| `generate_span_id()` | 生成 SpanID |
| `prepare_for_child_thread()` | 准备跨线程 |
| `inherit_from_prepared()` | 继承准备好的上下文 |
| `inherit_from_parent()` | 自动继承父上下文 |

### 上下文管理

| 函数 | 说明 |
|------|------|
| `current_context()` | 获取当前上下文 |
| `make_context(tid, sid, psid)` | 创建上下文 |
| `with_context(tid, sid)` | 创建上下文管理器（RAII） |
| `with_context_from_ctx(ctx)` | 从已有 Context 创建 |

### 建造者模式

| 方法 | 说明 |
|------|------|
| `ctx.info(msg)` | Info 级别链式调用 |
| `ctx.error(msg)` | Error 级别链式调用 |

### 资源管理

| 函数 | 说明 |
|------|------|
| `global_resource()` | 获取全局资源 |
| `set_global_resource(r)` | 设置全局资源 |

### 数据结构

| 类型 | 说明 |
|------|------|
| `LogLevel` | 日志级别枚举 |
| `InitParam` | 初始化参数 |
| `Context` / `LogContext` | 链路上下文 |
| `Resource` | 资源信息 |
| `Caller` | 调用位置 |
| `LogError` | 错误信息 |
| `EventRequest` | 请求信息 |
| `LogBuilder` | 链式日志构建器 |
| `ContextWithLog` | 上下文管理器 |

### Header 常量

| 常量 | 值 |
|------|-----|
| `HEADER_TRACE_ID` | `X-InsightOSLog-TraceID` |
| `HEADER_SPAN_ID` | `X-InsightOSLog-SpanID` |
| `HEADER_PARENT_SPAN_ID` | `X-InsightOSLog-ParentSpanID` |

---

## 许可证

MIT License

Copyright (c) 2026 InsightOS Team


