Migrate from Grafana Stack to TraceKit
Running Grafana + Tempo + Loki means managing three separate tools, three data stores, and three query languages. TraceKit consolidates tracing, dashboards, and log correlation into one platform.
Migration Steps
Audit Your Grafana Stack Components
Identify which Grafana ecosystem tools you are running (Grafana, Tempo, Loki, Mimir, Alloy/Agent) and which data sources each dashboard uses. TraceKit replaces the tracing pipeline (Tempo) and provides built-in dashboards (replacing Grafana for APM use cases).
| Category | Before | After (TraceKit) | Notes |
|---|---|---|---|
| Component | Grafana (visualization) | TraceKit Dashboard | Built-in dashboards for APM; Grafana can remain for infrastructure |
| Component | Tempo (trace storage) | TraceKit (managed trace storage) | No self-hosted trace backend needed |
| Component | Loki (log aggregation) | TraceKit (trace-linked events) | Span events replace log-to-trace correlation |
| Component | Grafana Alloy / Agent (collector) | TraceKit SDK (direct send) | SDK sends directly; no collector pipeline |
Replace Tempo Trace Ingestion
Point your OpenTelemetry instrumentation from the Tempo OTLP endpoint to TraceKit's ingestion endpoint. If you were using Grafana Alloy or the Grafana Agent as a collector, you can remove it -- TraceKit SDKs send directly.
| Category | Before | After (TraceKit) | Notes |
|---|---|---|---|
| Ingestion | TEMPO_STORAGE_TRACE_BACKEND (s3/gcs/azure) | (managed by TraceKit) | No storage backend to configure |
| Ingestion | OTEL_EXPORTER_OTLP_ENDPOINT (Tempo endpoint) | TRACEKIT_ENDPOINT | Point OTLP exporter to TraceKit or use native SDK |
| Ingestion | Tempo distributor port (default 4317) | TRACEKIT_ENDPOINT (HTTPS) | Single HTTPS endpoint, no gRPC port management |
Install TraceKit SDK (Optional OTLP Alternative)
While you can keep sending via OTLP, TraceKit's native SDKs offer additional features like live code monitoring and PII scrubbing. Install the SDK alongside your existing OTel instrumentation.
| Category | Before | After (TraceKit) | Notes |
|---|---|---|---|
| SDK | OpenTelemetry SDK + Tempo exporter | TraceKit SDK (native) | Native SDK adds live debugging, PII scrubbing |
| Authentication | Tempo API key / no auth (self-hosted) | TRACEKIT_API_KEY | API key required for managed ingestion |
| Service Identity | OTEL_SERVICE_NAME | TRACEKIT_SERVICE_NAME | Service name for trace grouping |
Migrate Key Dashboards
Identify your critical Grafana dashboards that use Tempo data and recreate them in TraceKit. TraceKit provides built-in service map, trace waterfall, and latency distribution views that replace common Tempo panels.
| Category | Before | After (TraceKit) | Notes |
|---|---|---|---|
| Dashboard | Grafana Tempo data source panels | TraceKit built-in trace views | Service map, waterfall, and latency views are built in |
| Dashboard | TraceQL queries in Grafana | TraceKit search and filters | Filter by service, status, duration, attributes |
| Dashboard | GF_SERVER_HTTP_PORT (default 3000) | TraceKit Dashboard URL | Cloud-hosted dashboard, no port management |
Verify Traces and Decommission Tempo
Confirm traces appear in TraceKit, then gradually decommission Tempo and its storage backend. Keep Grafana running for infrastructure dashboards (Prometheus/Mimir data sources) if needed.
| Category | Before | After (TraceKit) | Notes |
|---|---|---|---|
| Verification | Grafana > Explore > Tempo data source | TraceKit Dashboard > Traces | Verify trace search and waterfall |
| Verification | Grafana > Service Graph panel | TraceKit Service Map | Verify service dependency visualization |
| Decommission | Tempo compactor, distributor, querier pods | (not needed) | Remove Tempo infrastructure components |
Code Examples
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
exporter, _ := otlptracegrpc.New(ctx,
otlptracegrpc.WithEndpoint("tempo:4317"),
otlptracegrpc.WithInsecure(),
)
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
)
otel.SetTracerProvider(tp)
tracer := otel.Tracer("my-service")
ctx, span := tracer.Start(ctx, "process-order")
defer span.End()
}import "github.com/tracekit/go-sdk/tracekit"
func main() {
tracekit.Init("tk_your_api_key",
tracekit.WithService("my-service"),
tracekit.WithEnvironment("production"),
)
defer tracekit.Shutdown(context.Background())
ctx, span := tracekit.StartSpan(context.Background(), "process-order")
defer span.End()
}const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const exporter = new OTLPTraceExporter({
url: 'http://tempo:4317',
});
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
provider.register();
const tracer = provider.getTracer('my-service');
const span = tracer.startSpan('process-order');
// ... business logic
span.end();const tracekit = require('@tracekit/node-apm');
tracekit.init({
apiKey: 'tk_your_api_key',
service: 'my-service',
environment: 'production',
});
const span = tracekit.startSpan('process-order');
// ... business logic
span.end();from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
exporter = OTLPSpanExporter(endpoint="tempo:4317", insecure=True)
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("my-service")
with tracer.start_as_current_span("process-order"):
pass # business logicimport tracekit
tracekit.init(
api_key='tk_your_api_key',
service='my-service',
environment='production',
)
with tracekit.start_span('process-order') as span:
pass # business logic