Instrument a service with OpenTelemetry
Add the OpenTelemetry SDK to a service, capture traces automatically, write one custom span, and export it all over OTLP — then point that same stream at Sluicio. Shown in Java, .NET and JavaScript.
Most modern services can emit production-grade telemetry with little or no code change — the OpenTelemetry SDK (or agent) wraps your HTTP server, database driver, and message client and records a span for every operation. This guide takes you from an un-instrumented service to a live trace stream in four steps, then adds a single custom span where the automatic ones aren’t enough.
Every code example below is shown in Java, .NET and JavaScript — pick your language with the tabs and the whole page follows.
1 · Install the SDK
Section titled “1 · Install the SDK”Pull in the OpenTelemetry SDK plus auto-instrumentation for your framework.
The Java agent auto-instruments your app with no code changes — just download the jar.
curl -L -o opentelemetry-javaagent.jar \ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jardotnet add package OpenTelemetry.Extensions.Hostingdotnet add package OpenTelemetry.Instrumentation.AspNetCoredotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocolnpm install @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/exporter-trace-otlp-http2 · Wire it up
Section titled “2 · Wire it up”Initialise tracing before your application logic runs.
No code — attach the agent at startup and name your service. The agent patches libraries as they load.
java -javaagent:./opentelemetry-javaagent.jar \ -Dotel.service.name=orders-api \ -jar app.jarRegister OpenTelemetry in Program.cs. AddSource("orders") is what lets the custom span in step 4 be picked up.
using OpenTelemetry.Resources;using OpenTelemetry.Trace;
builder.Services.AddOpenTelemetry() .ConfigureResource(r => r.AddService("orders-api")) .WithTracing(tracing => tracing .AddAspNetCoreInstrumentation() .AddSource("orders") .AddOtlpExporter());Create an instrumentation.js that starts the SDK, and load it with --require so it runs first: node --require ./instrumentation.js server.js.
const { NodeSDK } = require('@opentelemetry/sdk-node');const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const sdk = new NodeSDK({ serviceName: 'orders-api', traceExporter: new OTLPTraceExporter(), instrumentations: [getNodeAutoInstrumentations()],});
sdk.start();3 · Point the export at Sluicio
Section titled “3 · Point the export at Sluicio”The OTLP exporter reads its target from standard environment variables — the same names in every language, so nothing here is language-specific. Set the endpoint and your workspace key:
OTEL_EXPORTER_OTLP_ENDPOINT=https://your-instance-name.sluicio.comOTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer <your-ingest-key>4 · Add a custom span
Section titled “4 · Add a custom span”Auto-instrumentation covers the edges of your service. To time a specific piece of business logic — say, validating an order — wrap it in a span of your own. The setAttribute calls become searchable fields in Sluicio.
import io.opentelemetry.api.GlobalOpenTelemetry;import io.opentelemetry.api.trace.Span;import io.opentelemetry.api.trace.Tracer;
Tracer tracer = GlobalOpenTelemetry.getTracer("orders");
void validateOrder(Order order) { Span span = tracer.spanBuilder("order.validate").startSpan(); try (var scope = span.makeCurrent()) { span.setAttribute("order.id", order.getId()); span.setAttribute("order.items", order.getLines().size()); runRules(order); } finally { span.end(); // always close the span }}using System.Diagnostics;
// Registered via .AddSource("orders") in Program.csstatic readonly ActivitySource Source = new("orders");
async Task ValidateOrder(Order order){ using var activity = Source.StartActivity("order.validate"); activity?.SetTag("order.id", order.Id); activity?.SetTag("order.items", order.Lines.Count); await RunRules(order); // activity disposes (ends) automatically}const { trace } = require('@opentelemetry/api');const tracer = trace.getTracer('orders');
async function validateOrder(order) { return tracer.startActiveSpan('order.validate', async (span) => { span.setAttribute('order.id', order.id); span.setAttribute('order.items', order.lines.length); try { await runRules(order); } finally { span.end(); // always close the span } });}Verify it in Sluicio
Section titled “Verify it in Sluicio”Within a few seconds of restarting, your service appears in the overview and traces start flowing. Open one and you’ll see the auto-captured HTTP and database spans alongside your order.validate span, nested exactly where it ran.
Where to go next
Section titled “Where to go next”- Track RabbitMQ queue depth and consumer lag — pair service traces with broker metrics.
- Monitor a file-drop integration (hot folder) — instrument a file-based flow.
- Monitor ActiveMQ Artemis queue depth — backlog and dead-letter monitoring.