All Products
Search
Document Center

Application Real-Time Monitoring Service:Use OpenTelemetry to perform tracing analysis on NGINX

Last Updated:Nov 19, 2025

This topic describes how to use OpenTelemetry to perform tracing analysis on NGINX. NGINX is a high-performance, lightweight, and open-source web server and reverse proxy whose functionality can be extended through modules. The ngx_otel_module collects traces from NGINX and forwards them toManaged Service for OpenTelemetry.

Limitations

  • The ngx_otel_module can report the trace data of NGINX only over gRPC and cannot report the trace data of NGINX over HTTP.

  • Release notes for the ngx_otel_module:

    • V0.1.2 or later: You can directly forward NGINX traces to Managed Service for OpenTelemetry.

    • V0.1.1 or earlier: The ngx_otel_module does not support setting gRPC authentication tokens. Therefore, you must deploy an OpenTelemetry Collector to forward NGINX traces to Managed Service for OpenTelemetry.

Prerequisites

Obtain an endpoint

  1. Log on to the Application Real-Time Monitoring Service (ARMS) console. In the left-side navigation pane, click Integration Center.

  2. On the Integration Center page, click the OpenTelemetry card in the Server-side Applications section.

  3. In the OpenTelemetry panel, click the Start Integration tab, and then select a region in which you want to report the trace data.

    Note

    Resources are automatically initialized in the region that you access for the first time.

  4. Configure the Connection Type and Export Protocol parameters and copy an endpoint.

    • Connection Type: If your service is deployed on Alibaba Cloud and resides in the region that you selected, we recommend that you set this parameter to Alibaba Cloud VPC Network. Otherwise, set this parameter to Public Network.

    • Export Protocol: Set this parameter to gRPC based on the protocol that is supported by the client.

    87.jpg

Procedure

Step 1: Download the ngx_otel_module

Method 1: Use the package manager

  • Download the ngx_otel_module for Alibaba Cloud Linux, Red Hat Linux, Red Hat Enterprise Linux, or their derivatives:

    sudo yum install nginx-module-otel
  • Download the ngx_otel_module for Debian, Ubuntu, or their derivatives:

    sudo apt install nginx-module-otel

Method 2: Use the pre-built Docker image

Note

NGINX V1.27.5 and later use the ngx_otel_module V0.1.2 by default.

Visit the Docker official website, search for and pull the NGINX images suffixed with -otel, such as nginx:1.23.3-otel, and deploy the service following the standard procedure for starting a Docker.

image

Step 2: Enable the ngx_otel_module

To enable the tracing analysis feature for NGINX, you must load the ngx_otel_module and configure parameters of the ngx_otel_module in the main configuration file /etc/nginx/nginx.conf of NGINX. For more information about the parameters of the ngx_otel_module, see the ngx_otel_module official documentation.

  • Enable tracing analysis for all HTTP requests

    ngx_otel_module V0.1.2 or later

    load_module modules/ngx_otel_module.so; # Load ngx_otel_module
    ...
    http {
        ...
    
        otel_exporter {
            endpoint "${GRPC_ENDPOINT}"; # The gRPC endpoint obtained in the prerequisites.
            header Authentication "${GRPC_TOKEN}"; # The authentication token obtained in the prerequisites.
        }
    
        otel_trace on;                     # Enable Tracing Analysis.
        otel_service_name ${SERVICE_NAME};  # The application name.
        otel_trace_context propagate;         # Inject the trace context into downstream services.
        ...
    }

    ngx_otel_module V0.1.1 or earlier

    Note

    Replace the following variables in the configuration:

    • ${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}: The gRPC endpoint of the OpenTelemetry Collector that you deployed, for example, localhost:4317. This endpoint is different from the one of Managed Service for OpenTelemetry obtained in the prerequisites.

    • ${SERVICE_NAME}: The application name. This name is displayed as the NGINX application name in the Managed Service for OpenTelemetry console.

    load_module modules/ngx_otel_module.so; # Load the ngx_otel_module.
    ...
    http {
        ...
    
        otel_exporter {
            endpoint ${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}; # The reporting address of the OpenTelemetry Collector, such as localhost:4317.
        }
    
        otel_trace on;                     # Enable Tracing Analysis.
        otel_service_name ${SERVICE_NAME};  # The application name.
        otel_trace_context propagate;         # Inject the trace context into downstream services.
        ...
    }
  • Enable tracing analysis for HTTP requests sent to a single location

    ngx_otel_module V0.1.2 or later

    load_module modules/ngx_otel_module.so; # Load the ngx_otel_module.
    
    ...
    
    http {
    
        otel_exporter {
            endpoint "${GRPC_ENDPOINT}"; # The gRPC endpoint obtained in the prerequisites.
            header Authentication "${GRPC_TOKEN}"; # The authentication token obtained in the prerequisites.
        }
    
        server {
            listen 127.0.0.1:80;
    
            location /hello {
                otel_trace         on;             # Enable Tracing Analysis only for 127.0.0.1:80/hello.
                otel_service_name ${SERVICE_NAME}  # The application name.
                otel_trace_context propagate;         # Inject the trace context into downstream services.
    
                ...
            }
        }
    }

    ngx_otel_module V0.1.1 or earlier

    Note

    Replace the two variables in the configuration:

    • ${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}: The gRPC endpoint of the OpenTelemetry Collector that you deployed, for example, localhost:4317. This endpoint is different from the one of Managed Service for OpenTelemetry obtained in the prerequisites.

    • ${SERVICE_NAME}: The application name. This name is displayed as the NGINX application name in the Managed Service for OpenTelemetry console.

    load_module modules/ngx_otel_module.so; # Load the ngx_otel_module.
    
    ...
    
    http {
    
        otel_exporter {
            endpoint ${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}; # The reporting address of the OpenTelemetry Collector, for example, localhost:4317.
        }
    
        server {
            listen 127.0.0.1:80;
    
            location /hello {
                otel_trace         on;             # Enable Tracing Analysis only for 127.0.0.1:80/hello.
                otel_service_name ${SERVICE_NAME}  # The application name.
                otel_trace_context propagate;         # Inject the trace context into downstream services.
    
                ...
            }
        }
    }

Step 3: (Optional) Deploy an OpenTelemetry Collector

Note

This step is required only for the ngx_otel_module V0.1.1 or earlier.

Method 1: Installation in the ACK console

  1. Log on to the ACK console. In the left-side navigation pane, choose Marketplace > Marketplace.

  2. On the page that appears, find and click opentelemetry-collector. In the panel that appears, click Deploy in the upper-right corner.

  3. In the Deploy panel, select the target cluster and click Next.

  4. In the Parameters step, add the following parameters and click OK.

    Note

    Replace ${GRPC_ENDPOINT} and ${GRPC_ENDPOINT_TOKEN} with the gPRC endpoint and authentication token you retrieved in Prerequisites.

    receivers:
      otlp:
        protocols:
          grpc: 
            endpoint: 0.0.0.0:4317
    
    exporters:
      otlp:
        endpoint: ${GRPC_ENDPOINT}
        tls:
          insecure: true
        headers:
          "Authentication": "${GRPC_ENDPOINT_TOKEN}"
    
    processors:
      batch:
      
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [otlp]

    Example:

    81

Method 2: Manual installation

The following example shows how to deploy the OpenTelemetry Collector by using Docker. For more information, see Install the Collector.

  1. Create a file named opentelemetry-config.yaml and copy the following content to the file.

    This file is used to define and configure the behaviors and features of the OpenTelemetry Collector, including how to receive, process, and export data.

    Note

    Replace ${GRPC_ENDPOINT} and ${GRPC_ENDPOINT_TOKEN} with the gRPC endpoint and authentication token that you obtained in the Prerequisites section of this topic.

    receivers:
      otlp:
        protocols:
          grpc: 
            endpoint: 0.0.0.0:4317
    
    exporters:
      otlp:
        endpoint: ${GRPC_ENDPOINT}
        tls:
          insecure: true
        headers:
          "Authentication": "${GRPC_ENDPOINT_TOKEN}"
    
    processors:
      batch:
      
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [otlp]
  2. Run the following command to start the OpenTelemetry Collector:

    docker run -v $(pwd)/opentelemetry-config.yaml:/etc/otelcol-contrib/config.yaml otel/opentelemetry-collector-contrib:0.105.0

Step 4: View NGINX traces

After you complete the preceding steps and restart NGINX, you can send requests to NGINX to generate traces. Then, you can log on to the Managed Service for OpenTelemetry console to view the NGINX traces generated by OpenTelemetry.

  • On the Applications page, find the NGINX application and click the application name.89.jpg

  • On the Trace details tab, view the trace details, including the request duration, client IP address, and HTTP status code. If your backend service is also connected to Managed Service for OpenTelemetry, the traces of NGINX and the backend services are automatically associated to provide an integrated view.88.jpg

Example

The following example shows how to collect the trace data of NGINX and a backend service and report the trace data to Managed Service for OpenTelemetry.

Step 1: Make preparations

Step 2: Create project directories

nginx-otel-demo
│
├── docker-compose.yml          # The configuration file of Docker Compose.
│
├── nginx_conf/                 # The configuration files of NGINX.
│   ├── default.conf
│   └── nginx.conf              
│
├── otel_conf/                  # The configuration file of the OpenTelemetry Collector.
│   └── config.yaml           
│
└── backend/                    # The backend service developed by using Node.js.
    ├── Dockerfile              
    ├── main.js
    ├── package.json
    └── package-lock.json

Create directories.

mkdir nginx-otel-demo && cd nginx-otel-demo

mkdir -p nginx_conf otel_conf backend

Step 3: Create the configuration files of NGINX

  1. Create the main configuration file nginx.conf of NGINX.

    ngx_otel_module V0.1.2 or later

    cat << 'EOF' > nginx_conf/nginx.conf
    load_module modules/ngx_otel_module.so;
    
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        otel_exporter {
            endpoint "${GRPC_ENDPOINT}";
            header Authentication "${GRPC_TOKEN}";
        }
    
        otel_trace on;
    
        otel_trace_context propagate;
    
        otel_service_name nginx;
    
        include /etc/nginx/conf.d/*.conf;
    
    }
    EOF

    ngx_otel_module V0.1.1 or earlier

    load_module modules/ngx_otel_module.so;
    
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        otel_exporter {
            endpoint otel-collector:4317;
        }
    
        otel_trace on;
    
        otel_trace_context propagate;
    
        otel_service_name nginx;
    
        include /etc/nginx/conf.d/*.conf;
    
    }
    EOF
    
  2. Create the configuration file default.conf of NGINX.

    cat << 'EOF' > nginx_conf/default.conf
    server {
        listen       80;
        server_name  localhost;
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
        
        # Configure parameters.
        location /hello {
            proxy_pass http://backend-api:7001/hello;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    EOF

Step 4: (Optional) Create the configuration file of the OpenTelemetry Collector

Note

This step is required only for the ngx_otel_module V0.1.1 or earlier.

Create the configuration file of the OpenTelemetry Collector. This configuration file defines the methods to receive, process, and report data.

Note

Replace ${GRPC_ENDPOINT} and ${GRPC_ENDPOINT_TOKEN} with the gRPC endpoint and authentication token that are obtained in the Prerequisites section of this topic.

cat << 'EOF' > otel_conf/config.yaml
receivers:
  otlp:
    protocols:
      grpc: 
        endpoint: 0.0.0.0:4317

exporters:
  otlp:
    endpoint: ${GRPC_ENDPOINT}
    tls:
      insecure: true
    headers:
      "Authentication": "${GRPC_ENDPOINT_TOKEN}"

processors:
  batch:
  
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlp]
EOF

Step 5: Create a backend service by using Node.js

  1. Create the package.json file. This file contains the configuration information of the backend service, including the service name, service version, and dependencies.

    cat << 'EOF' > backend/package.json
    {
      "name": "backend",
      "version": "1.0.0",
      "main": "index.js",
      "scripts": {},
      "keywords": [],
      "author": "",
      "license": "ISC",
      "description": "",
      "dependencies": {
        "@opentelemetry/api": "^1.9.0",
        "@opentelemetry/auto-instrumentations-node": "^0.52.0",
        "axios": "^1.7.7",
        "express": "^4.21.1"
      }
    }
    EOF
  2. Create the main.js file that defines a basic Express web application.

    cat << 'EOF' > backend/main.js
    "use strict";
    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/hello");
      return res.status(201).send(result.data);
    });
    app.get("/hello", async (req, res) => {
      console.log("hello world!")
      res.json({ code: 200, msg: "success" });
    });
    app.use(express.json());
    app.listen(7001, () => {
      console.log("Listening on http://localhost:7001");
    });
    EOF
  3. Create the Dockerfile.

    ngx_otel_module V0.1.2 or later

    cat << 'EOF' > backend/Dockerfile
    FROM node:20.16.0
    WORKDIR /app
    COPY package*.json ./
    RUN npm install
    COPY . .
    ENV OTEL_TRACES_EXPORTER="otlp"
    ENV OTEL_LOGS_EXPORTER=none
    ENV OTEL_METRICS_EXPORTER=none
    ENV OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc
    ENV OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="${GRPC_ENDPOINT}"
      export OTEL_EXPORTER_OTLP_HEADERS=Authentication=${GRPC_TOKEN}
    ENV OTEL_NODE_RESOURCE_DETECTORS="env,host,os"
    ENV OTEL_SERVICE_NAME="ot-nodejs-demo"
    ENV NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
    EXPOSE 7001
    CMD ["node", "main.js"]
    EOF

    ngx_otel_module V0.1.1 or earlier

    cat << 'EOF' > backend/Dockerfile
    FROM node:20.16.0
    WORKDIR /app
    COPY package*.json ./
    RUN npm install
    COPY . .
    ENV OTEL_TRACES_EXPORTER="otlp"
    ENV OTEL_LOGS_EXPORTER=none
    ENV OTEL_METRICS_EXPORTER=none
    ENV OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc
    ENV OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://otel-collector:4317"
    ENV OTEL_NODE_RESOURCE_DETECTORS="env,host,os"
    ENV OTEL_SERVICE_NAME="ot-nodejs-demo"
    ENV NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
    EXPOSE 7001
    CMD ["node", "main.js"]
    EOF

Step 6: Create the configuration file of Docker Compose

The configuration file of Docker Compose defines the configurations of a multi-container application, including NGINX that serves as a reverse proxy, the OpenTelemetry Collector, and a Node.js backend service. This file also defines the network connections and port mappings between the components.

ngx_otel_module V0.1.2 or later

cat << 'EOF' > docker-compose.yml
version: "3"

services:
  nginx:
    image: nginx:1.27.5-alpine-otel # The default NGINX image that contains the ngx_otel_module V0.1.2.
    volumes:
      - ./nginx_conf/nginx.conf:/etc/nginx/nginx.conf:ro 
      - ./nginx_conf/default.conf:/etc/nginx/conf.d/default.conf:ro 
    ports:
      - "80:80"
    networks:
      - nginx-otel-demo

  backend-api:
    build:
      context: ./backend
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
    ports:
      - "7001:7001"
    networks:
      - nginx-otel-demo

networks:
  nginx-otel-demo:
    driver: bridge
EOF

ngx_otel_module V0.1.1 or earlier

cat << 'EOF' > docker-compose.yml
version: "3"

services:
  nginx:
    image: nginx:1.27.2-alpine-otel # The default NGINX image that contains the OpenTelemetry module.
    volumes:
      - ./nginx_conf/nginx.conf:/etc/nginx/nginx.conf:ro 
      - ./nginx_conf/default.conf:/etc/nginx/conf.d/default.conf:ro 
    ports:
      - "80:80"
    networks:
      - nginx-otel-demo

  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    volumes:
      - ./otel_conf/config.yaml:/etc/otelcol-contrib/config.yaml # Mount the configuration file for the OpenTelemetry Collector.
    ports:
      - "4317:4317" # OTLP gRPC receiver
    networks:
      - nginx-otel-demo

  backend-api:
    build:
      context: ./backend
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
    ports:
      - "7001:7001"
    networks:
      - nginx-otel-demo

networks:
  nginx-otel-demo:
    driver: bridge
EOF

Step 7: Start the service

  1. Run the following command in the nginx-otel-demo directory:

    docker compose up -d

    Expected output:

    ngx_otel_module V0.1.2 or later

    image

    ngx_otel_module V0.1.1 or earlier

    image (14).png

  2. Access the backend service.

    curl http://localhost:80/hello

    Expected output:

    {"code":200,"msg":"success"}
  3. Log on to the Managed Service for OpenTelemetry console to view the traces of NGINX and the backend service.

    In this example, nginx is displayed as the application name of NGINX on the Applications page, and the name of the backend service is ot-nodejs-demo.

FAQ

  1. What do I do if I fail to download nginx-module-otel with the error message "Unable to find a match: nginx-module-otel"?

    Check whether you have configured the NGINX package repository. If no, configure it by referring to nginx-otel.

  2. What do I do if I fail to start NGINX after I configure the ngx_otel_module in the configuration file of NGINX?

    Run the nginx -t command to check whether the NGINX configurations are valid, or view the error message in the NGINX logs.

    sudo tail -n 50 /var/log/nginx/error.log
  3. What do I do if no NGINX traces are available in the Managed Service for OpenTelemetry console after I enable the ngx_otel_module?

    Check whether the value of the otel_exporter.endpoint parameter is valid in the configuration file of NGINX. This endpoint consists of the IP address of the server on which the OpenTelemetry Collector is deployed and the port that the OpenTelemetry Collector uses to receive data reported over gRPC. Example: localhost:4317. You can check whether the configurations are valid by viewing the NGINX logs. If errors shown in the following figure are reported, the endpoint is invalid.

    image (15).png

  4. What do I do if the NGINX traces cannot be associated with those of another application?

    Check whether otel_trace_context propagate; is configured in the configuration file of NGINX, and whether the protocol that the application uses for trace context propagation is the same as the protocol used by NGINX. The ngx_otel_module uses the OpenTelemetry protocol and W3C specification for trace context propagation. Therefore, the NGINX traces can be associated with those of the application only if the application also uses the OpenTelemetry protocol and W3C specification for trace context propagation.

  5. Does the ngx_otel_module affect the NGINX performance?

    The ngx_otel_module is a native module of NGINX. According to the NGINX team, the impact of this module on the NGINX performance is limited to 10% to 15%. For more information, see NGINX Native OpenTelemetry (OTel) Module.

References