title: "可观测性实战:从日志、指标到链路追踪的完整体系"
date: "2026-07-10"
tags: ["可观测性", "监控", "日志", "链路追踪"]
可观测性实战:从日志、指标到链路追踪的完整体系
可观测性(Observability)是理解系统运行状态的核心能力。它由三个支柱组成:日志(Logs)、指标(Metrics)和链路追踪(Traces)。
三大支柱
日志(Logs)
记录离散的事件信息。
PYTHON
import logging
import structlog
# 结构化日志
structlog.configure(
processors=[
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.add_log_level,
structlog.processors.JSONRenderer()
]
)
logger = structlog.get_logger()
def process_order(order_id: str, user_id: str):
logger.info(
"order_processing_started",
order_id=order_id,
user_id=user_id,
service="order-service"
)
try:
# 业务逻辑
result = validate_order(order_id)
logger.info(
"order_validated",
order_id=order_id,
validation_result=result
)
except ValidationError as e:
logger.error(
"order_validation_failed",
order_id=order_id,
error=str(e),
error_type=type(e).__name__
)
raise指标(Metrics)
记录可聚合的数值型数据。
PYTHON
from prometheus_client import Counter, Histogram, Gauge, start_http_server
# 计数器
request_counter = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status']
)
# 直方图
request_duration = Histogram(
'http_request_duration_seconds',
'HTTP request duration',
['method', 'endpoint'],
buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 5.0]
)
# 仪表盘
active_connections = Gauge(
'active_connections',
'Number of active connections'
)
# 使用
from fastapi import FastAPI, Request
import time
app = FastAPI()
@app.middleware("http")
async def metrics_middleware(request: Request, call_next):
start_time = time.time()
active_connections.inc()
try:
response = await call_next(request)
status = response.status_code
except Exception:
status = 500
raise
finally:
duration = time.time() - start_time
active_connections.dec()
request_counter.labels(
method=request.method,
endpoint=request.url.path,
status=status
).inc()
request_duration.labels(
method=request.method,
endpoint=request.url.path
).observe(duration)
return response
# 启动指标服务器
start_http_server(8000)链路追踪(Traces)
记录跨服务的请求流转。
PYTHON
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
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
# 配置追踪
provider = TracerProvider()
exporter = OTLPSpanExporter(endpoint="http://jaeger:4317")
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
# FastAPI 自动追踪
FastAPIInstrumentor.instrument_app(app)
# 手动追踪
@app.get("/api/orders/{order_id}")
async def get_order(order_id: str):
with tracer.start_as_current_span("get_order") as span:
span.set_attribute("order_id", order_id)
# 调用其他服务
with tracer.start_as_current_span("fetch_user_data"):
user_data = await user_service.get_user(order_id)
with tracer.start_as_current_span("fetch_order_items"):
items = await inventory_service.get_items(order_id)
span.set_attribute("item_count", len(items))
return {"order": order_id, "user": user_data, "items": items}ELK 日志栈
YAML
# docker-compose.yml
version: '3'
services:
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
volumes:
- es_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
logstash:
image: logstash:8.11.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5044:5044"
kibana:
image: kibana:8.11.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
volumes:
es_data:RUBY
# logstash.conf
input {
beats {
port => 5044
}
}
filter {
json {
source => "message"
}
if [service] {
mutate {
add_field => { "app_name" => "%{service}" }
}
}
date {
match => ["timestamp", "ISO8601"]
target => "@timestamp"
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
}
}Prometheus + Grafana
YAML
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'api-service'
static_configs:
- targets: ['api:8000']
metrics_path: '/metrics'
- job_name: 'order-service'
static_configs:
- targets: ['order:8000']YAML
# docker-compose.yml
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
volumes:
grafana_data:告警规则
YAML
# alert_rules.yml
groups:
- name: api_alerts
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate detected"
description: "Error rate is {{ $value | humanizePercentage }} for {{ $labels.endpoint }}"
- alert: HighLatency
expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "High latency detected"
description: "P99 latency is {{ $value }}s for {{ $labels.endpoint }}"
- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Service {{ $labels.job }} is down"统一可观测性
PYTHON
from opentelemetry import trace, metrics
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.metrics import MeterProvider
# 统一资源标识
resource = Resource.create({
"service.name": "order-service",
"service.version": "1.0.0",
"deployment.environment": "production"
})
# 追踪
tracer_provider = TracerProvider(resource=resource)
trace.set_tracer_provider(tracer_provider)
# 指标
meter_provider = MeterProvider(resource=resource)
metrics.set_meter_provider(meter_provider)
# 日志(通过 OpenTelemetry)
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import LoggerProvider
logger_provider = LoggerProvider(resource=resource)
set_logger_provider(logger_provider)可观测性不是"出了问题再看",而是"随时能理解系统在做什么"。建立完整的可观测性体系,是保障系统稳定性的基础投资。
读者评论 3