Skip to content

Commit

Permalink
custom processor
Browse files Browse the repository at this point in the history
  • Loading branch information
sjvans committed Nov 28, 2024
1 parent 94cb036 commit b21d96a
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 24 deletions.
32 changes: 26 additions & 6 deletions lib/logging/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,40 @@ function _getExporter() {
const loggingExporterModule = _require(loggingExporter.module)
if (!loggingExporterModule[loggingExporter.class])
throw new Error(`Unknown logs exporter "${loggingExporter.class}" in module "${loggingExporter.module}"`)
const loggingConfig = { ...(loggingExporter.config || {}) }
const config = { ...(loggingExporter.config || {}) }

if (kind.match(/to-cloud-logging$/)) {
if (!credentials) credentials = getCredsForCLSAsUPS()
if (!credentials) throw new Error('No SAP Cloud Logging credentials found.')
augmentCLCreds(credentials)
loggingConfig.url ??= credentials.url
loggingConfig.credentials ??= credentials.credentials
config.url ??= credentials.url
config.credentials ??= credentials.credentials
}

const exporter = new loggingExporterModule[loggingExporter.class](loggingConfig)
const exporter = new loggingExporterModule[loggingExporter.class](config)
LOG._debug && LOG.debug('Using logs exporter:', exporter)

return exporter
}

function _getCustomProcessor(exporter) {
let {
logging: { processor: loggingProcessor }
} = cds.env.requires.telemetry

if (!loggingProcessor) return

// use _require for better error message
const loggingProcessorModule = _require(loggingProcessor.module)
if (!loggingProcessorModule[loggingProcessor.class])
throw new Error(`Unknown logs processor "${loggingProcessor.class}" in module "${loggingProcessor.module}"`)

const processor = new loggingProcessorModule[loggingProcessor.class](exporter)
LOG._debug && LOG.debug('Using logs processor:', processor)

return processor
}

module.exports = resource => {
if (!cds.env.requires.telemetry.logging?.exporter) return

Expand All @@ -66,10 +84,12 @@ module.exports = resource => {
}

const exporter = _getExporter()

const logProcessor =
process.env.NODE_ENV === 'production'
_getCustomProcessor(exporter) ||
(process.env.NODE_ENV === 'production'
? new BatchLogRecordProcessor(exporter)
: new SimpleLogRecordProcessor(exporter)
: new SimpleLogRecordProcessor(exporter))
loggerProvider.addLogRecordProcessor(logProcessor)

const loggers = {}
Expand Down
16 changes: 8 additions & 8 deletions lib/metrics/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,34 @@ function _getExporter() {
metricsExporter.module === '@cap-js/telemetry' ? require('../exporter') : _require(metricsExporter.module)
if (!metricsExporterModule[metricsExporter.class])
throw new Error(`Unknown metrics exporter "${metricsExporter.class}" in module "${metricsExporter.module}"`)
const metricsConfig = { ...(metricsExporter.config || {}) }
const config = { ...(metricsExporter.config || {}) }

if (kind.match(/to-dynatrace$/)) {
if (!credentials) credentials = getCredsForDTAsUPS()
if (!credentials) throw new Error('No Dynatrace credentials found.')
metricsConfig.url ??= `${credentials.apiurl}/v2/otlp/v1/metrics`
metricsConfig.headers ??= {}
config.url ??= `${credentials.apiurl}/v2/otlp/v1/metrics`
config.headers ??= {}
// credentials.rest_apitoken?.token is deprecated and only supported for compatibility reasons
const { token_name } = cds.env.requires.telemetry
// metrics_apitoken for compatibility with previous releases
const token = credentials[token_name] || credentials.metrics_apitoken || credentials.rest_apitoken?.token
if (!token)
throw new Error(`Neither "${token_name}" nor deprecated "rest_apitoken.token" found in Dynatrace credentials`)
metricsConfig.headers.authorization ??= `Api-Token ${token}`
config.headers.authorization ??= `Api-Token ${token}`
}

if (kind.match(/to-cloud-logging$/)) {
if (!credentials) credentials = getCredsForCLSAsUPS()
if (!credentials) throw new Error('No SAP Cloud Logging credentials found.')
augmentCLCreds(credentials)
metricsConfig.url ??= credentials.url
metricsConfig.credentials ??= credentials.credentials
config.url ??= credentials.url
config.credentials ??= credentials.credentials
}

// default to DELTA
metricsConfig.temporalityPreference ??= AggregationTemporality.DELTA
config.temporalityPreference ??= AggregationTemporality.DELTA

const exporter = new metricsExporterModule[metricsExporter.class](metricsConfig)
const exporter = new metricsExporterModule[metricsExporter.class](config)
LOG._debug && LOG.debug('Using metrics exporter:', exporter)

return exporter
Expand Down
14 changes: 7 additions & 7 deletions lib/tracing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,30 +100,30 @@ function _getExporter() {
tracingExporter.module === '@cap-js/telemetry' ? require('../exporter') : _require(tracingExporter.module)
if (!tracingExporterModule[tracingExporter.class])
throw new Error(`Unknown trace exporter "${tracingExporter.class}" in module "${tracingExporter.module}"`)
const tracingConfig = { ...(tracingExporter.config || {}) }
const config = { ...(tracingExporter.config || {}) }

if (kind.match(/to-dynatrace$/)) {
if (!credentials) credentials = getCredsForDTAsUPS()
if (!credentials) throw new Error('No Dynatrace credentials found')
tracingConfig.url ??= `${credentials.apiurl}/v2/otlp/v1/traces`
tracingConfig.headers ??= {}
config.url ??= `${credentials.apiurl}/v2/otlp/v1/traces`
config.headers ??= {}
// credentials.rest_apitoken?.token is deprecated and only supported for compatibility reasons
const { token_name } = cds.env.requires.telemetry
const token = credentials[token_name] || credentials.rest_apitoken?.token
if (!token)
throw new Error(`Neither "${token_name}" nor deprecated "rest_apitoken.token" found in Dynatrace credentials`)
tracingConfig.headers.authorization ??= `Api-Token ${token}`
config.headers.authorization ??= `Api-Token ${token}`
}

if (kind.match(/to-cloud-logging$/)) {
if (!credentials) credentials = getCredsForCLSAsUPS()
if (!credentials) throw new Error('No SAP Cloud Logging credentials found')
augmentCLCreds(credentials)
tracingConfig.url ??= credentials.url
tracingConfig.credentials ??= credentials.credentials
config.url ??= credentials.url
config.credentials ??= credentials.credentials
}

const exporter = new tracingExporterModule[tracingExporter.class](tracingConfig)
const exporter = new tracingExporterModule[tracingExporter.class](config)
LOG._debug && LOG.debug('Using trace exporter:', exporter)

return exporter
Expand Down
3 changes: 1 addition & 2 deletions lib/tracing/trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ 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[ATTR_URL_PATH])
parent.name += ' ' + parent.attributes[ATTR_URL_PATH]
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)
}
Expand Down
9 changes: 9 additions & 0 deletions test/bookshop/lib/MySimpleLogRecordProcessor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { SimpleLogRecordProcessor } = require('@opentelemetry/sdk-logs')

class MySimpleLogRecordProcessor extends SimpleLogRecordProcessor {
onEmit(logRecord) {
return super.onEmit(logRecord)
}
}

module.exports = { MySimpleLogRecordProcessor }
7 changes: 6 additions & 1 deletion test/logging.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* eslint-disable no-console */

process.env.cds_log_format = 'json'

process.env.cds_requires_telemetry_logging_exporter_module = '@opentelemetry/sdk-logs'
process.env.cds_requires_telemetry_logging_exporter_class = 'ConsoleLogRecordExporter'
process.env.cds_log_format = 'json'

// experimental feature of the experimental feature!!!
process.env.cds_requires_telemetry_logging_processor_module = './lib/MySimpleLogRecordProcessor.js'
process.env.cds_requires_telemetry_logging_processor_class = 'MySimpleLogRecordProcessor'

const cds = require('@sap/cds')
const { expect, GET } = cds.test().in(__dirname + '/bookshop')
Expand Down

0 comments on commit b21d96a

Please sign in to comment.