CDS pluginCDS plugintypeInstalls into a CAP project and extends the runtime. CAP loads it through cds.requires or the plugin hook.See every one →What this type is →independently maintainedindependently maintainedoriginPublished by one person or a small company outside SAP. Says nothing about quality; the readings say that.See every one →

cap-ui-telemetry

UI5 frontend performance (FESR) and client error capture for CAP, written as cds.log records and forwarded to SAP Cloud Logging, rather than as OpenTelemetry spans.

cap-ui-telemetry captures the half of a request that happens before it reaches the server. It reads the SAP-Perf-FESRec headers UI5 piggybacks onto the next backend call after each completed interaction, and it adds a CDS REST service that accepts batches of client-side JavaScript errors, writing one structured cds.log record per interaction and one cds.log('ui-error') record per error. Both arrive as log records and not as OpenTelemetry spans, so they are read where the application's logs are read rather than in a trace view. It needs @sap/cds 8.0 or later on Node.js, a UI5 app that sends FESR, and SAP Cloud Logging bound to the CAP app for the custom fields to be indexed; the sampling fraction, the batch size and the message and stack lengths are configuration.

Facts

Latestv0.1.2ReleasedLast pushLicenceApache-2.0

Where it sits

Lives in
Provides
TelemetryCAPTelemetrycapabilitySeeing what a running service did — traces across handlers and database calls, metrics, and correlation that survives an async boundary.
Flavors
Node.jsfrom its runtime
Requires
@sap/cds≥ 8.0@sap/cdsartifactThe peer range, as published.
Optional
SAP Cloud LoggingSAP Cloud LoggingartifactThe records are written through cds.log, and the README lists a bound SAP Cloud Logging instance among the prerequisites so that the custom fields they carry are indexed.log sink

Who is behind it

Sören LeibachSören LeibachPersonMaintains this
In the atlas: maintains 6, contributes to 5, wrote 1
@sleibach
maintainer

Before choosing this

Conditions

LicenceSAP Developer License Agreement 3.2 CAP§ 1, 2, 3A cds-plugin is used with SAP CAP materials, or an artifact is explicitly identified as a CAP plugin or application.
  • § 1 License. Productive customer applications are limited to SAP BTP or another SAP-licensed platform, and mass extraction to a non-SAP product is restricted except where solely required for SAP interoperability.
  • § 2 Intellectual Property. The agreement retains SAP's rights in the covered materials and limits making APIs, tools or software available to third parties, while preserving ownership of customer applications subject to SAP's underlying rights.
  • § 3 Artificial Intelligence Training. The agreement prohibits use of the covered materials and customer applications for training artificial-intelligence models or systems.
SAP Developer License Agreement 3.2 CAP →

What it declares

Every artifact

Type
CDS plugin
Origin
Independently maintained
Runtime
Node.js

As a CDS plugin

Declared for
>=8.0
Distributed through
npm

For telemetry

Where it sends data
SAP Cloud Logging
Instrumented by
Automatically

Tasks this contributes to1Beta

See what the browser did before the request arrivedThe time a UI5 interaction took in the browser, and the JavaScript errors it hit, land in the backend beside the server's own telemetry, so a complaint about a slow or broken screen can be checked.Node.jsCovers, under conditionsclient capture in the server
What it does

It reads the SAP-Perf-FESRec headers UI5 piggybacks onto the next backend request after a completed interaction, and it adds a CDS REST service that accepts batches of client errors. Each interaction becomes one structured cds.log record and each error one cds.log('ui-error') record, so the client's side arrives as logs rather than as spans.

Conditions

@sap/cds 8.0 or later on Node.js; A UI5 app that sends the FESR headers; SAP Cloud Logging bound to the CAP app for the custom fields to be indexed

Remaining work

Switch FESR on in the UI5 app and point its error reporting at the service's path, then choose the sampling fraction and the batch and length limits. Because the records are logs, a trace view will not show them beside the server's spans.

All options on the Telemetry page →

Connections2

Install

npm add cap-ui-telemetry

Derived from the package name. No recipe recorded; the README has the configuration.

Where it sits in your app

Download
Your CAP applicationYour SAP BTP subaccountdocumentedmay needif The custom fields of theFESR and error records are tobe indexed, which is what the RE…cap-ui-telemetry, modulecap-ui-telemetrySAP Cloud Logging, service instanceSAP Cloud Logging
SAPnot SAP's, or the project's ownunder a condition

README

quoted from sleibach/cap-ui-telemetry under Apache-2.0, read
sleibach/cap-ui-telemetry/README.mdOn GitHub

cap-ui-telemetry

npm version

UI5 FESR (frontend performance) + client-error capture for SAP CAP (Node.js), forwarded to SAP Cloud Logging via cds.log.

Built for landscapes that run SAP Cloud Logging but have no Cloud ALM — official FESR targets CALM RUM, which has nowhere to land without it. This plugin uses Cloud Logging as a primary sink for both signals instead: UI5's piggybacked FESR headers, and client-side JS errors.

Features

  • FESR capture — reads the SAP-Perf-FESRec / SAP-Perf-FESRec-opt headers UI5 piggybacks onto the next backend request after each completed interaction (when sap-ui-fesr=true), parses them, and emits one structured cds.log('ui-fesr') record per interaction.
  • Client-error ingestion — a CDS REST service (POST <path>/errors) accepts batches of client errors and emits one cds.log('ui-error') record per entry.
  • Cloud-Logging-ready by construction — automatically extends cds.env.log.cls_custom_fields so every field (app name, step name, durations, error message, ...) lands as a flat, filterable/aggregatable field, not buried in free text.
  • No database — pure logging, nothing persisted by this plugin.
  • Zero backend wiring — install it and it's active; the only integration work is on the frontend (three copy-paste snippets, see below).
  • Optional user attribution on demand — cds.context.user.id gets attached to a record once you raise that logger's verbosity (DEBUG=ui-fesr / DEBUG=ui-error), config-gated and off by default in normal operation.

Requirements

  • @sap/cds >= 8.0 (Node.js)
  • A UI5 app (any version with sap/ui/performance/trace/FESR and sap/base/Log — i.e., any reasonably recent UI5)
  • SAP Cloud Logging bound to your CAP app for the custom fields to be indexed (works locally without it too — see Cloud Logging notes)

Install

npm add cap-ui-telemetry

That's it for the backend — no code changes required. CAP auto-discovers the plugin via cds-plugin.js.

Setup

Backend: nothing to do. On next cds watch / cds-serve you'll see:

[ui-telemetry] - active (FESR → cds.log('ui-fesr'), errors → POST /service/telemetry/errors → cds.log('ui-error'))

Frontend: copy three files from ui5-snippets/ into your app and wire them up — see INTEGRATION.md for numbered, verifiable steps (written so a coding agent can follow them unattended). npx cds add ui-telemetry automates the bootstrap flag + file-copy part of this (see INTEGRATION.md's Shortcut section). Summary:

  1. bootstrap-fesr.html — add data-sap-ui-fesr="true" to your bootstrap tag.
  2. fesr-enrichment.js — optional, enriches FESR records with "which app is open" for shells hosting multiple apps.
  3. ErrorReporter.js — captures sap/base/Log errors/warnings, uncaught exceptions, and unhandled promise rejections, and POSTs them (batched, CSRF-protected, rate-limited) to the backend. Pass appName (a static string, or a resolver function for shells) so ui-error records correlate with the same app identity as ui-fesr records.

Configuration reference

Set under a top-level cds['ui-telemetry'] key (package.json, .cdsrc.json, or any CAP profile) — not under cds.requires, since nothing ever cds.connect.to's this plugin.

KeyDefaultDescription
enabledtrueMaster switch. false disables everything (FESR middleware, errors service, custom-fields merge).
fesr.enabledtrueEnable/disable FESR header capture independently.
fesr.logger'ui-fesr'cds.log(...) category for FESR records.
fesr.sampling1.0Fraction of interactions to log (0–1). Useful to cut volume in production (e.g. 0.25).
errors.enabledtrueEnable/disable the client-error ingestion service independently.
errors.logger'ui-error'cds.log(...) category for client-error records.
errors.path'/service/telemetry'Service base path — action is served at <path>/errors. Change this if /service/* is already taken.
errors.maxBatchSize50Reject (400) a batch with more entries than this.
errors.maxMessageLength2048Truncate message beyond this length (never rejects).
errors.maxStackLength8192Truncate stackTrace beyond this length (never rejects).
customFields.extendtrueAuto-merge this plugin's fields into cds.env.log.cls_custom_fields. Set false to manage that list yourself.
logUserOn'debug'One of 'debug' | 'info' | 'warn' | 'error' | 'never' — attach cds.context.user.id to a record once that logger's configured verbosity reaches this threshold (e.g. DEBUG=ui-fesr). 'never' fully opts out. See Log record reference.

Example: sample 25% of FESR records and silence errors reporting in production only:

{
  "cds": {
    "ui-telemetry": {
      "fesr": { "sampling": 1.0 },
      "[production]": { "fesr": { "sampling": 0.25 } }
    }
  }
}

Example: relax auth on the errors endpoint for a fully anonymous UI (not recommended unless the route is otherwise protected):

using { TelemetryService } from 'cap-ui-telemetry/lib/telemetry-service';
annotate TelemetryService with @requires: 'any';

Log record reference

Every field listed here is registered in cds.env.log.cls_custom_fields (see Cloud Logging notes for why that matters). Numeric fields are emitted as actual numbers, not strings — required for percentile/avg aggregations.

ui-fesr records
FieldTypeSource (SAP-Perf-FESRec[-opt] position)
rootContextIdstringmandatory #0
fesrTransactionIdstringmandatory #1
clientNavigationTimenumber (ms)mandatory #2
clientRoundTripTimenumber (ms)mandatory #3
interactionDurationnumber (ms)mandatory #4 — UI5's Time To Interactive
completedRoundTripsnumbermandatory #5
passportActionstringmandatory #6 — <trigger>_<event>_<stepCounter>
networkTimenumber (ms)mandatory #7
requestTimenumber (ms)mandatory #8
clientOSstringmandatory #9
appNamestringoptional #0 (UI5's appNameShort)
stepNamestringoptional #1
clientModelstringoptional #3 — browser + version
bytesSent / bytesReceivednumberoptional #4/#5
clientProcessingTimenumber (ms)optional #8
compressedbooleanoptional #9
busyDurationnumber (ms)optional #14
interactionTypenumberoptional #15 — 0 n/a, 1 app start, 2 follow-up step, 3 unknown
clientDevicenumberoptional #16 — 0 unknown, 1 combi, 2 desktop, 3 phone, 4 tablet
legacyDurationnumber (ms)optional #17
interactionStartTimestringoptional #18 — digits-only ISO timestamp
appNameLongstringoptional #19
fesrDirtybooleanpresent only if any numeric field carried UI5's own "-1 = dirty" marker
userstringcds.context.user.id, only when logUserOn's threshold is met
ui-error records
FieldTypeNotes
errorLevel'error' | 'warn' | 'info'mapped from the client's level ('error'→error, 'warning'→warn, anything else→info)
errorMessagestringtruncated to errors.maxMessageLength
stackTracestringtruncated to errors.maxStackLength
errorSourcestring'ui5-log' | 'window-error' | 'unhandledrejection'
appNamestringshared name with ui-fesr records — correlate errors to performance by app
componentNamestringUI5 log component, when available
clientUrlstringpage URL at the time of the error
clientUserAgentstringnavigator.userAgent
clientTimestampstringclient-supplied ISO timestamp
userstringcds.context.user.id, only when logUserOn's threshold is met

Cloud Logging notes

cls_custom_fields is not an indexing switch — OpenSearch (Cloud Logging's backing store) dynamically indexes any top-level JSON field regardless. What it actually gates is whether an object argument passed to a log call (cds.log(id).info(msg, {...})) gets flattened into top-level fields at all, or falls through as an unstructured, util.inspect-style blob inside msg.

That gate is all-or-nothing per object: if even one key in the object isn't registered, the entire object degrades to text — not "some fields indexed, some not." That's why this plugin auto-registers every field it ever emits (customFields.extend, on by default) — and why, if you ever see plugin fields showing up inside msg instead of as their own JSON properties, the first thing to check is whether customFields.extend got turned off, or whether cls_custom_fields was replaced (not merged) by some other config.

Useful OpenSearch queries once records are flowing:

  • logger: "ui-fesr" AND appName: "your-app-id" — all performance records for one app
  • p95/avg of interactionDuration, faceted by appName + stepName — per-app, per-action performance dashboards
  • logger: "ui-error" AND errorLevel: "error" — error rate, faceted by appName
  • rootContextId: "<id>" or fesrTransactionId: "<id>" — exact-match trace correlation across records

Locally, without a Cloud Logging binding, the plain-text formatter is used and none of this matters — log lines are just readable text, no config needed.

Development and testing

npm install
npm run build   # tsc → dist/
npm test        # build + jest --runInBand (unit + integration, test/app workspace)
  • test/unit — pure logic: FESR header parsing, custom-fields merge mechanics, client-error sanitization, user-attachment gating, CSN model injection.
  • test/integration — boots the test/app sample CAP project (via @cap-js/cds-test) and exercises the FESR middleware and the errors service end to end over real HTTP.

License

Apache-2.0

Apache-2.0, read

History

Latest

v0.1.2

  1. v0.1.1

  2. v0.1.0

On npm
4downloads per week, npm
Weekly downloads for cap-ui-telemetry26 complete calendar weeks from 2026-04-20 to 2026-10-18; the latest total is 4.20 Apr – 26 Apr: 027 Apr – 3 May: 04 May – 10 May: 011 May – 17 May: 018 May – 24 May: 025 May – 31 May: 01 Jun – 7 Jun: 08 Jun – 14 Jun: 015 Jun – 21 Jun: 022 Jun – 28 Jun: 029 Jun – 5 Jul: 06 Jul – 12 Jul: 013 Jul – 19 Jul: 020 Jul – 26 Jul: 42327 Jul – 2 Aug: 1003 Aug – 9 Aug: 5910 Aug – 16 Aug: 6017 Aug – 23 Aug: 6624 Aug – 30 Aug: 2731 Aug – 6 Sept: 77 Sept – 13 Sept: 514 Sept – 20 Sept: 2221 Sept – 27 Sept: 1428 Sept – 4 Oct: 155 Oct – 11 Oct: 1312 Oct – 18 Oct: 4
Telemetry
  1. abap-metrics-providerExposes ABAP stack metrics to a monitoring toolfrom ABAP
  2. admin-cockpitUsage, error and response-time monitor for abap2UI5from ABAP
  3. SAP Cloud LoggingOpenSearch-based store for logs, metrics and tracesfrom BTP/BAIP
  4. Agent Activation for Dynatrace Service for SAP BTPInjects the Dynatrace agent into Java applications on SAP BTPfrom BTP/BAIP
  5. SAP Monitoring Service for SAP BTPMetrics, availability checks and alerts for apps in Neo regionsfrom BTP/BAIP
  6. com.sap.cds:cds-services-bomMaven bill of materials pinning CAP Java module versionsfrom CAP
  7. @cap-js-community/business-metricsBusiness-level metrics from CDS annotations via @cap-js/telemetryfrom CAP
  8. @cap-js/telemetryOpenTelemetry instrumentation for CAP servicesfrom CAP
  9. cds-cachingCAP caching plugin for query results and remote service responsesfrom CAP
  10. cap-mcp-guardPolicy enforcement and field masking for MCP-enabled CAP appsfrom CAP
  11. abap-opentelemetryOTLP serialisation of traces, metrics and logs in ABAPfrom ABAP
  12. abap-prometheusPrometheus client for ABAP, installed with abapGitfrom ABAP
  13. @sanjay-sde/cap-js-log-controlCAP plugin controlling CDS logger and OpenTelemetry log verbosityfrom CAP
  14. @sap/e2e-traceSAP Passport handling for Node.js componentsfrom BTP/BAIP
  15. @sap-ux/telemetryLibrary for sending usage telemetry datafrom CAP
  16. @saptools/cf-metricsRead-only query tool for metrics in SAP Cloud Loggingfrom BTP/BAIP
  17. @saptools/cf-otelRead-only query tool for OpenTelemetry spans in SAP Cloud Loggingfrom BTP/BAIP
  18. opentelemetry-cdsOpenTelemetry support for the CDS Node.js runtimefrom CAP

Details

Sources4
GitHub APIdiscovered here, sleibachchecked
npm registry, cap-ui-telemetryversion, releases, installschecked
github.com/git+https://github.com/sleibach/cap-ui-telemetry.gittree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
runtimesnode
declared for>=8.0
latestv0.1.2
first release
releases and cadence3, ~0d median
discovered viaGitHub API · sleibach
first seen in the atlas
ecosystem and domaincap, operations-and-runtime
History in the atlas2
  1. what it does for telemetry, its two stated properties, and the Cloud Logging edge
  2. First seen.
For your agent
Ref
artifact:sleibach-cap-ui-telemetry
JSON
/artifacts/sleibach-cap-ui-telemetry.json
MCP
Connecting an agent