This topic describes how to submit the trace data of an Express-based Node.js application to Tracing Analysis by using OpenTelemetry.

Prerequisites

The following dependencies on OpenTelemetry are added to the package.json file.
 "dependencies": {
    "@opentelemetry/api": "^1.0.4",
    "@opentelemetry/exporter-trace-otlp-grpc": "^0.27.0",
    "@opentelemetry/instrumentation": "^0.27.0",
    "@opentelemetry/instrumentation-express": "^0.27.0",
    "@opentelemetry/resources": "^1.0.1",
    "@opentelemetry/sdk-trace-base": "^1.0.1",
    "@opentelemetry/sdk-trace-node": "^1.0.1",
    "instrumentation-http": "^0.27.0",
  }

Procedure

  1. Obtain an endpoint.
    1. Log on to the ARMS console.
    2. In the left-side navigation pane, click Integration Center. In the Open Source Monitoring Systems section, click OpenTelemetry.
    3. In the Monitor OpenTelemetry panel, click the Node.js tab. In the upper-right corner, select the region where your application resides.
    4. Copy and save the endpoint and authentication information.
      Note If you deploy your application in an Alibaba Cloud production environment, copy the VPC endpoint. Otherwise, copy the public endpoint.
      Endpoints for a Node.js application
  2. Create a provider.
    const { Resource } = require("@opentelemetry/resources");
    const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
    const {
      SemanticResourceAttributes,
    } = require("@opentelemetry/semantic-conventions");
    
    const provider = new NodeTracerProvider({
      resource: new Resource({
        [SemanticResourceAttributes.HOST_NAME]: require("os").hostname(),
        [SemanticResourceAttributes.SERVICE_NAME]: "opentelemetry-express",    // You can replace opentelemetry-express with the actual service name. 
      }),
    });
  3. Register the HTTP and Express instrumentations by using the provider. The HTTP and Express instrumentations are automatically monitored and intercepted.
    Note For information about how to monitor Node.js applications in other frameworks, see OpenTelemetry documentation.
    const { registerInstrumentations } = require("@opentelemetry/instrumentation");
    const { HttpInstrumentation } = require("instrumentation-http");
    const {
      ExpressInstrumentation,
    } = require("@opentelemetry/instrumentation-express");
    
    registerInstrumentations({
      tracerProvider: provider,
      instrumentations: [HttpInstrumentation, ExpressInstrumentation],
    });
  4. Configure the exporter to export data to ARMS Tracing Analysis.
    Replace <ENDPOINT> and <AUTHENTICATION> in the following code with the endpoint and authentication information that is obtained in Step 1.
    const metadata = new grpc.Metadata();
    metadata.set("Authentication", "<AUTHENTICATION>");
    
    const exporter = new OTLPTraceExporter({ url: "<ENDPOINT>", metadata });
    provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
    provider.register();
  5. Optional:Add custom events and attributes.
    Note For information about how to use the OpenTelemetry API, see OpenTelemetry documentation.
    const api = require("@opentelemetry/api");
    const currentSpan = api.trace.getSpan(api.context.active());
    currentSpan.addEvent("timestamp", { value: Date.now() });
    currentSpan.setAttribute("tagKey-01", "tagValue-01");

View trace data in the ARMS console

Log on to the ARMS console. In the left-side navigation pane, choose Application Monitoring > Trace Explorer. On the Trace Explorer page, you can view the monitoring data that is reported by the Node.js application.

Example: Instrument an Express-based Node.js application

"use strict";

const { Resource } = require("@opentelemetry/resources");
const {
  OTLPTraceExporter,
} = require("@opentelemetry/exporter-trace-otlp-grpc");
const { NodeTracerProvider } = require("@opentelemetry/sdk-trace-node");
const { HttpInstrumentation } = require("instrumentation-http");
const { SimpleSpanProcessor } = require("@opentelemetry/sdk-trace-base");
const {
  ExpressInstrumentation,
} = require("@opentelemetry/instrumentation-express");
const { registerInstrumentations } = require("@opentelemetry/instrumentation");
const {
  SemanticResourceAttributes,
} = require("@opentelemetry/semantic-conventions");
const grpc = require("@grpc/grpc-js");

const provider = new NodeTracerProvider({
  resource: new Resource({
    [SemanticResourceAttributes.HOST_NAME]: require("os").hostname(),
    [SemanticResourceAttributes.SERVICE_NAME]: "opentelemetry-express",
  }),
});

registerInstrumentations({
  tracerProvider: provider,
  instrumentations: [HttpInstrumentation, ExpressInstrumentation],
});

const metadata = new grpc.Metadata();
metadata.set("Authentication", "<AUTHENTICATION>");

const exporter = new OTLPTraceExporter({ url: "<ENDPOINT>", metadata });
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();

// Application code
const api = require("@opentelemetry/api");
const axios = require("axios").default;
const express = require("express");
const app = express();

app.get("/", async (req, res) => {
  const result = await axios.get("http://localhost:7001/api");
  return res.status(201).send(result.data);
});

app.get("/api", async (req, res) => {
  const currentSpan = api.trace.getSpan(api.context.active());
  currentSpan.addEvent("timestamp", { value: Date.now() });
  currentSpan.setAttribute("tagKey-01", "tagValue-01");
  res.json({ code: 200, msg: "success" });
});

app.use(express.json());

app.listen(7001, () => {
  console.log("Listening on http://localhost:7001");
});