Skip to content

Commit

Permalink
less config
Browse files Browse the repository at this point in the history
  • Loading branch information
sjvans committed Oct 31, 2023
1 parent af0d862 commit ef2fd32
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 89 deletions.
70 changes: 15 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand Down
26 changes: 6 additions & 20 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -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)
}
12 changes: 3 additions & 9 deletions lib/tracing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
17 changes: 12 additions & 5 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down

0 comments on commit ef2fd32

Please sign in to comment.