> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring Node.js traces with ClickHouse Observability

> Monitoring Node.js traces with ClickHouse Observability setup and configuration for ClickHouse Observability and self-managed deployments.

Capture traces from your Node.js application with OpenTelemetry automatic instrumentation and send them to ClickHouse Observability. Use the [demo dataset](#demo-dataset) to try the integration without instrumenting an application.

## Prerequisites

* A ClickHouse Observability service
* For your application, Node.js 22 or newer and npm
* For the demo, Docker and `curl`

### Connection details

> [tab] Fully managed
>
> [Beta offering](https://clickhouse.com/docs/reference/settings/beta-and-experimental-features.md#beta-features)
>
> Open ClickHouse Observability and go to **Team Settings → Data → Managed Telemetry**. Copy your OTLP HTTP endpoint and API key. You can use **Copy connection details** to copy the configuration, or **Reveal key** to view the masked key.
>
> ![Managed Telemetry connection details](https://mintcdn.com/private-7c7dfe99/Zk1feNn6fCQBpold/images/clickstack/getting-started/observability-managed-telemetry.png?fit=max\&auto=format\&n=Zk1feNn6fCQBpold\&q=85\&s=e63a2ac2e6ab996d3fc360ebe0f487a5)
>
> Set these connection variables in the terminal where you will run your application or demo collector:
>
> ```bash theme={null}
> export OTEL_EXPORTER_OTLP_ENDPOINT='https://YOUR_OTEL_ENDPOINT:4318'
> export OTEL_EXPORTER_OTLP_AUTHORIZATION='Bearer YOUR_API_KEY'
> ```
>
> Replace the placeholders with the exact endpoint, including its port, and API key from your service. Use the base HTTP endpoint without a `/v1/traces` suffix; the exporter appends the signal path.

> [tab] Self-managed
>
> Use your collector's reachable OTLP HTTP endpoint (for example, `http://YOUR_COLLECTOR_HOST:4318`) and authentication settings. If your collector does not require authentication, omit the exporter's `headers` block from the configurations below. See the [self-managed getting-started guide](https://clickhouse.com/docs/clickstack/self-configured/getting-started/managed.md) for setup guidance.
>
> ```bash theme={null}
> export OTEL_EXPORTER_OTLP_ENDPOINT='http://YOUR_COLLECTOR_HOST:4318'
> export OTEL_EXPORTER_OTLP_AUTHORIZATION='YOUR_INGESTION_KEY'
> ```

## Integration with an existing Node.js application

**1. Install OpenTelemetry**

From your application's directory, install the instrumentation packages:

```bash theme={null}
npm install @opentelemetry/api @opentelemetry/auto-instrumentations-node@0.81.0
```

These steps use [OpenTelemetry automatic instrumentation](https://opentelemetry.io/docs/zero-code/js/) for CommonJS applications. Native ES modules require the [ESM setup](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md). Use one instrumentation setup per application to avoid duplicate spans.

**2. Configure tracing and start your application**

In the terminal where you set the connection variables, run:

```bash theme={null}
export OTEL_SERVICE_NAME='nodejs-service'
export OTEL_TRACES_EXPORTER='otlp'
export OTEL_EXPORTER_OTLP_PROTOCOL='http/protobuf'
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=${OTEL_EXPORTER_OTLP_AUTHORIZATION}"
export OTEL_METRICS_EXPORTER='none'
export OTEL_LOGS_EXPORTER='none'

node --require @opentelemetry/auto-instrumentations-node/register app.js
```

Replace `app.js` with your application entry point. The preload initializes instrumentation before your application imports its libraries. For a self-managed endpoint without authentication, omit the headers export and run `unset OTEL_EXPORTER_OTLP_HEADERS`.

The endpoint must be reachable from the application. If it runs in a container, `localhost` refers to that container.

**3. Generate traffic**

Make requests to an endpoint your application serves. For an application listening on port `3000`:

```bash theme={null}
curl http://localhost:3000/
```

Allow a few seconds for the exporter to send the spans.

**4. Verify traces**

Open **Search**, select **Traces**, filter for `ServiceName:nodejs-service`, and select **Last 15 minutes**. Open a trace to inspect its spans, timing, and attributes.

## Demo dataset

The sample contains 822 spans from `nodejs-demo-api`. You do not need a running Node.js application.

**1. Download the sample dataset**

```bash theme={null}
curl -fLO https://datasets-documentation.s3.eu-west-3.amazonaws.com/clickstack-integrations/nodejs/nodejs-traces-sample.json
```

**2. Configure the demo collector**

Save the following as `nodejs-traces-demo.yaml` in the download directory:

```yaml theme={null}
receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 256
    spike_limit_mib: 64
  transform/demo_timestamps:
    error_mode: propagate
    trace_statements:
      - context: span
        statements:
          - set(cache["duration_ns"], end_time_unix_nano - start_time_unix_nano)
          - >-
            set(start_time,
              Now() - Duration("2m") -
              (Time("2025-10-27T17:59:15Z", "%Y-%m-%dT%H:%M:%SZ") - start_time)
            )
          - set(end_time_unix_nano, start_time_unix_nano + cache["duration_ns"])
  batch:
    timeout: 5s
    send_batch_size: 1024

exporters:
  otlp_http/observability:
    endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
    headers:
      authorization: "${env:OTEL_EXPORTER_OTLP_AUTHORIZATION}"

service:
  pipelines:
    traces/nodejs-demo:
      receivers: [otlp]
      processors: [memory_limiter, transform/demo_timestamps, batch]
      exporters: [otlp_http/observability]
```

> [!NOTE]
>
> The demo-only `transform/demo_timestamps` processor shifts this sample into roughly the past 24 hours, ending two minutes before ingestion, while preserving span durations and the traffic pattern. Omit this processor for your own Node.js traces so their original timestamps are preserved. Sending the sample again can produce duplicate spans.

**3. Run the demo collector**

> [!NOTE]
>
> For a destination collector running on this computer, set `OTEL_EXPORTER_OTLP_ENDPOINT` to `http://host.docker.internal:4318`. The command below includes the Docker host mapping.

Run OpenTelemetry Collector Contrib `0.161.0` from the directory containing the configuration, in the terminal where you set the connection variables. Keep this terminal open:

```bash theme={null}
docker run --rm --name nodejs-traces-demo-collector \
  --add-host=host.docker.internal:host-gateway \
  --memory=512m \
  -p 127.0.0.1:14318:4318 \
  -e OTEL_EXPORTER_OTLP_ENDPOINT \
  -e OTEL_EXPORTER_OTLP_AUTHORIZATION \
  -v "$(pwd)/nodejs-traces-demo.yaml:/etc/otelcol-contrib/config.yaml:ro" \
  otel/opentelemetry-collector-contrib:0.161.0 \
  --config=/etc/otelcol-contrib/config.yaml
```

The local receiver uses port `14318` to avoid conflicting with an existing collector on port `4318`. The collector forwards the traces to your configured endpoint using the authentication settings above.

**4. Send the traces**

In another terminal, from the download directory, send the original sample to the local collector:

```bash theme={null}
curl --fail-with-body -sS http://localhost:14318/v1/traces \
  -H "Content-Type: application/json" \
  --data-binary @nodejs-traces-sample.json
```

An empty success response such as `{}` or `{"partialSuccess":{}}` indicates the local collector accepted the request. Check the collector's output for export errors and allow a few seconds for the batch to reach your service. Stop the demo collector with **Ctrl+C** when finished.

**5. Verify the demo traces**

Open **Search**, select **Traces**, filter for `ServiceName:nodejs-demo-api`, and select **Last 2 days** to include the full shifted dataset. Open a trace to inspect the HTTP attributes.

![Node.js demo traces in ClickHouse Observability Search](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-nodejs-demo-traces.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=7e8d84a89134197f2ad6e65f4dcd8b8b)

## Dashboards and visualization

**1. [Download the dashboard configuration](https://clickhouse-docs-assets.s3.us-east-1.amazonaws.com/examples/nodejs-traces-dashboard.json)**

**2. Import the dashboard**

1. Open **Dashboards** and click **Import** in the upper-right corner.
2. Upload `nodejs-traces-dashboard.json`.
3. Map the charts to your **Traces** source and click **Finish Import**.

![Dashboards page with the Import button highlighted](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-import-dashboard.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=16bcb7e6365ca0f6decac5c693e228eb)

**3. View the dashboard**

For the sample, select **Last 2 days** and optionally filter for `ServiceName:nodejs-demo-api`. For your application, select its service name and a time range covering your requests.

The dashboard uses the sample's HTTP span attributes. Instrumentation versions can use different attribute names; adjust chart fields if your application's spans differ.

![Node.js traces dashboard showing requests, latency, endpoints, HTTP status codes, methods, and database queries](https://mintcdn.com/private-7c7dfe99/dW6bcEakZdn3a5oP/images/clickstack/observability-nodejs-traces-dashboard.png?fit=max\&auto=format\&n=dW6bcEakZdn3a5oP\&q=85\&s=f84b0350aeacd091ae80a4ed7019cea6)

## Troubleshooting

### No application traces appear

Check application output for export errors. Verify the endpoint, protocol, and authentication settings. Load instrumentation before application libraries, generate requests, and check the service-name filter and time range. For native ES modules, follow the linked ESM setup.

### Demo traces do not appear

Check the demo collector output for authentication or export errors. A successful `curl` response confirms local acceptance; allow a few seconds for forwarding to your service. Include `transform/demo_timestamps` in the pipeline and select **Last 2 days**. Resending the sample can create duplicates.

## Next steps

* Set up [alerts](https://clickhouse.com/docs/clickstack/observability/features/alerts.md) for errors and latency.
* Create additional [dashboards](https://clickhouse.com/docs/clickstack/observability/features/dashboards/overview.md).
