I’ve been diving deep into OpenTelemetry lately and wanted to share what I’ve learned about the three pillars of observability. If you’re anything like me, you’ve probably been confused about when to use traces vs metrics vs logs. In this post, I’ll break down each of these observability signals and share some real-world examples. I’ll also cover how these three pieces fit together in OpenTelemetry’s framework, and share some practical tips. Whether you’re just getting started with observability or looking to level up your debugging game, this guide should help clear the fog. OpenTelemetry, the CNCF-backed standard for observability, helps developers collect traces , metrics , and logs in a unified way.
But what’s the difference between these three pillars? And how can you actually implement them in your Go or Node.js apps?
Let’s break it down.
Traces: Follow the Request’s Journey
Traces track the full lifecycle of a request across services.
Imagine a user hits your frontend, which calls your API, which queries a database. A trace captures that entire flow as a tree of spans , each representing an operation.
What Traces Answer
- Where is the latency coming from?
- Which service is failing?
- How are requests flowing through the system?
Go Example
tr := otel.Tracer("my-service")
ctx, span := tr.Start(ctx, "HandleRequest")
defer span.End()
// Do some work...
Node.js Example
const tracer = opentelemetry.trace.getTracer('my-service');
const span = tracer.startSpan('handleRequest');
// ...work...
span.end();
Metrics: Know the System Health
Metrics are numerical values measured over time. Think counters, gauges, histograms.
They help you understand system-wide health and performance trends.
What Metrics Answer
- What’s the current CPU/memory usage?
- How many requests/errors per second?
- Is latency getting worse over time?
Go Example
meter := global.Meter("my-service")
counter, _ := meter.Int64Counter("http_requests_total")
counter.Add(ctx, 1, attribute.String("route", "/login"))
Node.js Example (with Prometheus)
const client = require('prom-client');
const httpCounter = new client.Counter({
name: 'http_requests_total',
help: 'Total HTTP requests',
});
httpCounter.inc();
Logs: Details When You Need Them
Logs are textual messages generated during code execution. They’re often rich with context and great for debugging.
With OpenTelemetry, logs can be correlated with traces using trace_id
and span_id
.
What Logs Answer
- What exactly happened here?
- What was the value of
X
during that error? - Stack traces and errors with context
Go Example
log.Printf("User %s failed login, traceID: %s", userID, trace.SpanContextFromContext(ctx).TraceID())
Node.js Example
console.log(`User login failed. traceId: ${span.spanContext().traceId}`);
How They Work Together
Imagine a slow API request:
-
Metrics show API latency has spiked.
-
A trace shows which service or DB call is slowing things down.
-
Logs show the exact error message or bad config that caused the issue.
Together, these three tools give you complete visibility.
Minimal Go Setup (Traces Only)
func initTracer() {
exporter, _ := otlptracehttp.New(context.Background())
tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
otel.SetTracerProvider(tp)
}
Minimal Node.js Setup (Traces Only)
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new BatchSpanProcessor(new OTLPTraceExporter()));
provider.register();
Summary
Feature | Traces | Metrics | Logs |
---|---|---|---|
Purpose | Request flow analysis | System performance overview | Debugging and forensics |
Format | Spans (structured) | Numbers over time | Text (structured/unstructured) |
Best For | Debugging latency, dependencies | Monitoring health & throughput | Investigating specific issues |
Final Thoughts
Start with tracing — it’s the easiest way to understand what your system is actually doing. Add metrics for system health and logs for depth. With OpenTelemetry, you can collect all three in a consistent, vendor-neutral way.
Top comments (0)