Grafana Tempo — distributed tracing bez limitów kosztowych
Opublikowano: 10 kwietnia 2026 · Kategoria: VPS
Distributed tracing to brakujące ogniwo obserwabilności — metryki mówią co się dzieje, logi mówią co aplikacja zapisała, ale traces pokazują dokładnie jak przepłynęło konkretne żądanie przez cały system. Grafana Tempo przechowuje traces tanio w S3/MinIO i integruje się bezpośrednio z Grafaną — bez kosztownego Elasticsearch.
Architektura Tempo — uproszczona i rozszerzona
Tempo można uruchomić w trybie all-in-one (jeden proces) lub distributed (osobne komponenty). Dla małych i średnich środowisk all-in-one z MinIO jest w zupełności wystarczające:
# docker-compose.yml — Tempo all-in-one + MinIO
version: "3.8"
services:
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
volumes:
- minio_data:/data
ports:
- "9000:9000"
tempo:
image: grafana/tempo:latest
command: ["-config.file=/etc/tempo/config.yaml"]
volumes:
- ./tempo-config.yaml:/etc/tempo/config.yaml
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "3200:3200" # Tempo HTTP API
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
minio_data: Konfiguracja Tempo — tempo-config.yaml
# tempo-config.yaml
server:
http_listen_port: 3200
distributor:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
grpc:
endpoint: 0.0.0.0:4317
jaeger: # Akceptuj też Jaeger format
protocols:
thrift_http:
endpoint: 0.0.0.0:14268
zipkin: # Akceptuj Zipkin format
endpoint: 0.0.0.0:9411
storage:
trace:
backend: s3
s3:
endpoint: minio:9000
bucket: tempo-traces
access_key: minioadmin
secret_key: minioadmin
insecure: true
wal:
path: /tmp/tempo/wal
compactor:
compaction:
block_retention: 336h # 14 dni retention
querier:
frontend_worker:
frontend_address: localhost:9095 Utwórz bucket MinIO przed uruchomieniem:
mc alias set local http://localhost:9000 minioadmin minioadmin mc mb local/tempo-traces
Instrumentacja OpenTelemetry — Node.js
npm install \ @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http
// tracing.ts — importuj jako pierwszy moduł
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { Resource } from '@opentelemetry/resources';
import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
const sdk = new NodeSDK({
resource: new Resource({
[SEMRESATTRS_SERVICE_NAME]: 'my-api-service',
}),
traceExporter: new OTLPTraceExporter({
url: 'http://tempo:4318/v1/traces',
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
console.log('OpenTelemetry tracing initialized');
// Uruchomienie:
// node -r ./dist/tracing.js dist/app.js Tempo datasource w Grafanie
Dodaj datasource Tempo w Grafanie: Configuration → Data Sources → Add → Tempo. Ustaw URL: http://tempo:3200. Opcjonalnie skonfiguruj Service Graph (wymaga
Prometheus ze span metrics) i Node Graph. Po zapisaniu przejdź do Explore → Tempo i wyszukaj traces.
TraceQL — język zapytań
TraceQL to zaawansowany język zapytań do filtrowania traces i spans. Kilka praktycznych przykładów:
| Zapytanie TraceQL | Co zwraca |
|---|---|
{ .http.url = "/api/orders" } | Traces z żądaniami do /api/orders |
{ duration > 500ms } | Wolne traces powyżej 500ms |
{ .error = true } | Traces zawierające błędy |
{ .service.name = "api" && .db.system = "postgresql" } | Zapytania do PostgreSQL z serwisu api |
{ .http.status_code >= 500 } | Traces z błędami 5xx HTTP |
Porównanie: Tempo vs Jaeger vs Zipkin
| Cecha | Grafana Tempo | Jaeger | Zipkin |
|---|---|---|---|
| Storage backend | S3/MinIO/GCS (tani) | Elasticsearch/Cassandra | Elasticsearch/MySQL |
| Własne UI | Brak (używa Grafany) | Wbudowane UI | Wbudowane UI |
| Język zapytań | TraceQL | Ograniczony search | Ograniczony search |
| Integracja Grafana | Natywna (LGTM stack) | Plugin (gorszy UX) | Plugin (gorszy UX) |
| Koszt storage | Niski (S3 ~$0.02/GB) | Wysoki (ES cluster) | Wysoki (ES cluster) |