技能创建器
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 以接並存追蹤。
選 A: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
選 B: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 鏈