From 151aadd849f9cb3e6fb7ad7252d2a23103fa7eca Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:24:50 +0100 Subject: [PATCH] chore: update usage of constants from @opentelemetry/semantic-conventions (#251) --- lib/exporter/ConsoleSpanExporter.js | 26 +++---- lib/index.js | 6 +- lib/tracing/trace.js | 109 +++++++++++++--------------- lib/utils.js | 18 ++--- package.json | 12 +-- 5 files changed, 81 insertions(+), 90 deletions(-) diff --git a/lib/exporter/ConsoleSpanExporter.js b/lib/exporter/ConsoleSpanExporter.js index 41b0c31..80533a4 100644 --- a/lib/exporter/ConsoleSpanExporter.js +++ b/lib/exporter/ConsoleSpanExporter.js @@ -5,13 +5,13 @@ const path = require('path') const { ExportResultCode, hrTimeToMilliseconds } = require('@opentelemetry/core') const { - SEMATTRS_HTTP_TARGET, - SEMATTRS_CODE_FILEPATH, - SEMATTRS_CODE_LINENO - // SEMATTRS_CODE_COLUMN + ATTR_URL_PATH, + SEMATTRS_CODE_FILEPATH: ATTR_CODE_FILEPATH, + SEMATTRS_CODE_LINENO: ATTR_CODE_LINENO + // ATTR_CODE_COLUMN } = require('@opentelemetry/semantic-conventions') -// REVISIT: SEMATTRS_CODE_COLUMN doesn't yet exist in semantic conventions 1.25 -const SEMATTRS_CODE_COLUMN = 'code.column' +// REVISIT: ATTR_CODE_COLUMN doesn't yet exist in semantic conventions 1.27 +const ATTR_CODE_COLUMN = 'code.column' const _padded = v => `${`${v}`.split('.')[0].padStart(3, ' ')}.${(`${v}`.split('.')[1] || '0').padEnd(2, '0').substring(0, 2)}` @@ -26,25 +26,25 @@ const _span2line = (span, parentStartTime = 0) => { let result = `\n ${_padded(start)} → ${_padded(end)} = ${_padded(duration)} ms` let name = span.name - if (name.match(/^[A-Z]+$/)) name = name + ' ' + span.attributes[SEMATTRS_HTTP_TARGET] + if (name.match(/^[A-Z]+$/)) name = name + ' ' + span.attributes[ATTR_URL_PATH] if (name.length > 80) name = name.substring(0, 79) + '…' result += ' ' + (span.___indent || '') + name // REVISIT: what is this for? - if (span.attributes[SEMATTRS_CODE_FILEPATH] !== undefined) { + if (span.attributes[ATTR_CODE_FILEPATH] !== undefined) { if ( path - .normalize(span.attributes[SEMATTRS_CODE_FILEPATH]) + .normalize(span.attributes[ATTR_CODE_FILEPATH]) .match(new RegExp(path.normalize(cds.env._home).replaceAll('\\', '\\\\'), 'g')) && - !path.normalize(span.attributes[SEMATTRS_CODE_FILEPATH]).match(/node_modules/g) + !path.normalize(span.attributes[ATTR_CODE_FILEPATH]).match(/node_modules/g) ) { result += `: .${path - .normalize(span.attributes[SEMATTRS_CODE_FILEPATH]) + .normalize(span.attributes[ATTR_CODE_FILEPATH]) .substring( path.normalize(cds.env._home).length + 1, - path.normalize(span.attributes[SEMATTRS_CODE_FILEPATH]).length - )}:${span.attributes[SEMATTRS_CODE_LINENO]}:${span.attributes[SEMATTRS_CODE_COLUMN]}` + path.normalize(span.attributes[ATTR_CODE_FILEPATH]).length + )}:${span.attributes[ATTR_CODE_LINENO]}:${span.attributes[ATTR_CODE_COLUMN]}` } } diff --git a/lib/index.js b/lib/index.js index 4675553..d9d37f7 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,7 +3,7 @@ const LOG = cds.log('telemetry') const { diag } = require('@opentelemetry/api') const { registerInstrumentations } = require('@opentelemetry/instrumentation') -const { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions') +const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions') const tracing = require('./tracing') const metrics = require('./metrics') @@ -49,8 +49,8 @@ module.exports = function () { // REVISIT: better way to make available? cds._telemetry = { - name: resource.attributes[SEMRESATTRS_SERVICE_NAME], - version: resource.attributes[SEMRESATTRS_SERVICE_VERSION] + name: resource.attributes[ATTR_SERVICE_NAME], + version: resource.attributes[ATTR_SERVICE_VERSION] } /* diff --git a/lib/tracing/trace.js b/lib/tracing/trace.js index c76cbff..a449a05 100644 --- a/lib/tracing/trace.js +++ b/lib/tracing/trace.js @@ -4,28 +4,29 @@ const LOG = cds.log('telemetry') const otel = require('@opentelemetry/api') const { SpanKind, SpanStatusCode, ROOT_CONTEXT } = otel const { - SEMATTRS_HTTP_HOST, - SEMATTRS_HTTP_URL, - SEMATTRS_HTTP_SCHEME, - SEMATTRS_HTTP_TARGET, - SEMATTRS_HTTP_METHOD, - SEMATTRS_CODE_FUNCTION, - SEMATTRS_CODE_FILEPATH, - SEMATTRS_CODE_NAMESPACE, - SEMATTRS_CODE_LINENO, - // SEMATTRS_CODE_COLUMN, - SEMATTRS_DB_SYSTEM, - SEMATTRS_DB_NAME, - SEMATTRS_DB_USER, - SEMATTRS_DB_CONNECTION_STRING, - SEMATTRS_NET_PEER_NAME, - SEMATTRS_NET_PEER_PORT, - SEMATTRS_DB_STATEMENT, - SEMATTRS_DB_OPERATION, - SEMATTRS_DB_SQL_TABLE + ATTR_SERVER_ADDRESS, + ATTR_URL_FULL, + ATTR_URL_SCHEME, + ATTR_URL_PATH, + ATTR_URL_QUERY, + ATTR_HTTP_REQUEST_METHOD, + SEMATTRS_CODE_FUNCTION: ATTR_CODE_FUNCTION, + SEMATTRS_CODE_FILEPATH: ATTR_CODE_FILEPATH, + SEMATTRS_CODE_NAMESPACE: ATTR_CODE_NAMESPACE, + SEMATTRS_CODE_LINENO: ATTR_CODE_LINENO, + // ATTR_CODE_COLUMN, + SEMATTRS_DB_SYSTEM: ATTR_DB_SYSTEM, + SEMATTRS_DB_NAME: ATTR_DB_NAME, + SEMATTRS_DB_USER: ATTR_DB_USER, + SEMATTRS_DB_CONNECTION_STRING: ATTR_DB_CONNECTION_STRING, + SEMATTRS_DB_STATEMENT: ATTR_DB_STATEMENT, + SEMATTRS_DB_OPERATION: ATTR_DB_OPERATION, + SEMATTRS_DB_SQL_TABLE: ATTR_DB_SQL_TABLE, + ATTR_CLIENT_ADDRESS, + ATTR_CLIENT_PORT } = require('@opentelemetry/semantic-conventions') -// REVISIT: SEMATTRS_CODE_COLUMN doesn't yet exist in semantic conventions 1.25 -const SEMATTRS_CODE_COLUMN = 'code.column' +// REVISIT: ATTR_CODE_COLUMN doesn't yet exist in semantic conventions 1.27 +const ATTR_CODE_COLUMN = 'code.column' const { _hrnow } = require('../utils') @@ -57,8 +58,8 @@ function _getParentSpan() { // root span gets request attributes _setAttributes(parent, _getRequestAttributes()) if (HRTIME) parent.startTime = cds.context.http?.req?.__hrnow || _hrnow() - if (ADJUST_ROOT_NAME && parent.attributes[SEMATTRS_HTTP_TARGET]) - parent.name += ' ' + parent.attributes[SEMATTRS_HTTP_TARGET] + if (ADJUST_ROOT_NAME && parent.attributes[ATTR_URL_PATH]) + parent.name += ' ' + parent.attributes[ATTR_URL_PATH] } if (!parent?._is_async) cds.context._otelctx.setValue(cds.context._otelKey, parent) } @@ -99,16 +100,16 @@ function _getStaticAttributes(fn) { if (!fn.__attributes) { const attributes = new Map() - if (fn.name) attributes.set(SEMATTRS_CODE_FUNCTION, fn.name) + if (fn.name) attributes.set(ATTR_CODE_FUNCTION, fn.name) if (fn.__location) { const location = fn.__location const path = location.url.replace('file://', '') - attributes.set(SEMATTRS_CODE_FILEPATH, path) + attributes.set(ATTR_CODE_FILEPATH, path) const namespace = path.match(/\/node_modules\//) ? path.split('/node_modules/')[1] : path - attributes.set(SEMATTRS_CODE_NAMESPACE, namespace) - attributes.set(SEMATTRS_CODE_LINENO, location.line) - attributes.set(SEMATTRS_CODE_COLUMN, location.column) + attributes.set(ATTR_CODE_NAMESPACE, namespace) + attributes.set(ATTR_CODE_LINENO, location.line) + attributes.set(ATTR_CODE_COLUMN, location.column) } const VCAP_APPLICATION = process.env.VCAP_APPLICATION && JSON.parse(process.env.VCAP_APPLICATION) @@ -130,24 +131,14 @@ function _getRequestAttributes() { const attributes = new Map() - attributes.set(SEMATTRS_HTTP_HOST, req.headers.host) - attributes.set('server.address', req.headers.host) - + attributes.set(ATTR_SERVER_ADDRESS, req.headers.host) const full = req.protocol + '://' + req.headers.host + req.url - attributes.set(SEMATTRS_HTTP_URL, full) - attributes.set('url.full', full) - - attributes.set(SEMATTRS_HTTP_SCHEME, req.protocol) - attributes.set('url.scheme', req.protocol) - - attributes.set(SEMATTRS_HTTP_TARGET, req.url) + attributes.set(ATTR_URL_FULL, full) + attributes.set(ATTR_URL_SCHEME, req.protocol) const [path, query] = req.url.split('?') - attributes.set('url.path', path) - if (query) attributes.set('url.query', query) - - attributes.set(SEMATTRS_HTTP_METHOD, req.method) - attributes.set('http.request.method', req.method) - + attributes.set(ATTR_URL_PATH, path) + if (query) attributes.set(ATTR_URL_QUERY, query) + attributes.set(ATTR_HTTP_REQUEST_METHOD, req.method) for (const [key, value] of Object.entries(cds.context.http.req.headers || {})) { if (MASK_HEADERS.some(m => key.match(m))) attributes.set(`http.request.header.${key}`, '***') else attributes.set(`http.request.header.${key}`, value.split(';')) @@ -163,12 +154,12 @@ function _getStaticDBAttributes(tenant = '', creds) { if (!module.exports.__dbAttributes) module.exports.__dbAttributes = new Map() if (!module.exports.__dbAttributes.has(tenant)) { const attributes = new Map() - attributes.set(SEMATTRS_DB_SYSTEM, DB_KINDS[cds.db.options.kind] || cds.db.options.kind) - attributes.set(SEMATTRS_DB_NAME, cds.db.vcap?.name || cds.db.name) - attributes.set(SEMATTRS_DB_USER, creds ? creds.user : cds.db.options.credentials.user) - attributes.set(SEMATTRS_DB_CONNECTION_STRING, creds ? creds.url : cds.db.options.credentials.url) - attributes.set(SEMATTRS_NET_PEER_NAME, creds ? creds.host : cds.env.requires.db.credentials.host) - attributes.set(SEMATTRS_NET_PEER_PORT, creds ? creds.port : cds.env.requires.db.credentials.port) + attributes.set(ATTR_DB_SYSTEM, DB_KINDS[cds.db.options.kind] || cds.db.options.kind) + attributes.set(ATTR_DB_NAME, cds.db.vcap?.name || cds.db.name) + attributes.set(ATTR_DB_USER, creds ? creds.user : cds.db.options.credentials.user) + attributes.set(ATTR_DB_CONNECTION_STRING, creds ? creds.url : cds.db.options.credentials.url) + attributes.set(ATTR_CLIENT_ADDRESS, creds ? creds.host : cds.env.requires.db.credentials.host) + attributes.set(ATTR_CLIENT_PORT, creds ? creds.port : cds.env.requires.db.credentials.port) module.exports.__dbAttributes.set(tenant, attributes) } return module.exports.__dbAttributes.get(tenant) @@ -181,11 +172,11 @@ function _getDynamicDBAttributes(options, args, parentSpan) { const dbAttributes = new Map() const db_statement = options.sql || (typeof args[0].query === 'string' && args[0].query) || (typeof args[0] === 'string' && args[0]) - if (db_statement) dbAttributes.set(SEMATTRS_DB_STATEMENT, db_statement) - const db_operation = args[0].event || parentSpan?.attributes[SEMATTRS_DB_OPERATION] - if (db_operation) dbAttributes.set(SEMATTRS_DB_OPERATION, db_operation) - const db_sql_table = args[0].target?.name || parentSpan?.attributes[SEMATTRS_DB_SQL_TABLE] - if (db_sql_table) dbAttributes.set(SEMATTRS_DB_SQL_TABLE, db_sql_table) + if (db_statement) dbAttributes.set(ATTR_DB_STATEMENT, db_statement) + const db_operation = args[0].event || parentSpan?.attributes[ATTR_DB_OPERATION] + if (db_operation) dbAttributes.set(ATTR_DB_OPERATION, db_operation) + const db_sql_table = args[0].target?.name || parentSpan?.attributes[ATTR_DB_SQL_TABLE] + if (db_sql_table) dbAttributes.set(ATTR_DB_SQL_TABLE, db_sql_table) return dbAttributes } @@ -277,11 +268,11 @@ function trace(name, fn, targetObj, args, options = {}) { // augment db.statement at parent, if necessary if ( - span.attributes[SEMATTRS_DB_STATEMENT] && - parentSpan?.attributes[SEMATTRS_DB_SYSTEM] && - !parentSpan.attributes[SEMATTRS_DB_STATEMENT] + span.attributes[ATTR_DB_STATEMENT] && + parentSpan?.attributes[ATTR_DB_SYSTEM] && + !parentSpan.attributes[ATTR_DB_STATEMENT] ) { - parentSpan.setAttribute(SEMATTRS_DB_STATEMENT, span.attributes[SEMATTRS_DB_STATEMENT]) + parentSpan.setAttribute(ATTR_DB_STATEMENT, span.attributes[ATTR_DB_STATEMENT]) } } diff --git a/lib/utils.js b/lib/utils.js index 436972d..23be98a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -7,10 +7,10 @@ const { DiagLogLevel } = require('@opentelemetry/api') const { hrTimeToMilliseconds } = require('@opentelemetry/core') const { Resource } = require('@opentelemetry/resources') const { - SEMRESATTRS_SERVICE_NAME, - SEMRESATTRS_SERVICE_VERSION, - SEMRESATTRS_SERVICE_NAMESPACE, - SEMRESATTRS_SERVICE_INSTANCE_ID + ATTR_SERVICE_NAME, + ATTR_SERVICE_VERSION, + SEMRESATTRS_SERVICE_NAMESPACE: ATTR_SERVICE_NAMESPACE, + SEMRESATTRS_SERVICE_INSTANCE_ID: ATTR_SERVICE_INSTANCE_ID } = require('@opentelemetry/semantic-conventions') function getDiagLogLevel() { @@ -38,15 +38,15 @@ function getResource() { const attributes = {} // Service - attributes[SEMRESATTRS_SERVICE_NAME] = process.env.OTEL_SERVICE_NAME || name - attributes[SEMRESATTRS_SERVICE_VERSION] = process.env.OTEL_SERVICE_VERSION || version + attributes[ATTR_SERVICE_NAME] = process.env.OTEL_SERVICE_NAME || name + attributes[ATTR_SERVICE_VERSION] = process.env.OTEL_SERVICE_VERSION || version // Service (Experimental) - if (process.env.OTEL_SERVICE_NAMESPACE) attributes[SEMRESATTRS_SERVICE_NAMESPACE] = process.env.OTEL_SERVICE_NAMESPACE - if (VCAP_APPLICATION) attributes[SEMRESATTRS_SERVICE_INSTANCE_ID] = VCAP_APPLICATION.instance_id + if (process.env.OTEL_SERVICE_NAMESPACE) attributes[ATTR_SERVICE_NAMESPACE] = process.env.OTEL_SERVICE_NAMESPACE + if (VCAP_APPLICATION) attributes[ATTR_SERVICE_INSTANCE_ID] = VCAP_APPLICATION.instance_id if (process.env.CF_INSTANCE_GUID) { - attributes[SEMRESATTRS_SERVICE_INSTANCE_ID] = process.env.CF_INSTANCE_GUID + attributes[ATTR_SERVICE_INSTANCE_ID] = process.env.CF_INSTANCE_GUID attributes['sap.cf.instance_id'] = process.env.CF_INSTANCE_GUID } diff --git a/package.json b/package.json index 696047e..ee4c279 100644 --- a/package.json +++ b/package.json @@ -20,14 +20,14 @@ }, "dependencies": { "@opentelemetry/api": "^1.9", - "@opentelemetry/core": "^1.25", + "@opentelemetry/core": "^1.27", "@opentelemetry/instrumentation": "^0.55", "@opentelemetry/instrumentation-http": "^0.55", - "@opentelemetry/resources": "^1.25", - "@opentelemetry/sdk-metrics": "^1.25", - "@opentelemetry/sdk-trace-base": "^1.25", - "@opentelemetry/sdk-trace-node": "^1.25", - "@opentelemetry/semantic-conventions": "^1.25" + "@opentelemetry/resources": "^1.27", + "@opentelemetry/sdk-metrics": "^1.27", + "@opentelemetry/sdk-trace-base": "^1.27", + "@opentelemetry/sdk-trace-node": "^1.27", + "@opentelemetry/semantic-conventions": "^1.27" }, "peerDependencies": { "@sap/cds": ">=7"