Agent Skills
› grafana/skills
› tempo
tempo
GitHub部署Grafana Tempo分布式追踪后端,配置对象存储与多租户,通过TraceQL查询慢请求或错误,调试链路数据缺失,以及关联日志、指标和性能分析。
Trigger Scenarios
部署 Tempo 追踪后端
编写 TraceQL 查询慢请求
调试 Explore 中无追踪数据
配置 S3/GCS/Azure 块存储
设置追踪-日志-指标关联
Install
npx skills add grafana/skills --skill tempo -g -y
SKILL.md
Frontmatter
{
"name": "tempo",
"license": "Apache-2.0",
"description": "Stand up Grafana Tempo as a cost-efficient distributed-tracing backend that only needs object storage, and write TraceQL queries against it. Covers OTLP + Jaeger + Zipkin ingestion, the distributor → live-store → block-builder → object-storage write path, metrics-generator for RED spanmetrics + service graphs, Helm `tempo-distributed` deployment, multi-tenant `X-Scope-OrgID`, TraceQL span \/ resource \/ event scopes, structural operators (`>>`, `<<`), `rate()` + `quantile_over_time` metrics, and the traces-to-logs \/ metrics \/ profiles datasource links. Use when deploying Tempo, writing a TraceQL query for slow \/ errored requests, debugging \"no traces showing in Explore\", sizing queriers \/ compactors, configuring S3 \/ GCS \/ Azure block storage, or wiring trace ↔ log ↔ profile correlation — even when the user says \"tracing backend\", \"find slow requests\", \"show me the service graph\", \"store traces in S3\", \"Jaeger compatible store\", or \"what called this span\" without naming Tempo."
}
Grafana Tempo
Cost-efficient distributed tracing. Accepts OTLP / Jaeger / Zipkin / OpenCensus / Kafka. Stores Parquet blocks in S3/GCS/Azure.
Prerequisites
- Docker (quick start) or Kubernetes (production)
- Object storage bucket (S3/GCS/Azure) for distributed deployments
- An OTLP-emitting app or
tempo-clifor synthetic traffic - A Grafana stack with a Tempo datasource for querying
Common Workflows
1. Stand up Tempo locally + verify ingestion
# 1. Start the official Docker Compose example
git clone https://github.com/grafana/tempo.git
cd tempo/example/docker-compose/local
mkdir -p tempo-data
docker compose up -d
# 2. Verify readiness
curl -sf http://localhost:3200/ready # → "ready"
# 3. Send a synthetic OTLP span (full payload in scratch terminal)
curl -X POST -H 'Content-Type: application/json' \
http://localhost:4318/v1/traces \
-d '{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"my-service"}}]},
"scopeSpans":[{"spans":[{"traceId":"5B8EFFF798038103D269B633813FC700","spanId":"EEE19B7EC3C1B100",
"name":"my-op","startTimeUnixNano":1689969302000000000,"endTimeUnixNano":1689969302500000000,"kind":2}]}]}]}'
# 4. Verify the trace landed (ingestion-counter > 0 and the trace is fetchable)
curl -s http://localhost:3200/metrics | grep tempo_distributor_spans_received_total | head
curl -s http://localhost:3200/api/v2/traces/5B8EFFF798038103D269B633813FC700 | jq '.batches | length'
# Expect > 0.
# 5. In Grafana → Explore → Tempo, run TraceQL: {resource.service.name="my-service"}
2. Send traces from an app via Alloy
// alloy.river
otelcol.receiver.otlp "default" {
grpc { endpoint = "0.0.0.0:4317" }
http { endpoint = "0.0.0.0:4318" }
output { traces = [otelcol.exporter.otlp.tempo.input] }
}
otelcol.exporter.otlp "tempo" {
client {
endpoint = "tempo:4317"
tls { insecure = true }
}
}
# Verify Alloy forwarded successfully
curl -s http://localhost:12345/metrics | grep otelcol_exporter_sent_spans
# Then: same Grafana → Explore → Tempo check.
3. Write + run TraceQL
# Slow requests from a service
{ resource.service.name = "frontend" && duration > 1s }
# Server span that has a downstream error (structural)
{ kind = server } >> { status = error }
# Error rate per service (metrics)
{ status = error } | rate() by (resource.service.name)
Full operator + scope cheat sheet, intrinsics list, metric functions: references/traceql.md.
# Via the API
curl -sG --data-urlencode 'q={resource.service.name="frontend" && duration > 1s}' \
--data-urlencode "start=$(date -d '1h ago' +%s)" --data-urlencode "end=$(date +%s)" \
http://localhost:3200/api/search | jq '.traces | length'
4. Deploy on Kubernetes (Helm)
helm repo add grafana https://grafana.github.io/helm-charts
helm install tempo grafana/tempo-distributed --version 1.61.3 \
--set storage.trace.backend=s3 \
--set storage.trace.s3.bucket=my-tempo-bucket \
--set storage.trace.s3.region=us-east-1
# Verify every pod is Ready (distributor, ingester, querier, query-frontend, compactor)
kubectl get pods -n default -l app.kubernetes.io/instance=tempo
kubectl port-forward svc/tempo-query-frontend 3200:3200 &
curl -sf http://localhost:3200/ready
Multi-tenancy
multitenancy_enabled: true
# All requests must include header: X-Scope-OrgID: <tenant-id>
Full architecture, ports, performance tuning, metrics-generator config, multi-tenant client snippets, traces-to-logs/metrics/profiles datasource: references/architecture-and-operations.md.
Troubleshooting
/ready→ 503 → ingester still joining; checktempo_ingester_*metrics + logs- 429 on push → raise
max_outstanding_per_tenantor per-tenant ingest limits - "no traces showing in Explore" → confirm
X-Scope-OrgIDmatches between writer and Grafana datasource - TraceQL slow → narrow
start/end, add a service.name filter, enable dedicated Parquet columns for hot attributes
Resources
- Tempo docs
- TraceQL reference
references/traceql.md— full TraceQL cheat sheetreferences/architecture-and-operations.md— components, ports, Helm, tuning, datasource links
Version History
- b583762 Current 2026-07-06 00:36


