Skip to content

@opentelemetry/instrumentation-express - incorrect route set to span, if middlewares are being used #2680

Open
@RigoTamas

Description

@RigoTamas

What version of OpenTelemetry are you using?

{
    "@opentelemetry/api": "^1.9.0",
    "@opentelemetry/auto-instrumentations-node": "^0.55.3",
    "@opentelemetry/exporter-metrics-otlp-proto": "^0.57.1",
    "@opentelemetry/exporter-trace-otlp-proto": "^0.57.1",
    "@opentelemetry/instrumentation-express": "^0.47.0",
    "@opentelemetry/sdk-metrics": "^1.30.1",
    "@opentelemetry/sdk-node": "^0.57.1",
    "@opentelemetry/sdk-trace-node": "^1.30.1",
    "express": "4.21.1"
  }

What version of Node are you using?

20.15.0

What did you do?

This repository reproduces the bug:
https://github.com/RigoTamas/opentelemetry-express-instrumentation-span-name-bug

// index.ts

import express, { NextFunction, Request, Response, Router } from "express";

const app = express();

const userMiddleware = (req: Request, res: Response, next: NextFunction) => {
  console.log("user middleware running");
  next();
};

const userMiddleware2 = (req: Request, res: Response, next: NextFunction) => {
  console.log("user middleware 2 running");
  next();
};

const userRouter = Router({ mergeParams: true });

userRouter.use(userMiddleware);

userRouter.use(userMiddleware2);

userRouter.get("/", (req: Request, res: Response, next: NextFunction) => {
  res.send({ name: "John" });
});

const v1Router = Router({ mergeParams: true });

v1Router.use("/user", userRouter);

app.use("/v1", v1Router);

app.listen(8000, () => {
  console.log("api listening on 8000");
});
// instrumentation.ts
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { Resource } from "@opentelemetry/resources";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter(),
  metricReader: new PeriodicExportingMetricReader({
    exporter: new OTLPMetricExporter(),
  }),
  resource: new Resource({
    [ATTR_SERVICE_NAME]: "test service",
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();

What did you expect to see?

I expected to see the http.route tag on the root span, and the name of the root span to be set to GET /v1/user

Image

What did you see instead?

Instead I have seen, that the http.route tag on the root span, and also the name of the root span gets set to GET /

Image

Additional Context

This issue arises because I am calling middlewares on a child router.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghas:reproducerThis bug/feature has a minimal reproduction providedpkg:instrumentation-expresspriority:p2Bugs and spec inconsistencies which cause telemetry to be incomplete or incorrect

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions