opentelemetry-js icon indicating copy to clipboard operation
opentelemetry-js copied to clipboard

Missing http_route attribute on the http_server_duration metric when traces export is disabled

Open mivanilov opened this issue 1 year ago • 1 comments

What happened?

Steps to Reproduce

Set up NodeSDK with HttpInstrumentation, ExpressInstrumentation and metricReader. Run app with OTEL_TRACES_EXPORTER: none.

Expected Result

http_route attribute is present on the http_server_duration metric.

Actual Result

http_route attribute is missing on the http_server_duration metric.

Additional Details

If NodeSDK is set up with some traceExporter e.g. ConsoleSpanExporter then http_route attribute is present on the http_server_duration metric. Sharing my investigation results - the http_route attribute is added to the metric attributes by HttpInstrumentation from the rpc metadata which in turn is added to the propagation context by ExpressInstrumentation only when tracing is enabled. Apparently at the moment there is no way to workaround it using instrumentation hooks as inside the hooks you have no means to manipulate the propagation context. Also e.g. OTel Java instrumentation adds http_route to the http_server_duration metric even if OTEL_TRACES_EXPORTER: none. There is a feature request that could help to workaround this https://github.com/open-telemetry/opentelemetry-js/issues/3694 but ideally this bug should be fixed.

OpenTelemetry Setup Code

import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { NodeSDK } from '@opentelemetry/sdk-node';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import * as process from 'process';

function startOTelNodeSDK() {
  const otelSDK = new NodeSDK({
    instrumentations: [
      new HttpInstrumentation(),
      new ExpressInstrumentation(),
    ],
    metricReader: new PeriodicExportingMetricReader({
      exporter: new OTLPMetricExporter(),
    }),
  });

  process.on('SIGTERM', () => {
    otelSDK
        .shutdown()
        .then(
            () => console.log('SDK shut down successfully'),
            (err) => console.log('Error shutting down SDK', err),
        )
        .finally(() => process.exit(0));
  });

  console.log('Starting OTel NodeSDK...');
  otelSDK.start();
}

startOTelNodeSDK();

package.json

{
  "name": "otel-instrumentation",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "clean": "rimraf build/*",
    "prepare": "npm run compile",
    "compile": "tsc -p .",
    "postcompile": "copyfiles -f 'build/src/**' build/workspace/ && copyfiles 'node_modules/**' build/workspace/"
  },
  "devDependencies": {
    "copyfiles": "^2.4.1",
    "rimraf": "^5.0.0",
    "typescript": "^5.0.4"
  },
  "dependencies": {
    "@opentelemetry/api": "^1.4.1",
    "@opentelemetry/auto-instrumentations-node": "^0.37.0",
    "@opentelemetry/core": "^1.13.0",
    "@opentelemetry/exporter-metrics-otlp-grpc": "^0.39.1",
    "@opentelemetry/instrumentation-express": "^0.32.3",
    "@opentelemetry/instrumentation-http": "^0.39.1",
    "@opentelemetry/sdk-metrics": "^1.13.0",
    "@opentelemetry/sdk-node": "^0.39.1",
  }
}

Relevant log output

No response

mivanilov avatar Jun 05 '23 19:06 mivanilov