Full link tracking and error interception for koatty.
- 🔍 全链路追踪: 基于OpenTelemetry的分布式链路追踪
- 📊 多协议指标收集: 支持HTTP、WebSocket、gRPC的指标收集并导出到Prometheus
- 🚨 错误拦截: 统一的错误处理和异常捕获
- 🔗 服务拓扑: 自动分析和记录服务依赖关系
- ⚡ 性能监控: 请求响应时间、错误率等关键指标
- 🔄 重试机制: 可配置的请求重试策略
- 🎯 请求ID追踪: 全链路请求ID生成和传播
- 🛡️ 并发安全: 线程安全的指标收集和Span管理
- 🚀 高性能: 路径标准化缓存、批量处理、内存优化
npm install koatty_trace
# 或
pnpm add koatty_trace
import { Trace } from 'koatty_trace';
import { Koatty } from 'koatty_core';
const app = new Koatty();
// 基础配置
app.use(Trace({
enableTrace: true,
timeout: 10000,
requestIdHeaderName: 'X-Request-Id'
}, app));
import { Trace } from 'koatty_trace';
app.use(Trace({
enableTrace: true,
// Prometheus指标配置
metricsConf: {
metricsEndpoint: '/metrics', // 指标端点路径
metricsPort: 9464, // 指标服务端口
reportInterval: 5000, // 上报间隔(ms)
defaultAttributes: { // 默认标签
service: 'my-service',
version: '1.0.0'
}
}
}, app));
框架会自动收集以下多协议指标,支持HTTP、WebSocket和gRPC:
- 类型: Counter
- 描述: 所有协议的请求总数统计
- 标签:
method
: 请求方法 (GET, POST, PUT, DELETE等)status
: 状态码 (HTTP状态码或gRPC状态码)path
: 标准化的请求路径 (如/users/:id
)protocol
: 协议类型 (http
,websocket
,grpc
)compression
: 压缩类型 (WebSocket:deflate
/none
, gRPC:gzip
/brotli
/none
)grpc_service
: gRPC服务名 (仅gRPC协议)
- 类型: Counter
- 描述: 所有协议的错误请求统计
- 标签:
method
: 请求方法status
: 状态码path
: 标准化的请求路径protocol
: 协议类型error_type
: 错误类型- HTTP/WebSocket:
client_error
(4xx),server_error
(5xx) - gRPC:
grpc_error
(非0状态码)
- HTTP/WebSocket:
- 类型: Histogram
- 描述: 所有协议的请求响应时间分布
- 单位: 秒
- 桶边界: [0.1, 0.5, 1, 2.5, 5, 10]
- 标签:
method
: 请求方法status
: 状态码path
: 标准化的请求路径protocol
: 协议类型
- 类型: Counter
- 描述: WebSocket连接统计
- 标签:
protocol
: 协议类型 (websocket)service
: 服务名称
框架会自动检测请求协议类型:
// HTTP请求
GET /api/users HTTP/1.1
-> protocol: "http"
// WebSocket连接
GET /ws HTTP/1.1
Upgrade: websocket
-> protocol: "websocket"
// gRPC请求
POST /package.UserService/GetUser HTTP/2
Content-Type: application/grpc
-> protocol: "grpc"
为了减少指标的基数,框架会自动标准化请求路径:
// 原始路径 -> 标准化路径
'/users/123' -> '/users/:id'
'/users/123/profile' -> '/users/:id/profile'
'/api/v1/users/550e8400-e29b-41d4-a716-446655440000' -> '/api/v1/users/:uuid'
'/posts/507f1f77bcf86cd799439011' -> '/posts/:objectid'
// gRPC服务路径
'/package.UserService/GetUser' -> '/package.UserService/GetUser' (保持原样)
启动应用后,可以通过以下方式查看指标:
# 访问指标端点
curl http://localhost:9464·
# 示例输出
# HELP requests_total Total requests across all protocols
# TYPE requests_total counter
requests_total{method="GET",status="200",path="/api/users",protocol="http"} 42
requests_total{method="POST",status="0",path="/package.UserService/GetUser",protocol="grpc",grpc_service="package.UserService",compression="gzip"} 15
requests_total{method="GET",status="101",path="/ws",protocol="websocket",compression="deflate"} 8
# HELP response_time_seconds Response time in seconds across all protocols
# TYPE response_time_seconds histogram
response_time_seconds_bucket{method="GET",status="200",path="/api/users",protocol="http",le="0.1"} 35
response_time_seconds_bucket{method="POST",status="0",path="/package.UserService/GetUser",protocol="grpc",le="0.1"} 12
# HELP websocket_connections_total Total WebSocket connections
# TYPE websocket_connections_total counter
websocket_connections_total{protocol="websocket",service="my-service"} 5
app.use(Trace({
// 基础配置
enableTrace: true, // 是否启用链路追踪
timeout: 10000, // 请求超时时间(ms)
encoding: 'utf-8', // 响应编码
requestIdHeaderName: 'X-Request-Id', // 请求ID头名称
requestIdName: 'requestId', // 请求ID属性名
asyncHooks: false, // 是否启用异步钩子
// 指标配置
metricsConf: {
metricsEndpoint: '/metrics', // Prometheus指标端点
metricsPort: 9464, // 指标服务端口
reportInterval: 5000, // 上报间隔(ms)
defaultAttributes: {}, // 默认指标标签
reporter: (metrics) => { // 自定义指标上报器
console.log('Metrics:', metrics);
}
},
// OpenTelemetry配置
opentelemetryConf: {
endpoint: "http://localhost:4318/v1/traces", // OTLP端点
enableTopology: false, // 是否启用拓扑分析
headers: {}, // OTLP请求头
resourceAttributes: {}, // 资源属性
samplingRate: 1.0, // 采样率
timeout: 10000, // 导出超时时间
spanTimeout: 30000, // Span超时时间
maxActiveSpans: 1000, // 最大活跃Span数
},
// 重试配置
retryConf: {
enabled: false, // 是否启用重试
count: 3, // 最大重试次数
interval: 1000, // 重试间隔(ms)
conditions: (error) => true // 重试条件判断函数
}
}, app));
在prometheus.yml
中添加抓取配置:
scrape_configs:
- job_name: 'koatty-app'
static_configs:
- targets: ['localhost:9464']
scrape_interval: 15s
metrics_path: /metrics
推荐的Grafana查询示例:
# 请求QPS
rate(http_requests_total[5m])
# 错误率
rate(http_errors_total[5m]) / rate(http_requests_total[5m])
# 平均响应时间
rate(http_response_time_seconds_sum[5m]) / rate(http_response_time_seconds_count[5m])
# P95响应时间
histogram_quantile(0.95, rate(http_response_time_seconds_bucket[5m]))
# 安装依赖
pnpm install
# 运行测试
pnpm test
# 运行指标收集测试
pnpm test test/metrics.test.ts
# 代码检查
pnpm run eslint
# 构建项目
pnpm run build
BSD-3-Clause License
欢迎提交Issue和Pull Request来改进这个项目。