From 9543e8b7edac128a54b8c66ddac728a6685afb8a Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:56:56 +0200 Subject: [PATCH 1/2] chore: downport `1.5.2` to `1` (#370) --- .github/workflows/hana.yml | 2 +- .gitignore | 1 + CHANGELOG.md | 6 +++++ jest.config.js | 2 +- lib/tracing/cds.js | 8 +++---- lib/tracing/trace.js | 6 +++-- package.json | 2 +- test/passport.test.js | 49 +++++++++++++++++++++++++------------- 8 files changed, 51 insertions(+), 25 deletions(-) diff --git a/.github/workflows/hana.yml b/.github/workflows/hana.yml index 4ab51956..4d43b9c6 100644 --- a/.github/workflows/hana.yml +++ b/.github/workflows/hana.yml @@ -1,4 +1,4 @@ -name: CI +name: HANA permissions: contents: read diff --git a/.gitignore b/.gitignore index 0fd69489..99e365a6 100644 --- a/.gitignore +++ b/.gitignore @@ -140,3 +140,4 @@ package-lock.json test/msg-box test/bookshop/gen +test/bookshop/.cdsrc.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 64dd9b6c..8bcb59ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ 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 1.5.2 - 2025-08-18 + +### Fixed + +- SAP Passport propagation with `cds.requires.telemetry.tracing._hana_prom = true` + ## Version 1.5.1 - 2025-08-11 ### Fixed diff --git a/jest.config.js b/jest.config.js index 9ca04ddc..70fb6cd8 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,7 +5,7 @@ const config = { if (process.env.CI && process.env.HANA_DRIVER) { config.testTimeout *= 10 - config.testMatch = ['**/tracing-attributes.test.js'] + config.testMatch = ['**/tracing-attributes.test.js', '**/passport.test.js'] if (process.env.HANA_PROM) process.env.cds_requires_telemetry_tracing = JSON.stringify({ _hana_prom: process.env.HANA_PROM === 'true' }) diff --git a/lib/tracing/cds.js b/lib/tracing/cds.js index 934e8330..c6766273 100644 --- a/lib/tracing/cds.js +++ b/lib/tracing/cds.js @@ -14,14 +14,14 @@ function _wrapHandler(handler) { }) } -const _wrapStmt = (stmt, impl, sql) => { +const _wrapStmt = (stmt, impl, sql, dbc) => { for (const fn of ['run', 'get', 'all', 'stream', 'runBatch']) { if (!stmt[fn]) continue const it = stmt[fn] stmt[fn] = wrap(it, { no_locate: true, wrapper: function () { - return trace(`${impl} - stmt.${fn} ${sql}`, it, this, arguments, { sql, fn, kind: SpanKind.CLIENT }) + return trace(`${impl} - stmt.${fn} ${sql}`, it, this, arguments, { sql, dbc, fn, kind: SpanKind.CLIENT }) } }) } @@ -131,8 +131,8 @@ module.exports = () => { fn: 'prepare', kind: SpanKind.CLIENT }) - if (stmt instanceof Promise) return stmt.then(stmt => _wrapStmt(stmt, impl, sql)) - return _wrapStmt(stmt, impl, sql) + if (stmt instanceof Promise) return stmt.then(stmt => _wrapStmt(stmt, impl, sql, this.dbc)) + return _wrapStmt(stmt, impl, sql, this.dbc) } }) dbService.prototype.exec = wrap(_exec, { diff --git a/lib/tracing/trace.js b/lib/tracing/trace.js index fed83d59..48e6054c 100644 --- a/lib/tracing/trace.js +++ b/lib/tracing/trace.js @@ -321,7 +321,9 @@ function trace(req, fn, that, args, opts = {}) { if (span.constructor.name === 'NonRecordingSpan') return fn.apply(that, args) // SAP Passport - if (process.env.SAP_PASSPORT && that.dbc?.set) { + // REVISIT: fallback for _hana_prom = false + const dbc = opts.dbc || name.startsWith('@cap-js/hana') && that.dbc + if (process.env.SAP_PASSPORT && dbc?.set) { const { spanId, traceId } = span.spanContext() // REVISIT: @sap/dsrpassport uses '0226' for VARPARTOFFSET // prettier-ignore @@ -346,7 +348,7 @@ function trace(req, fn, that, args, opts = {}) { /* VARPARTOFFSET */ '0000' }${ /* EYECATCHER */ '2A54482A'}` LOG._debug && LOG.debug('Setting SAP Passport:', passport) - that.dbc.set({ SAP_PASSPORT: passport }) + dbc.set({ SAP_PASSPORT: passport }) } const _on_success = res => { diff --git a/package.json b/package.json index ed821139..ef38eefa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cap-js/telemetry", - "version": "1.5.1", + "version": "1.5.2", "description": "CDS plugin providing observability features, incl. automatic OpenTelemetry instrumentation.", "repository": { "type": "git", diff --git a/test/passport.test.js b/test/passport.test.js index c0a78731..652d564f 100644 --- a/test/passport.test.js +++ b/test/passport.test.js @@ -2,37 +2,54 @@ process.env.SAP_PASSPORT = 'true' const cds = require('@sap/cds') const { expect, GET } = cds.test().in(__dirname + '/bookshop') -const log = cds.test.log() describe('SAP Passport', () => { - let _session_vars, _count + if (cds.env.requires.db.kind === 'sqlite') return test.skip('n/a for SQLite', () => {}) - cds.on('connect', srv => { - if (srv.options.kind === 'sqlite') { - const { acquire } = srv - srv.acquire = async function () { + const admin = { auth: { username: 'alice' } } + + cds.on('connect', async service => { + if (service.kind === 'hana') { + const { acquire } = service + service.acquire = async function () { const dbc = await acquire.apply(this, arguments) - dbc.set ??= o => { - _session_vars = Object.assign(_session_vars || {}, o) - _count++ + if (!dbc._native.set._patched) { + const { set } = dbc._native + dbc._native.set = function (obj) { + if ('SAP_PASSPORT' in obj) { + _passports.push(obj.SAP_PASSPORT) + _count++ + } + return set.apply(this, arguments) + } + dbc._native.set._patched = true } return dbc } } }) - const admin = { auth: { username: 'alice' } } - - beforeEach(log.clear) + let _passports, _count beforeEach(() => { - _session_vars = undefined + _passports = [] _count = 0 }) - test('gets set', async () => { - const { status } = await GET('/odata/v4/admin/Books', admin) + test('gets set once for simple queries', async () => { + const { status } = await GET('/odata/v4/admin/Books?$select=ID,title', admin) expect(status).to.equal(200) - expect(_session_vars).to.containSubset({ SAP_PASSPORT: s => s.match(/^2A54482A/) }) expect(_count).to.equal(2) + expect(_passports[0]).to.equal('') //> the reset + expect(_passports[1]).to.match(/^2A54482A/) + }) + + test('gets set twice for prepared statements', async () => { + const { status } = await GET("/odata/v4/admin/Books?$select=ID,title&$filter=title eq 'hurz'", admin) + expect(status).to.equal(200) + expect(_count).to.equal(3) + expect(_passports[0]).to.equal('') //> the reset + expect(_passports[1]).to.match(/^2A54482A/) + expect(_passports[2]).to.match(/^2A54482A/) + expect(_passports[1]).to.not.equal(_passports[2]) //> different for prepare and execute }) }) From 0e0e6e1fa679007e637c56663271cb5922d489db Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Mon, 27 Oct 2025 13:30:33 +0100 Subject: [PATCH 2/2] fix: handle pre-initialized LoggerProvider (#383) --- CHANGELOG.md | 6 ++++++ lib/logging/index.js | 3 +-- package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de549ce8..b9f0b081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ 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 1.5.4 - 2025-10-27 + +### Fixed + +- Handle pre-initialized `LoggerProvider` + ## Version 1.5.3 - 2025-09-01 ### Fixed diff --git a/lib/logging/index.js b/lib/logging/index.js index 6d77d766..f7e204c9 100644 --- a/lib/logging/index.js +++ b/lib/logging/index.js @@ -77,12 +77,11 @@ module.exports = resource => { const { LoggerProvider, BatchLogRecordProcessor, SimpleLogRecordProcessor } = require('@opentelemetry/sdk-logs') let loggerProvider = logs.getLoggerProvider() - if (!loggerProvider.getDelegateLogger()) { + if (loggerProvider.constructor.name === 'ProxyLoggerProvider') { loggerProvider = new LoggerProvider({ resource }) logs.setGlobalLoggerProvider(loggerProvider) } else { LOG._warn && LOG.warn('LoggerProvider already initialized by a different module. It will be used as is.') - loggerProvider = loggerProvider.getDelegateLogger() } const exporter = _getExporter() diff --git a/package.json b/package.json index 2c795049..c7a77abe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cap-js/telemetry", - "version": "1.5.3", + "version": "1.5.4", "description": "CDS plugin providing observability features, incl. automatic OpenTelemetry instrumentation.", "repository": { "type": "git",