技能创建器
skill-creator
创建、改进和评估自定义技能,把专业流程转化为可重复使用的 AI 能力。
instrument-distributed-tracing【数据与研究】Instrument applications with OpenTelemetry for distributed tracing, including auto and manual instrumentation, context propagation, sampling strategies, and integration with Jaeger or Tempo. Use when debugging latency issues in distributed systems, understanding request flow across microservices, correlating traces with logs and metrics for root caus…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
以 OpenTelemetry 建分布式追蹤→跨微服務追請求、識性能瓶頸。
全配置文件與模板詳見 Extended Examples。
部署 Jaeger 或 Grafana Tempo 以收存追蹤。
甲:Jaeger all-in-one(開發/測試):
# docker-compose.yml
version: '3.8'
services:
jaeger:
image: jaegertracing/all-in-one:1.51
ports:
- "5775:5775/udp" # Zipkin compact thrift
- "6831:6831/udp" # Jaeger compact thrift
- "6832:6832/udp" # Jaeger binary thrift
- "5778:5778" # Serve configs
- "16686:16686" # Jaeger UI
- "14268:14268" # Jaeger HTTP thrift
- "14250:14250" # Jaeger GRPC
- "9411:9411" # Zipkin compatible endpoint
environment:
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
- COLLECTOR_OTLP_ENABLED=true
restart: unless-stopped
乙:Grafana Tempo(生產、可擴):
# docker-compose.yml
version: '3.8'
services:
tempo:
image: grafana/tempo:2.3.0
command: ["-config.file=/etc/tempo.yaml"]
volumes:
- ./tempo.yaml:/etc/tempo.yaml
- tempo-data:/tmp/tempo
ports:
- "3200:3200" # Tempo HTTP
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "9411:9411" # Zipkin
restart: unless-stopped
volumes:
tempo-data:
Tempo 配置(tempo.yaml):
server:
http_listen_port: 3200
distributor:
receivers:
jaeger:
# ... (see EXAMPLES.md for complete configuration)
生產用 S3 存:
storage:
trace:
backend: s3
s3:
bucket: tempo-traces
endpoint: s3.amazonaws.com
region: us-east-1
wal:
path: /tmp/tempo/wal
pool:
max_workers: 100
queue_depth: 10000
得:後端可達,可經 OTLP 收追蹤,Jaeger UI 或 Grafana 初示「無追蹤」。
敗:
netstat -tulpn | grep -E '(4317|16686|3200)'docker logs jaeger 或 docker logs tempocurl http://localhost:4318/v1/traces -vtempo -config.file=/etc/tempo.yaml -verify-config 驗配置用 OpenTelemetry 自動建以少改碼。
Python + Flask:
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
# app.py
from flask import Flask
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# ... (see EXAMPLES.md for complete configuration)
Go + Gin:
go get go.opentelemetry.io/otel
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
go get go.opentelemetry.io/otel/sdk/trace
go get go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin
package main
import (
"context"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel"
# ... (see EXAMPLES.md for complete configuration)
Node.js + Express:
npm install @opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-grpc
// tracing.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
# ... (see EXAMPLES.md for complete configuration)
得:受建服務之追蹤見於 Jaeger UI 或 Grafana,HTTP 請求自動成 span。
敗:
OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317OTEL_LOG_LEVEL=debug(Python)、OTEL_LOG_LEVEL=DEBUG(Node.js)為業務邏輯、數據庫查、外部調用造自定 span。
Python 手動 span:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def process_order(order_id):
# Create a span for the entire operation
# ... (see EXAMPLES.md for complete configuration)
Go 手動 span:
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
# ... (see EXAMPLES.md for complete configuration)
span 屬性佳法:
http.method、http.status_code、db.system、db.statementuser.id、order.id、product.categoryinstance.id、region、availability_zonespan.RecordError(err) 及 span.SetStatus(codes.Error, message)span.AddEvent("cache_miss")得:自定 span 見於追蹤視圖,父子關係正,屬性見於 span 詳,錯高亮。
敗:
defer span.End(),Python 用 with)確保追蹤脈絡跨服務邊與異步操作流轉。
HTTP 頭傳(W3C Trace Context):
# Client side (Python with requests)
import requests
from opentelemetry import trace
from opentelemetry.propagate import inject
tracer = trace.get_tracer(__name__)
# ... (see EXAMPLES.md for complete configuration)
// Server side (Go with Gin)
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
)
# ... (see EXAMPLES.md for complete configuration)
消息隊列傳(Kafka):
# Producer
from opentelemetry.propagate import inject
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers=['kafka:9092'])
# ... (see EXAMPLES.md for complete configuration)
# Consumer
from opentelemetry.propagate import extract
def process_message(msg):
# Extract trace context from Kafka headers
headers = {k: v.decode('utf-8') for k, v in msg.headers}
ctx = extract(headers)
# Continue the trace
with tracer.start_as_current_span("process_order_event", context=ctx):
order_id = json.loads(msg.value)['order_id']
handle_order(order_id)
異步操作(Python asyncio):
import asyncio
from opentelemetry import trace, context
async def async_operation():
# Capture current context
token = context.attach(context.get_current())
try:
with tracer.start_as_current_span("async_database_query"):
await asyncio.sleep(0.1) # Simulated async work
return "result"
finally:
context.detach(token)
得:追蹤跨多服務,追蹤 ID 跨服務邊一致,父子關係存。
敗:
otel.propagation.set_global_textmap(TraceContextTextMapPropagator())traceparent 頭值施採樣以減追蹤量與本而保可見。
採樣策略:
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.sampling import (
ParentBased,
TraceIdRatioBased,
StaticSampler,
Decision
# ... (see EXAMPLES.md for complete configuration)
Tempo 尾部採樣:
於 tempo.yaml 配:
overrides:
defaults:
metrics_generator:
processors: [service-graphs, span-metrics]
storage:
path: /tmp/tempo/generator/wal
remote_write:
- url: http://prometheus:9090/api/v1/write
send_exemplars: true
# Tail sampling (requires tempo-query)
ingestion_rate_limit_bytes: 5000000
ingestion_burst_size_bytes: 10000000
用 Grafana Tempo TraceQL 動態採樣:
# Sample traces with errors
{ status = error }
# Sample slow traces (>1s)
{ duration > 1s }
# Sample specific services
{ resource.service.name = "checkout-service" }
得:追蹤量降至目標比,錯追蹤必採,採樣決見於追蹤元。
敗:
ingestion_burst_size_bytes)otel_traces_dropped_total 指標鏈追蹤至指標與日誌以統一可觀察性。
於日誌加追蹤 ID(Python):
import logging
from opentelemetry import trace
# Custom log formatter with trace context
class TraceFormatter(logging.Formatter):
def format(self, record):
# ... (see EXAMPLES.md for complete configuration)
由追蹤生指標(Tempo):
# tempo.yaml
metrics_generator:
registry:
external_labels:
cluster: production
storage:
# ... (see EXAMPLES.md for complete configuration)
此生 Prometheus 指標:
traces_service_graph_request_total - 服務間請求計traces_span_metrics_duration_seconds - span 時長直方圖traces_spanmetrics_calls_total - span 調用計由指標查追蹤(Grafana):
於 Grafana 中為 Prometheus 源加 exemplar 支持:
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
jsonData:
exemplarTraceIdDestinations:
- name: trace_id
datasourceName: Tempo
於 Grafana 儀表板啟 exemplar:
{
"fieldConfig": {
"defaults": {
"custom": {
"showExemplars": true
}
}
}
}
得:點指標 exemplar 開追蹤,日誌示追蹤 ID,追蹤鏈日誌,跨信號統一調試。
敗:
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) and on() exemplarcontext 於下游調用→斷追蹤。必顯式傳。defer span.End()(Go)或 with(Python)→ span 長開、內存泄。span.RecordError() →失調試信息。必於 span 記錯。ParentBased 採樣器以守上游採樣。correlate-observability-signals - 指標、日誌、追蹤經追蹤 ID 鏈以統一調試setup-prometheus-monitoring - 以 Tempo 指標生成器由追蹤生指標configure-log-aggregation - 日誌加追蹤 ID 以合分布追蹤build-grafana-dashboards - 於儀表板可視化追蹤衍指標與 exemplar 鏈