75 · Distributed Tracing

Enable OpenTelemetry tracing in CAP, propagate trace context, export to SAP Cloud ALM, and read span trees.

Episode 75 — Distributed Tracing

What you'll learn

Why this matters

When a user reports "the purchase order page is slow", structured logs tell you that something took 3 seconds but not which call in the chain caused it. Distributed tracing generates a trace — a tree of spans showing every service call, DB query, and downstream request with its duration. You can see immediately whether the slowdown is in CAP handler code, an HANA query, or an S/4HANA OData call.

Key concepts

Term Meaning
Trace A complete request flow across all services
Span One unit of work (a function call, a DB query, an HTTP request)
Trace ID Unique ID shared by all spans in one trace
Span ID Unique ID for one span
Parent Span The span that initiated the current work unit
W3C Trace Context Standard HTTP headers: traceparent, tracestate

OpenTelemetry in CAP

CAP supports OpenTelemetry (OTel) tracing through @sap/cds-tracing:

npm install @sap/cds-tracing @opentelemetry/sdk-node
// srv/server.js — enable before anything else
const tracing = require('@sap/cds-tracing');
tracing.enable();   // auto-instruments DB calls, service calls, HTTP handlers

CAP will create spans automatically for:
- Every incoming OData request (root span)
- Every this.on() / this.before() / this.after() handler
- Every CQL DB operation
- Every cds.connect.to() remote service call

Propagating trace context

When CAP calls a remote service (S/4HANA, Event Mesh), pass the W3C traceparent header automatically:

// CAP does this for you when using cds.connect.to()
// For manual fetch calls, propagate explicitly:
const { context } = require('@opentelemetry/api');
const { propagation } = require('@opentelemetry/api');

async function callDownstream(url, req) {
  const headers = {};
  propagation.inject(context.active(), headers);  // injects traceparent

  return fetch(url, { headers });
}

Sending traces to SAP Cloud ALM

Configure the OTel exporter to send to Cloud ALM:

const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { NodeSDK }           = require('@opentelemetry/sdk-node');

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
    headers: {
      Authorization: `Bearer ${process.env.OTEL_EXPORTER_TOKEN}`
    }
  })
});

sdk.start();

Set OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_TOKEN from the Cloud ALM service key in your CF manifest:

env:
  OTEL_EXPORTER_OTLP_ENDPOINT: https://cloudalm.cfapps.eu10.hana.ondemand.com/api/v1/traces
  OTEL_EXPORTER_TOKEN: ((cloud-alm-token))

Reading traces in Cloud ALM

  1. Navigate to SAP Cloud ALM → Health Monitoring → Distributed Tracing
  2. Search by trace ID (from a specific user complaint) or filter by:
  3. Service name
  4. Duration > 2 s (slow requests)
  5. Status = ERROR (failed requests)
  6. Click a trace to see the span tree
  7. Each span shows: start time, duration, attributes (user, tenant, SQL query)

Correlating traces with logs

Include the trace ID in your structured log entries so you can jump from a log line to its trace:

const { trace } = require('@opentelemetry/api');

logger.info('Starting approval workflow', {
  traceId:  trace.getActiveSpan()?.spanContext().traceId,
  userId:   req.user.id,
  poAmount: req.data.totalAmount
});

In Kibana, click the traceId value → opens the trace in Cloud ALM (if linked).

Common mistakes

Mistake Fix
Enabling tracing after other middleware Enable @sap/cds-tracing before all other requires
Not propagating traceparent in manual fetch calls Use the OTel propagation API
Sampling rate at 100% in production Set OTEL_TRACES_SAMPLER_ARG=0.1 (10%) to control volume
No trace ID in log entries Correlate logs and traces via the trace ID field
Ignoring span attributes Span attributes (user, SQL, entity) are what make traces useful

Checkpoint ✓

You can enable OpenTelemetry tracing in CAP with @sap/cds-tracing, propagate trace context in downstream calls, export traces to SAP Cloud ALM, read the span tree to find the slow step, and correlate traces with structured log entries via trace ID.

Sign in for progress tracking & Q&A →