Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ jobs:
fail-fast: false
matrix:
node-version: [24.x, 22.x]
# cds-version: [10, 9]
cds-version: [9]
cds-version: [10, 9]
steps:
- uses: actions/checkout@v7.0.0
- name: Use Node.js ${{ matrix.node-version }}
Expand All @@ -36,7 +35,7 @@ jobs:
node-version: ${{ matrix.node-version }}
- run: npm i -g @sap/cds-dk@${{ matrix.cds-version }}
- run: npm i
#- run: if [ ${{ matrix.cds-version }} -eq 9 ]; then npm i -f @sap/cds@9 @cap-js/sqlite@2 @sap/cds-mtxs@3; fi
- run: if [ ${{ matrix.cds-version }} -eq 9 ]; then npm i -f @sap/cds@9 @cap-js/sqlite@2 @sap/cds-mtxs@3; fi
- run: if [ ${{ matrix.cds-version }} -eq 9 ]; then npm explore better-sqlite3 -- npm run install; fi
- run: cds v
- run: npm run test
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
run: |
npm i -g @sap/cds-dk
npm i
npm explore better-sqlite3 -- npm run install
npm run lint
npm run test
- name: get version
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
The format is based on [Keep a Changelog](http://keepachangelog.com/).

## Version 2.0.1 - 2026-07-03

### Fixed

- Readability of span names for DB and Cloud SDK traces
- Peer dependency allows `@sap/cds^10`

## Version 2.0.0 - 2026-06-29

### Added
Expand Down
2 changes: 1 addition & 1 deletion lib/metrics/db-pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ module.exports = () => {
_initialized.add(srv.name)

let pools
srv.after('BEGIN', async function (_, req) {
srv.after('BEGIN', async function () {
const pool = this.dbc._pool || this.pool
if (!pool) return

Expand Down
7 changes: 1 addition & 6 deletions lib/metrics/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ const LOG = cds.log('telemetry')
const { metrics } = require('@opentelemetry/api')
const { getStringFromEnv } = require('@opentelemetry/core')
const { resourceFromAttributes } = require('@opentelemetry/resources')
const {
AggregationTemporality,
AggregationType,
MeterProvider,
PeriodicExportingMetricReader
} = require('@opentelemetry/sdk-metrics')
const { AggregationTemporality, MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics')

const { getDynatraceMetadata, getCredsForDTAsUPS, getCredsForCLSAsUPS, augmentCLCreds, _require } = require('../utils')

Expand Down
3 changes: 0 additions & 3 deletions lib/metrics/queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,6 @@ module.exports = () => {
// Skip setup if queue telemetry is disabled
if (!cds.env.requires.telemetry.metrics?._queue) return

// Skip setup if the cds version is lower than 9
if (cds.version.split('.')[0] < 9) return
Comment thread
PDT42 marked this conversation as resolved.

/** @type {Record<[key: string], Record<[key: string], object>>} */
const statistics = {}
const registeredServices = new Set()
Expand Down
20 changes: 14 additions & 6 deletions lib/tracing/cloud_sdk.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
const { SpanKind } = require('@opentelemetry/api')

const cds = require('@sap/cds')
const trace = require('./trace')
const wrap = require('./wrap')

const { _append_url_path } = cds.env.requires.telemetry.tracing
const APPEND_URL_PATH = _append_url_path && _append_url_path !== 'false'

function _cloudSdkSpanName(destination, requestConfig) {
Comment thread
PDT42 marked this conversation as resolved.
const method = requestConfig?.method || 'GET'
if (!APPEND_URL_PATH) return method
const url = destination.url || requestConfig?.url || ''
const path = url.replace(/^https?:\/\/[^/]+/, '').split('?')[0]
return `${method}${path ? ' ' + path : ''}`
}

// REVISIT: unverified!
module.exports = () => {
try {
Expand All @@ -16,9 +28,7 @@ module.exports = () => {
cloudSDK.executeHttpRequest = wrap(_execute, {
wrapper: function executeHttpRequest(destination, requestConfig) {
return trace(
`${destination?.name ? destination?.name + ' ' : ''}${requestConfig?.method || 'GET'} ${
destination.url || requestConfig?.url
}`,
_cloudSdkSpanName(destination, requestConfig),
_execute,
this,
arguments,
Expand All @@ -29,9 +39,7 @@ module.exports = () => {
cloudSDK.executeHttpRequestWithOrigin = wrap(_executeWithOrigin, {
wrapper: function executeHttpRequestWithOrigin(destination, requestConfig) {
return trace(
`${destination?.name ? destination?.name + ' ' : ''}${requestConfig?.method || 'GET'} ${
destination.url || requestConfig?.url
}`,
_cloudSdkSpanName(destination, requestConfig),
_executeWithOrigin,
this,
arguments,
Expand Down
1 change: 0 additions & 1 deletion lib/tracing/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const cds = require('@sap/cds')
const LOG = cds.log('telemetry')

const { trace } = require('@opentelemetry/api')
const { getStringFromEnv } = require('@opentelemetry/core')
const { resourceFromAttributes } = require('@opentelemetry/resources')
const { BatchSpanProcessor, SimpleSpanProcessor, SamplingDecision } = require('@opentelemetry/sdk-trace-base')
Expand Down
22 changes: 16 additions & 6 deletions lib/tracing/trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ const MASK_HEADERS = (cds.env.log.mask_headers || ['/authorization/i', '/cookie/

const CRUD = { CREATE: 1, READ: 1, UPDATE: 1, DELETE: 1 }

const { hrtime, adjust_root_name, _truncate_span_name } = cds.env.requires.telemetry.tracing
const { hrtime, _append_url_path, _truncate_span_name } = cds.env.requires.telemetry.tracing
const HRTIME = hrtime && hrtime !== 'false'
const ADJUST_ROOT_NAME = adjust_root_name && adjust_root_name !== 'false'
const APPEND_URL_PATH = _append_url_path && _append_url_path !== 'false'

const $hrnow = Symbol('@cap-js/telemetry:hrnow')
const $adjusted = Symbol('@cap-js/telemetry:adjusted')
Expand Down Expand Up @@ -283,7 +283,7 @@ function trace(req, fn, that, args, opts = {}) {
_setAttributes(parent, _getRequestAttributes())
const ctx = cds.context
if (ctx?.http?.req?.[$hrnow]) parent.startTime = ctx.http.req[$hrnow]
if (ADJUST_ROOT_NAME && parent.attributes[ATTR_URL_PATH]) parent.name += ' ' + parent.attributes[ATTR_URL_PATH]
if (APPEND_URL_PATH && parent.attributes[ATTR_URL_PATH]) parent.name += ' ' + parent.attributes[ATTR_URL_PATH]
}

let name = typeof req === 'string' ? req : _getSpanName(req, fn, that)
Expand All @@ -308,9 +308,19 @@ function trace(req, fn, that, args, opts = {}) {
LOG._warn && LOG.warn('Failed to determine attributes:', err)
}

// REVISIT: with _hana_prom = true, the sql is not yet in the span name
if (name.match(/^@cap-js\/\w+ - \w+$/) && options.attributes[ATTR_DB_QUERY_TEXT]) {
name += ' ' + options.attributes[ATTR_DB_QUERY_TEXT]
// Normalize DB span names built in cds.js (prepare/exec/stmt.*) so raw SQL
// doesn't leak into the name; the SQL is preserved in db.query.text.
// Matches "@cap-js/<impl> - <verb>" optionally followed by " <sql...>",
// where <verb> is prepare | exec | stmt.<fn>. Covers both the sqlite/pg case
// (SQL is already baked in) and the HANA-promisified case (SQL not yet appended).
const dbNameMatch = name.match(/^(@cap-js\/\w+ - (?:prepare|exec|stmt\.\w+))(?:\s.*)?$/)
if (dbNameMatch && (options.attributes[ATTR_DB_OPERATION_NAME] || options.attributes[ATTR_DB_SQL_TABLE])) {
const SQL_VERB = { READ: 'SELECT', CREATE: 'INSERT' }
const op = options.attributes[ATTR_DB_OPERATION_NAME]
const verb = SQL_VERB[op] ?? op
const table = options.attributes[ATTR_DB_SQL_TABLE]
const tail = [verb, table].filter(Boolean).join(' ')
if (tail) name = `${dbNameMatch[1]} ${tail}`
Comment thread
PDT42 marked this conversation as resolved.
}

if (name.length > 80 && _truncate_span_name !== false) name = name.substring(0, 79) + '…'
Expand Down
Loading