From ef2fd321166bd5d2d361134b26cc31edbf7c99ea Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 31 Oct 2023 14:59:19 +0100 Subject: [PATCH] less config --- README.md | 70 ++++++++++---------------------------------- lib/index.js | 26 ++++------------ lib/tracing/index.js | 12 ++------ lib/utils.js | 17 +++++++---- 4 files changed, 36 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index 464ad5f..8a9ac13 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,11 @@ TODO: - Prerequisites? - Which modules must be installed per feature? +### Run Jaeger locally + +- Run `docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 -e COLLECTOR_OTLP_ENABLED=true -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 4317:4317 -p 4318:4318 -p 14250:14250 -p 14268:14268 -p 14269:14269 -p 9411:9411 jaegertracing/all-in-one:latest` +- Open `localhost:16686` to see the traces + ## Configuration Options @@ -91,13 +96,6 @@ Default: ``` -### Instrumentation range - TODO - -- Set the log level for the cds logger `app` to `trace`, to trace individual CAP handler -- With log level `info` of `cds` the handling function in each Service is traced, including DB Services -- Annotate services with `@cds.tracing : false` to disable all tracing for that service. Counterwise, you can enable only the tracing for one service with `@cds.tracing : true`. The exception is detailed OData Adapter tracing, which can only be enabled or disabled globally. At the moment the annotation also only disables all CAP tracing, but not the HTTP and Express tracing. - - ### Exporters @@ -189,62 +187,24 @@ Default: -### Details - TODO - -- In production the BatchSpanProcessor, locally SimpleSpanProcessor is used. -- For Jaeger locally run `docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 -e COLLECTOR_OTLP_ENABLED=true -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 4317:4317 -p 4318:4318 -p 14250:14250 -p 14268:14268 -p 14269:14269 -p 9411:9411 jaegertracing/all-in-one:latest` and open `localhost:16686` to see the traces. -- Due to the tracing initial requests might be slower, locally all requests are slower due to the sync writing to the console. -- In CF Environments `process.env.VCAP_APPLICATION` and `process.env.CF_INSTANCE_GUID` are used to determine the appropriate Resource Attributes - - - ### Environment variables -- NO_TELEMETRY | Disables all tracing -- OTEL_RESOURCE_ATTRIBUTES | Specify additional resource attributes. Per specification the "user defined" attributes, e.g. what CAP defines, has higher priority -- OTEL_SERVICE_NAME | Allows to override the name identified CAP. CAP will use the package.json name and version -- OTEL_LOG_LEVEL | Override the log level for OTEL, by default log level of cds logger `trace` is used -- OTEL_TRACES_EXPORTER | Override the exporter type - -[Batch Span processor config](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/#batch-span-processor): -- OTEL_BSP_SCHEDULE_DELAY | Override default OTEL value -- OTEL_BSP_EXPORT_TIMEOUT | Override default OTEL value -- OTEL_BSP_MAX_QUEUE_SIZE | Override default OTEL value -- OTEL_BSP_MAX_EXPORT_BATCH_SIZE | Override default OTEL value +- `NO_TELEMETRY`: Disables the plugin +- `OTEL_LOG_LEVEL`: If not specified, the log level of cds logger `otel` is used +- `OTEL_SERVICE_NAME`: If not specified, the name is determined from package.json (defaulting to "CAP Application") +- `OTEL_SERVICE_VERSION`: If not specified, the version is determined from package.json (defaulting to "1.0.0") -Should all work, as no explizit configuration is provided by this package: -- OTEL_EXPORTER_OTLP_ENDPOINT -- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT -- OTEL_EXPORTER_OTLP_TRACES_TIMEOUT -- OTEL_EXPORTER_OTLP_TIMEOUT -- DEFAULT_EXPORT_MAX_ATTEMPTS -- DEFAULT_EXPORT_INITIAL_BACKOFF -- DEFAULT_EXPORT_MAX_BACKOFF -- DEFAULT_EXPORT_BACKOFF_MULTIPLIER +For the complete list of environment variables supported by OpenTelemetry, see [Environment Variable Specification](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables). +Please note that `process.env.VCAP_APPLICATION` and `process.env.CF_INSTANCE_GUID`, if present, are used to determine some [Attributes](https://opentelemetry.io/docs/specs/otel/common/#attribute). -## Troubleshooting - TODO -### Plugin does not load +### Instrumentation range - TODO -If upon server startup you do not see the message `[cds] - loaded plugin: { impl: '@cap-js/opentelemetry-instrumentation/cds-plugin' }`, please add -``` -"plugins": [ - "./node_modules/@cap-js/opentelemetry-instrumentation/cds-plugin" -] -``` -to your cds configuration, like: -``` -cds : { - ..., - "plugins": [ - "./node_modules/@cap-js/opentelemetry-instrumentation/cds-plugin" - ], - ... -} -``` -This ensures that the plugin is loaded. +- Set the log level for the cds logger `app` to `trace`, to trace individual CAP handler +- With log level `info` of `cds` the handling function in each Service is traced, including DB Services +- Annotate services with `@cds.tracing : false` to disable all tracing for that service. Counterwise, you can enable only the tracing for one service with `@cds.tracing : true`. The exception is detailed OData Adapter tracing, which can only be enabled or disabled globally. At the moment the annotation also only disables all CAP tracing, but not the HTTP and Express tracing. diff --git a/lib/index.js b/lib/index.js index bbb4fdb..ba27a1c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,36 +1,22 @@ -const cds = require('@sap/cds') -// const LOG = cds.log('otel') - -const fs = require('fs') - const { diag, DiagConsoleLogger } = require('@opentelemetry/api') +const tracing = require('./tracing') +const metrics = require('./metrics') const { getDiagLogLevel, getResource } = require('./utils') module.exports = function () { - diag.setLogger(new DiagConsoleLogger(), getDiagLogLevel()) - - /** - * Registers OpenTelemetry trace provider - */ - // REVISIT: Determine app name and version via package.json - cds.env.requires.otel.trace.name = 'CAP Application' - cds.env.requires.otel.trace.version = 1.0 - if (fs.existsSync(cds.env._home + '/package.json')) { - const pack = JSON.parse(fs.readFileSync(cds.env._home + '/package.json', 'utf8')) - cds.env.requires.otel.trace.name = pack.name - cds.env.requires.otel.trace.version = pack.version - } + // propagate log level to opentelemetry + if (!process.env.OTEL_LOG_LEVEL) diag.setLogger(new DiagConsoleLogger(), getDiagLogLevel()) const resource = getResource() /* * add tracing */ - require('./tracing')(resource) + tracing(resource) /* * add metrics */ - require('./metrics')(resource) + metrics(resource) } diff --git a/lib/tracing/index.js b/lib/tracing/index.js index fe78e0e..329a3d2 100644 --- a/lib/tracing/index.js +++ b/lib/tracing/index.js @@ -96,21 +96,15 @@ module.exports = resource => { // REVISIT: why not do if dynatrace is in deps? if (process.env.NODE_ENV !== 'production' || !isDynatraceEnabled()) { const exporter = _getExporter() + // REVISIT: why this difference? if (process.env.NODE_ENV !== 'production') { tracerProvider.addSpanProcessor(new SimpleSpanProcessor(exporter)) } else { - // REVISIT: config from cds.env - const batchConfig = { - exportTimeoutMillis: process.env.OTEL_BSP_EXPORT_TIMEOUT || 30000, - maxExportBatchSize: process.env.OTEL_BSP_MAX_EXPORT_BATCH_SIZE || 512, - maxQueueSize: process.env.OTEL_BSP_MAX_QUEUE_SIZE || 2048, - scheduledDelayMillis: process.env.OTEL_BSP_SCHEDULE_DELAY || 5000 - } - tracerProvider.addSpanProcessor(new BatchSpanProcessor(exporter, batchConfig)) + tracerProvider.addSpanProcessor(new BatchSpanProcessor(exporter)) } } - // REVISIT + // REVISIT: why needed? if (!cds._tracer) { cds._tracer = trace.getTracer(cds.env.requires.otel.trace.name, cds.env.requires.otel.trace.version) } diff --git a/lib/utils.js b/lib/utils.js index 75a0d9a..b60a79c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -6,7 +6,6 @@ const { Resource } = require('@opentelemetry/resources') const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions') function getDiagLogLevel() { - if (process.env.OTEL_LOG_LEVEL) return DiagLogLevel[process.env.OTEL_LOG_LEVEL.toUpperCase()] if (LOG._trace) return DiagLogLevel.VERBOSE if (LOG._debug) return DiagLogLevel.DEBUG if (LOG._info) return DiagLogLevel.INFO @@ -16,14 +15,22 @@ function getDiagLogLevel() { } function getResource() { - const { name, version } = cds.env.requires.otel.trace + let name = 'CAP Application' + let version = '1.0.0' + try { + const pkg = require(cds.root + '/package.json') + name = pkg.name + version = pkg.version + } catch (err) { + LOG._info && LOG.info('Unable to require package.json to resolve app name and version due to error:', err) + } // REVISIT: Think about adding more from: // https://github.tools.sap/CPA/telemetry-semantic-conventions/blob/main/specification/sap-extensions/resource/service.md const attributes = { - [SemanticResourceAttributes.SERVICE_NAME]: process.env.OTEL_SERVICE_NAME || name, // Set service name to CDS Service - [SemanticResourceAttributes.SERVICE_NAMESPACE]: name, - [SemanticResourceAttributes.SERVICE_VERSION]: version, + [SemanticResourceAttributes.SERVICE_NAME]: process.env.OTEL_SERVICE_NAME || name, + [SemanticResourceAttributes.SERVICE_NAMESPACE]: process.env.OTEL_SERVICE_NAMESPACE, + [SemanticResourceAttributes.SERVICE_VERSION]: process.env.OTEL_SERVICE_VERSION || version, [SemanticResourceAttributes.PROCESS_RUNTIME_NAME]: 'nodejs', [SemanticResourceAttributes.PROCESS_RUNTIME_VERSION]: process.versions.node, [SemanticResourceAttributes.PROCESS_PID]: process.pid,