On this page
Getting Started with OpenTelemetry in Deno
OpenTelemetry provides powerful observability tools for your applications. WithDeno's built-in OpenTelemetry support, you can easily instrument your code tocollect metrics, traces, and logs.
This tutorial will walk you through setting up a simple Deno application withOpenTelemetry instrumentation.
PrerequisitesJump to heading
- Deno 2.3 or later
Step 1: Create a Simple HTTP ServerJump to heading
Let's start by creating a basic HTTP server that simulates a small webapplication:
import{ metrics, trace}from"npm:@opentelemetry/api@1";// Create a tracer and meter for our applicationconst tracer= trace.getTracer("my-server","1.0.0");const meter= metrics.getMeter("my-server","1.0.0");// Create some metricsconst requestCounter= meter.createCounter("http_requests_total",{ description:"Total number of HTTP requests",});const requestDuration= meter.createHistogram("http_request_duration_ms",{ description:"HTTP request duration in milliseconds", unit:"ms",});// Start the serverDeno.serve({ port:8000},(req)=>{// Record the start time for measuring request durationconst startTime= performance.now();// Create a span for this requestreturn tracer.startActiveSpan("handle_request",async(span)=>{try{// Extract the path from the URLconst url=newURL(req.url);const path= url.pathname;// Add attributes to the span span.setAttribute("http.route", path); span.setAttribute("http.method", req.method); span.updateName(`${req.method}${path}`);// Add an event to the span span.addEvent("request_started",{ timestamp: startTime, request_path: path,});// Simulate some processing timeconst waitTime= Math.random()*100;awaitnewPromise((resolve)=>setTimeout(resolve, waitTime));// Add another event to the span span.addEvent("processing_completed");// Create the responseconst response=newResponse(`Hello from${path}!`,{ headers:{"Content-Type":"text/plain"},});// Record metrics requestCounter.add(1,{ method: req.method, path, status:200,});const duration= performance.now()- startTime; requestDuration.record(duration,{ method: req.method, path,}); span.setAttribute("request.duration_ms", duration);return response;}catch(error){// Record error in spanif(errorinstanceofError){ span.recordException(error); span.setStatus({ code: trace.SpanStatusCode.ERROR, message: error.message,});}returnnewResponse("Internal Server Error",{ status:500});}finally{// Always end the span span.end();}});});
This server:
- Creates a tracer and meter for our application
- Sets up metrics to count requests and measure their duration
- Creates a span for each request with attributes and events
- Simulates some processing time
- Records metrics for each request
Step 2: Run the Server with OpenTelemetry EnabledJump to heading
To run the server with OpenTelemetry, use these flags:
OTEL_DENO=trueOTEL_SERVICE_NAME=my-server deno run --allow-net server.ts
Step 3: Create a Test ClientJump to heading
Let's create a simple client to send requests to our server:
// Send 10 requests to different pathsfor(let i=0; i<10; i++){const path=["","about","users","products","contact"][i%5];const url=`http://localhost:8000/${path}`;console.log(`Sending request to${url}`);try{const response=awaitfetch(url);const text=await response.text();console.log(`Response from${url}:${text}`);}catch(error){console.error(`Error fetching${url}:`, error);}}
Step 4: Run the ClientJump to heading
In a separate terminal, run the client:
deno run --allow-net client.ts
Step 5: View the Telemetry DataJump to heading
By default, Deno exports telemetry data tohttp://localhost:4318
using theOTLP protocol. You'll need an OpenTelemetry collector to receive and visualizethis data.
Setting up a Local CollectorJump to heading
The quickest way to get started is with a local LGTM stack (Loki, Grafana,Tempo, Mimir) in Docker:
docker run--name lgtm-p3000:3000-p4317:4317-p4318:4318--rm-ti\-v"$PWD"/lgtm/grafana:/data/grafana\-v"$PWD"/lgtm/prometheus:/data/prometheus\-v"$PWD"/lgtm/loki:/data/loki\-eGF_PATHS_DATA=/data/grafana\ docker.io/grafana/otel-lgtm:0.8.1
Then access Grafana athttp://localhost:3000 (username: admin, password: admin).
In Grafana, you can:
- ViewTraces in Tempo to see the individual request spans
- ViewMetrics in Mimir/Prometheus to see request counts and durations
- ViewLogs in Loki to see any logs from your application
Understanding What You're SeeingJump to heading
TracesJump to heading
In the Traces view, you'll see spans for:
- Each HTTP request processed by your server
- Each fetch request made by your client
- The relationships between these spans
Click on any span to see its details, including:
- Duration
- Attributes (http.route, http.method, etc.)
- Events (request_started, processing_completed)
MetricsJump to heading
In the Metrics view, you can query for:
http_requests_total
- The counter tracking the number of HTTP requestshttp_request_duration_ms
- The histogram of request durations
You can also see built-in Deno metrics like:
http.server.request.duration
http.server.active_requests
LogsJump to heading
In the Logs view, you'll see all console logs from your application with correcttrace context.
TroubleshootingJump to heading
If you're not seeing data in your collector:
- Check that you've set
OTEL_DENO=true
- Verify the collector is running and accessible at the default endpoint
- Check if you need to set
OTEL_EXPORTER_OTLP_ENDPOINT
to a different URL - Look for errors in your Deno console output
Remember that OpenTelemetry support in Deno is still marked as unstable and maychange in future versions.
🦕 This tutorial provides a simple starting point for users who want toexperiment with OpenTelemetry in Deno without diving into more complex conceptsimmediately.
This basic example can be extended in many ways:
- Add more custom metrics for business logic
- Create additional spans for important operations
- Use baggage to pass context attributes between services
- Set up alerts based on metrics thresholds
For more advanced usage, see ourDistributed Tracing with Context Propagationtutorial.