Checklist

The setup procedure involves the following changes which are described in the following:

  1. package.json: add dependency to xotel-agent-ext-js
  2. package.json: change the start script to consider $NODE_ARGS
  3. mta.yaml: Add environment variables for SAP_CALM_SERVICE_TYPE, SAP_CALM_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES
  4. mta.yaml: Add/modify environment variable NODE_ARGS to contain 

    -r @sap/xotel-agent-ext-js/dist/common/tracer

  5. mta.yaml: Optionally modify build-parameters to include package-lock.json and node_modules in the mtar in case of problems.

Setup

otel 2.0

opentelemetry-js versions 2.0.0 and later are not yet supported.

package.json

{
"dependencies": {
"@sap/xotel-agent-ext-js": "https://73555000100200018064.npmsrv.cdn.repositories.cloud.sap/@sap/xotel-agent-ext-js/-/xotel-agent-ext-js-1.5.31.tgz",
},
}


For deployment, the below environment parameter needs to be configured. OTEL_RESOURCE_ATTRIBUTES not required anymore as of xotel-agent-ext-js version 1.5.23.

SAP_CALM_SERVICE_NAME = <name of your application>

SAP_CALM_SERVICE_TYPE = SAP_CP_CF

OTEL_RESOURCE_ATTRIBUTES = sap.tenancy.tenant_id=<your provider subaccount id>


For example in mta.yaml this can look like this:

mta.yaml

modules:
- name: <service module name>
  properties:
    SAP_CALM_SERVICE_NAME: <application name>
    SAP_CALM_SERVICE_TYPE: SAP_CP_CF
    OTEL_RESOURCE_ATTRIBUTES: sap.tenancy.tenant_id=<your provider subaccount id>


Parameters to be replaced:

  • <application name> arbitrary name of your application
  • <your provider subaccount id> Technical ID of the subaccount, where the instrumented application is running. The technical ID can be found in the SAP BTP cockpit and has the form of a guid: 12345678-1234-1234-1234-123456789abc and will be used by SAP Cloud ALM to map the data to the corresponding cloud service.

If you are using an mta application make sure that node modules and the package-lock.json are included in your mtar:

modules:
- name: <your service module>
type: nodejs
path: gen/srv
build-parameters:
builder: npm
ignore:
# - node_modules
# - package-lock.json


In some cases your mta build setup might copy the built resources to specific folder, e.g. gen/srv. If the node_modules and package-lock.json are not present in this folder we need to tell the mbt command to add these as well:

build-parameters:
before-all:
- builder: custom
commands:
- npm install --production
- ...
- npm install --prefix ./gen/srv


Instrumentation Settings

The following environment variables can be set to configure the behavior of the instrumentation:

NameDescription
SAP_CALM_DCI_AGG_THRESHOLDOptional - Threshold in ms spans to be aggregated (default: 100, i.e. all spans with a response time lower than 100ms will be aggregated and grouped by action, request, user, span type and span kind)
SAP_CALM_DCI_AGG_USEROptional - Specify whether user ids shall be aggregated spans (default: true)

Require the tracer via node arguments in the mta.yaml file:

mta.yaml

modules:
- name: <your srv module>
type: nodejs
properties:
NODE_ARGS: -r @sap/xotel-agent-ext-js/dist/common/tracer


In the package.json file of your project modify the start script to pick up the required tracer.

For regular node.js applications:

{

  "scripts": {

    "start": "node ${NODE_ARGS} <your main file name>.js"

  }

}


For CAP based applications with @sap/cds >= 7:

{

  "scripts": {

    "start": "node ${NODE_ARGS} ./node_modules/.bin/cds-serve"

  }

}

Additional steps for Exception Monitoring

Custom-built applications using cloud logging library

Add the following dependencies in package.json:

package.json

{

     "dependencies": {

        "cf-nodejs-logging-support": "7.5.0-beta.0",

        "@sap/opentelemetry-exporter-for-sap-cloud-logging": "0.4.0"

     },

}


Manual configuration for Exception Monitoring (old method)

If you are not using the @sap/xotel-agent-ext-js require to instrument your application, you have to manually configure Exception Monitoring as explained below. 

On application startup load the above-mentioned instrumentation:

const tracer = require('@sap/xotel-agent-ext-js/dist/common/tracer');

 

// Initialization of Exception Monitoring:

const sdklogs = require ('@opentelemetry/sdk-logs');

const calmExtAutoConf = require('@sap/xotel-agent-ext-js/dist/config/AutoInstrumentationConfig');

const cflog = require("cf-nodejs-logging-support");

const otellog = require('@sap/opentelemetry-exporter-for-sap-cloud-logging');

 

// Create an instance of the OpenTelemetryLogsOutputPlugin.

// By default, it will use the global logger provider.

// Use a custom loggerProvider to capture Cloud Foundry attributes.

const cfLoggerProvider = new sdklogs.LoggerProvider({resource: new otellog.CFApplicationDetector().detect()});

const otelOutputPlugin = new cflog.OpenTelemetryLogsOutputPlugin(cfLoggerProvider)

 

// Optionally set whether additional log fields should be included as log attributes.

// Default: include custom fields only.

otelOutputPlugin.setIncludeFieldsAsAttributes(cflog.FieldInclusionMode.CustomFieldsOnly)

 

// register the plugin

cflog.addOutputPlugin(otelOutputPlugin)

 

// optional, if application is bound to application-logs service

cflog.setCustomFieldsFormat(cflog.CustomFieldsFormat.All);

 

// add CALM Extension Exception Monitoring log processor

cfLoggerProvider.addLogRecordProcessor(calmExtAutoConf.createEXMLogRecordProcessor());

Note:

Require the tracer before you initialize your application. Otherwise the auto-instrumentation will not work. However, for some applications this will still not be sufficient. In such cases we recommend to initialize the application as a callback of the auto-instrumentation:

const tracer = require('@sap/xotel-agent-ext-js/dist/common/tracerCallback')(() => {

 

// Initialization of Exception Monitoring:

const sdklogs = require ('@opentelemetry/sdk-logs');

const calmExtAutoConf = require('@sap/xotel-agent-ext-js/dist/config/AutoInstrumentationConfig');

const cflog = require("cf-nodejs-logging-support");

const otellog = require('@sap/opentelemetry-exporter-for-sap-cloud-logging');

 

// Create an instance of the OpenTelemetryLogsOutputPlugin.

// By default, it will use the global logger provider.

// Use a custom loggerProvider to capture Cloud Foundry attributes

const cfLoggerProvider = new sdklogs.LoggerProvider({resource: new otellog.CFApplicationDetector().detect()});

const otelOutputPlugin = new cflog.OpenTelemetryLogsOutputPlugin(cfLoggerProvider);

 

// Optionally set whether additional log fields should be included as log attributes.

// Default: include custom fields only.

otelOutputPlugin.setIncludeFieldsAsAttributes(cflog.FieldInclusionMode.CustomFieldsOnly);

 

// Register the plugin

cflog.addOutputPlugin(otelOutputPlugin);

 

// optional, if application is bound to application-logs service

cflog.setCustomFieldsFormat(cflog.CustomFieldsFormat.All);

 

// Add CALM Extension Exception Monitoring log processor

cfLoggerProvider.addLogRecordProcessor(calmExtAutoConf.createEXMLogRecordProcessor());

 

//---------------------------------

// initialize your application here

})


Custom-built applications using CDS library (experimental)

Add the following dependencies in package.json:

package.json

{

     "dependencies": {

         "@sap/xotel-agent-ext-js": "https://73555000100200018064.npmsrv.cdn.repositories.cloud.sap/@sap/xotel-agent-ext-js/-/xotel-agent-ext-js-1.5.31.tgz",

         "@cap-js/telemetry": "1.5.3",

         "@sap/cds": "^9"

      },

        "cds": {

          "requires": {

            "telemetry": {

              "logging": {

               "processor": {

                  "module": "@sap/xotel-agent-ext-js",

                  "class": "ExmLogProcessor"

                },

                "exporter": {

                  "module": "@opentelemetry/exporter-logs-otlp-grpc",

                  "class": "OTLPLogExporter"

                }

              }

            }

          }

        }

 }

Here is an example of how to log an error to be collected by Exception Monitoring:

const cds = require ('@sap/cds')

const LOG = cds.log('cds.log')

 

// logging an error

LOG.error('NodeJs error message')

 

try {

    // Code throwing an Error

    } catch (e) {

        // logging an error with details

        LOG.error('NodeJs error message', e)

    }

Troubleshooting

Logging

Log levels can be specified via the the SAP_CALM_DCI_LOG_LEVEL environment variable, e.g.

SAP_CALM_DCI_LOG_LEVEL=debug

Log level of OpenTelemetry's diagnostics logger can set via the OTEL_LOG_LEVEL environment variable, e.g.

OTEL_LOG_LEVEL=info

Disabling auto-instrumentation

If you want to disable the auto-instrumentation (e.g. in case of an emergency) you can do this by

  • Set the environment variable

SAP_CALM_INSTRUMENTATION_ENABLED=false

  • Restart the application

The following variables can also be be set and are effective after restarting the application:

Tracing

If you only want to disable the tracing auto-instrumentation you can set.

SAP_CALM_TRACING_ENABLED=false

Metrics

If you only want to disable the metrics auto-instrumentation you can set.

SAP_CALM_METRICS_ENABLED=false