| name | observability-telemetry |
| description | Use when adding logging, tracing, metrics, or observability to a SAP CAP application: cds.log, @cap-js/telemetry, OpenTelemetry, SAP Cloud Logging, Dynatrace, W3C trace context, outbox metrics, or debugging CAP applications in production.
|
| metadata | {"version":"1.1.0","keywords":["cds.log","@cap-js/telemetry","OpenTelemetry","Cloud Logging","tracing","metrics","observability","logging","monitoring"],"related":{"btp-deployment":"configure telemetry in BTP deployment","cap-plugins":"@cap-js/telemetry plugin setup"}} |
Observability & Telemetry — CAP Best Practices
Primary reference: https://cap.cloud.sap/docs/plugins/#telemetry
Cloud Logging: https://cap.cloud.sap/docs/guides/deployment/to-cf
Structured logging with cds.log
Always use cds.log — never raw console.log in production code:
const log = cds.log('orders')
log.error('Failed to submit order', { orderID, error: err.message })
log.warn('Stock is low for product', { productID, remaining: stock })
log.info('Order submitted successfully', { orderID, amount })
log.debug('Entering validateOrder', { data: req.data })
if (log.debug) log.debug('Full request data:', req.data)
Configure log level per module:
{
"cds": {
"log": {
"levels": {
"orders": "debug",
"remote-services": "warn",
"*": "info"
}
}
}
}
@cap-js/telemetry plugin (OpenTelemetry)
Version 2 (June 2026+): @cap-js/telemetry v2 supports OpenTelemetry SDK 2.0 and adds @opentelemetry/instrumentation-undici for tracing outbound HTTP calls via the native Fetch API. All @opentelemetry/* dependencies are bumped to 2.x. Upgrade with npm install @cap-js/telemetry@latest.
npm install @cap-js/telemetry
Auto-activated — instruments CAP service calls, DB queries, and HTTP requests automatically.
Export to SAP Cloud Logging
{
"cds": {
"requires": {
"telemetry": {
"kind": "to-cloud-logging"
}
}
}
}
mta.yaml:
modules:
- name: my-cap-app-srv
requires:
- name: my-cap-app-logging
resources:
- name: my-cap-app-logging
type: org.cloudfoundry.managed-service
parameters:
service: cloud-logging
service-plan: standard
Export to Dynatrace
{
"cds": {
"requires": {
"telemetry": {
"kind": "to-dynatrace"
}
}
}
}
Local development (console output)
{
"cds": {
"requires": {
"telemetry": {
"[development]": {
"kind": "to-console"
}
}
}
}
}
W3C Trace Context propagation
CAP automatically propagates W3C traceparent/tracestate headers in:
- Incoming HTTP requests
- Outgoing remote service calls
- Outbox message processing (since CAP Nov 2025)
This means your end-to-end trace ID is consistent across:
Client → CAP Service → Remote S/4 Call → Outbox → Async Handler
No manual implementation needed — just ensure @cap-js/telemetry is installed.
Outbox metrics (CAP Nov 2025+)
Monitor outbox health with built-in OpenTelemetry metrics:
Metrics exposed:
cds.outbox.messages.pending — messages waiting to be delivered
cds.outbox.messages.failed — failed deliveries
cds.outbox.processing.duration — processing time histogram
Import the Cloud Logging dashboard:
- Go to Stack Management → Saved Objects → Import
- Import
cap-java-outbox-metrics.ndjson (from CAP docs)
- Open
CAP Java Outbox Metrics dashboard
Custom spans for business operations
const { trace } = require('@opentelemetry/api')
const tracer = trace.getTracer('orders-service')
async function processOrder(orderID) {
return tracer.startActiveSpan('processOrder', async (span) => {
try {
span.setAttribute('order.id', orderID)
span.setAttribute('order.tenant', cds.context?.tenant)
const result = await doProcessing(orderID)
span.setStatus({ code: 0 })
return result
} catch (err) {
span.setStatus({ code: 2, message: err.message })
span.recordException(err)
throw err
} finally {
span.end()
}
})
}
Health check endpoint
CAP exposes a /health endpoint out of the box:
GET /health → 200 OK {"status":"UP"}
Use it for Kubernetes liveness/readiness probes:
livenessProbe:
httpGet:
path: /health
port: 4004
initialDelaySeconds: 30
periodSeconds: 10
Debugging in production (safely)
cf set-env my-cap-app CDS_LOG_LEVELS '{"remote-services":"debug","db":"debug"}'
cf restage my-cap-app
CDS_LOG_LEVELS='{"orders":"debug"}' npm start
Common mistakes to avoid
- ❌ Using
console.log in production — not structured, not correlated with traces
- ❌ Logging sensitive data (PII, credentials) even at debug level
- ❌ Not scoping loggers (
cds.log('module-name')) — all logs appear as generic CAP logs
- ❌ Skipping
@cap-js/telemetry — you lose automatic DB query tracing and service call timing
- ❌ Not propagating
traceparent to remote service calls — trace breaks end-to-end
- ❌ Missing
cloud-logging service binding in mta.yaml — telemetry silently drops in production