JavaScript Instrumentation in Containers

JavaScript Applications in Containers with the otel-agent-nodejs-v2 Agent

This documentation details how to instrument a containerized Node.js application using the Elven Observability agent (otel-agent-nodejs-v2) to collect traces and metrics via OpenTelemetry (OTel).

Agent Installation in the Container

In your Dockerfile, install the agent using the following commands:

# Using Yarn
RUN yarn add otel-agent-nodejs-v2

# Or using NPM
RUN npm install otel-agent-nodejs-v2 --save --ignore-scripts

Information: The --ignore-scripts flag is important to prevent the execution of automatic scripts during installation that are not necessary in this context.

Example Dockerfile:

FROM node:20-alpine as build

WORKDIR /app

COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

COPY . .

# Intall OpenTelemetry
RUN yarn add otel-agent-nodejs-v2

RUN yarn build
RUN yarn prisma generate

FROM node:20-alpine

WORKDIR /app

COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/package.json ./
COPY --from=build /app/prisma ./prisma

RUN apk add --no-cache openssl

CMD ["node", "dist/index.js"]

Environment Variable Configuration

Include the following environment variables in your runtime (ECS, EC2, Kubernetes, Docker Compose, etc). They enable automatic instrumentation and define the destination of the data:

- name: NODE_OPTIONS
  value: "--require @opentelemetry/auto-instrumentations-node/register"

- name: OTEL_SERVICE_NAME
  value: "eo-bff"

- name: RESOURCES_ATTRIBUTES
  value: "service=eo-bff,environment=production"

- name: OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
  value: "http://your_collector_endpoint.com:4318/v1/metrics"

- name: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
  value: "http://your_collector_endpoint.com:4318/v1/traces"

- name: OTEL_NODE_DISABLED_INSTRUMENTATIONS
  value: "fs"

- name: OTEL_METRICS_EXPORTER
  value: "otlp"

- name: OTEL_TRACES_EXPORTER
  value: "otlp"

- name: OTEL_METRICS_EXEMPLAR_FILTER
  value: "always_on"

Explanation of main variables:

  • NODE_OPTIONS: Ensures that automatic instrumentation for Node.js is loaded at runtime.

  • OTEL_SERVICE_NAME: Name of the service for identification in the backend.

  • RESOURCES_ATTRIBUTES: Additional attributes that enrich spans and metrics (e.g., environment, version, etc).

  • OTEL_EXPORTER_OTLP_*: URLs where metrics and traces will be sent via OTLP (OpenTelemetry Protocol).

  • OTEL_NODE_DISABLED_INSTRUMENTATIONS: Instrumentations to be disabled (e.g., fs, which generates noise).

  • OTEL_METRICS_EXEMPLAR_FILTER: Defines how metric exemplars will be collected (ideally keep always_on).

Examples by Environment

Docker Compose

env_file:
  - .env
environment:
  - NODE_OPTIONS=--require @opentelemetry/auto-instrumentations-node/register
  - OTEL_SERVICE_NAME=eo-api
  ... # Other Variables

Kubernetes

spec:
  containers:
    - name: node-app
      image: node-app:latest
      env:
        - name: NODE_OPTIONS
          value: "--require @opentelemetry/auto-instrumentations-node/register"
        - name: OTEL_SERVICE_NAME
          value: "eo-api"
        ... # Other Variables

ECS (Fargate ou EC2)

"environment": [
  { "name": "NODE_OPTIONS", "value": "--require @opentelemetry/auto-instrumentations-node/register" },
  { "name": "OTEL_SERVICE_NAME", "value": "eo-api" },
  ...
]

Execução Local

NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" \\
OTEL_SERVICE_NAME=eo-api \\
RESOURCES_ATTRIBUTES="service=eo-api,environment=local" \\
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces \\
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4318/v1/metrics \\
npm run start

Collector (Collector Endpoint)

The OTEL_EXPORTER_OTLP_TRACES_ENDPOINT e OTEL_EXPORTER_OTLP_METRICS_ENDPOINT variables must point to the HTTP collector on port 4318 (default OTLP HTTP). This collector can be in the same container, host, VPC, or cluster.

If you are using Elven Observability, ensure that your Collector is:

  • Listening on 0.0.0.0:4318.

  • Configured to receive OTLP via HTTP (traces and metrics).

  • Exporting to the backend (Grafana Tempo, Mimir, etc).

Validation

Verify if metrics and traces are being received:

  • In Grafana, go to Explore > Tempo or Explore > Metrics with filters byservice.name="eo-bff"

  • It is also possible to enable logs via OTEL for debugging using OTEL_LOG_LEVEL=debug

Troubleshooting

  • Nothing appears in Grafana: check if the endpoint URLs are accessible from the container and if the Collector is listening properly.

  • Issues with NODE_OPTIONS: make sure it is set before running Node.js

  • Incomplete traces: check for libraries that are not manually instrumented or async/await blocks.

  • Ignored variables: some platforms (like ECS or Kubernetes) may override or not apply environment variables correctly, review the manifest/task definition.

  • Collector is down: check the collector logs to ensure it is accepting connections on port 4318

Best Practices

  • Use a OTEL_SERVICE_NAME that is descriptive and standardized (e.g., project-env-component).

  • Use RESOURCES_ATTRIBUTES with environment, version, owner etc, to enrich the data.

  • Disable unused instrumentations with OTEL_NODE_DISABLED_INSTRUMENTATIONS.

  • Avoid instrumenting development environments with too many unnecessary spans.

  • Enable exemplars with OTEL_METRICS_EXEMPLAR_FILTER=always_on to correlate traces with metrics.

Ready .env example

NODE_OPTIONS=--require @opentelemetry/auto-instrumentations-node/register
OTEL_SERVICE_NAME=eo-bff
RESOURCES_ATTRIBUTES=service=eo-bff,environment=production
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://seu_collector_endpoint.com:4318/v1/metrics
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://seu_collector_endpoint.com:4318/v1/traces
OTEL_NODE_DISABLED_INSTRUMENTATIONS=fs
OTEL_METRICS_EXPORTER=otlp
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXEMPLAR_FILTER=always_on

For questions or improvements to this process, contact the Elven Observability team. This instrumentation is designed to work without code modification, with automatic support for popular libraries such as express, http, axios, pg, among others.

Done! Your Node.js app is now instrumented with Elven Observability using OpenTelemetry.

Last updated

Was this helpful?