← Back to Home
🛠️

Instrumenting a Service & Sending Traces to Zipkin

From a running Zipkin to real spans flowing in from your app.

10 min read📚DevOps Fundamentals

Theory is done — let’s produce real traces. You’ll start Zipkin locally, then instrument an application so it records spans and reports them. We’ll use OpenTelemetry, today’s vendor-neutral standard for instrumentation, exporting to Zipkin.


🎯 Learning Objectives


Step 1 — Run Zipkin

The fastest way to get Zipkin is its official Docker image (uses in-memory storage — perfect for learning):

bash
docker run -d -p 9411:9411 openzipkin/zipkin
bash — 80×24
student@devops:~$curl -s localhost:9411/health

The UI is now at http://localhost:9411. It’s empty because nothing has sent traces yet — that’s our next job.


Automatic vs. Manual Instrumentation

There are two ways to get spans out of an app:

Approach What it means
Automatic An agent/library auto-instruments common frameworks (HTTP servers, clients, DB drivers) — little to no code change
Manual You create spans in your own code for business operations you care about

Real systems use both: automatic for the plumbing, manual for the important custom operations.


Step 2 — Auto-Instrument with OpenTelemetry

For a Node.js service, OpenTelemetry can auto-instrument with no app code changes and export to Zipkin. Point it at your Zipkin collector via environment variables:

bash
npm install @opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-zipkin
javascript
// tracing.js — loaded before your app
const { NodeSDK } = require("@opentelemetry/sdk-node");
const { ZipkinExporter } = require("@opentelemetry/exporter-zipkin");
const { getNodeAutoInstrumentations } =
require("@opentelemetry/auto-instrumentations-node");

const sdk = new NodeSDK({
serviceName: "orders-service",
traceExporter: new ZipkinExporter({
  url: "http://localhost:9411/api/v2/spans",
}),
instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

Run your app with this loaded first, and every incoming HTTP request and outgoing call automatically becomes a span in Zipkin:

bash
node -r ./tracing.js server.js

Step 3 — Add a Custom Span

For business logic you care about, create a manual span and tag it with useful metadata:

javascript
const { trace } = require("@opentelemetry/api");
const tracer = trace.getTracer("orders-service");

async function chargeCustomer(orderId, amount) {
const span = tracer.startSpan("charge-customer");
span.setAttribute("order.id", orderId);
span.setAttribute("payment.amount", amount);
try {
  await paymentGateway.charge(amount);
} catch (err) {
  span.recordException(err);
  span.setStatus({ code: 2 });   // ERROR
  throw err;
} finally {
  span.end();                    // always end the span
}
}

Now Zipkin shows a charge-customer span with your order.id and payment.amount tags — searchable and visible in the waterfall.

⚠ Always end your spans

A span that never calls end() never gets reported (and leaks memory). Wrap the work in try/finally and end the span in finally so it’s recorded even on error.

💡 Instrument once, export anywhere

Because we used OpenTelemetry, switching from Zipkin to Jaeger (or a hosted backend) later is just changing the exporter — your instrumentation code stays the same. That vendor-neutrality is why OpenTelemetry has become the standard.


🧪 Hands-on Lab

📝

Trace a Slow Dependency

You suspect an external inventory-check call is slow. Describe how you’d wrap it in a custom span (with a tag for the item ID) so its duration shows up in Zipkin.


🧠 Knowledge Check

Knowledge Check

What is the advantage of automatic instrumentation?

Knowledge Check

Why use OpenTelemetry to export to Zipkin rather than a Zipkin-specific library?


💼 Interview Preparation

Interview Q&A

How would you add tracing to an existing microservice with minimal risk?


Summary

You ran Zipkin, instrumented an app with OpenTelemetry, exported spans, and added a custom span with tags. Traces are now flowing. In the final lesson we use them: analyzing latency and debugging real problems in the Zipkin UI.

Up Next

Analysing Latency & Debugging with Zipkin

You've mastered this lesson. Continue your journey to becoming a DevOps Engineer.

Start Next Lesson