Node.js
Collect Node.js/V8 runtime and HTTP metrics from your services and get curated dashboards and alerts for them with a single import.
Node.js apps instrumented with the OpenTelemetry SDK export their metrics over OTLP to your LeanSignal agent gateway (one per cluster or environment) — never to a remote or third-party endpoint. The gateway keeps full fidelity locally and forwards only the demanded subset to your central dataplane. This integration covers the Node/V8 runtime (event-loop utilization and delay, V8 heap, GC pauses) plus HTTP server request metrics.
Metric names follow the standard OTLP → Prometheus normalization (dots become
underscores, unit/_total suffixes are added), so nodejs.eventloop.utilization
becomes nodejs_eventloop_utilization and http.server.request.duration becomes
http_server_request_duration_seconds. The demands below are built against those
names.
Prerequisites
Section titled “Prerequisites”- A LeanSignal agent gateway deployed and connected — one per cluster or
environment. If you haven’t deployed it yet, follow
Install the agent (source:
LeanSignal/leansignal-agent). It should show as Connected under Agents in the LeanSignal app. - Network reachability to the gateway’s OTLP port —
4317(gRPC) or4318(HTTP). See Agent configuration. - Your Node.js app instrumented with the OpenTelemetry SDK, exporting metrics over OTLP to the gateway — configured in Setup.
- Editor or admin role in the LeanSignal app (importing a demand creates dashboards and alert rules).
Install the SDK, HTTP auto-instrumentation, the runtime instrumentation, and the
OTLP exporters for all three signals, then point the SDK at your LeanSignal
agent gateway (OTLP gRPC :4317 / HTTP :4318) — not a SaaS endpoint.
npm i @opentelemetry/sdk-node @opentelemetry/sdk-metrics \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/instrumentation-runtime-node \ @opentelemetry/exporter-metrics-otlp-grpc \ @opentelemetry/exporter-trace-otlp-grpc \ @opentelemetry/api-logs @opentelemetry/sdk-logs \ @opentelemetry/exporter-logs-otlp-grpcexport OTEL_EXPORTER_OTLP_ENDPOINT="http://<gateway-host>:4317"export OTEL_SERVICE_NAME="my-node-service"export OTEL_SEMCONV_STABILITY_OPT_IN="http" # emit stable http.server.request.durationCreate instrument.js and load it before your app:
const { NodeSDK } = require('@opentelemetry/sdk-node');const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc');const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');const { RuntimeNodeInstrumentation } = require('@opentelemetry/instrumentation-runtime-node');
const sdk = new NodeSDK({ metricReader: new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter() }), instrumentations: [ getNodeAutoInstrumentations(), // includes instrumentation-http new RuntimeNodeInstrumentation({ monitoringPrecision: 5000 }), ],});sdk.start();node -r ./instrument.js app.js # or --import for ESMLogs and traces
Section titled “Logs and traces”The SDK bootstrap from Setup wires a metric reader; the same
NodeSDK carries traces and logs to the gateway too — the exporter packages
are already on the install line above. Extend instrument.js:
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-grpc');const { BatchLogRecordProcessor } = require('@opentelemetry/sdk-logs');
const sdk = new NodeSDK({ // …metricReader and instrumentations from Setup… traceExporter: new OTLPTraceExporter(), logRecordProcessors: [new BatchLogRecordProcessor(new OTLPLogExporter())],});-
Traces — with the trace exporter in place, the auto-instrumentations do the rest: inbound HTTP requests and outbound calls emit spans with no further code.
-
Logs —
getNodeAutoInstrumentations()already includes the@opentelemetry/instrumentation-pinoand-winstonbridges, so once the log record processor is registered your existing logger is exported as-is:const logger = require('pino')();logger.info('hello'); // also exported to the gateway as an OTLP log recordOr keep logging to stdout and ship files with a collector or shipper instead.
See the Node.js OpenTelemetry docs.
Demands
Section titled “Demands”Node.js ships as a ready-made demand in three variants. You don’t copy any JSON — in the LeanSignal app go to Demands, press the ˅ arrow on the Add Demand button (the arrow opens the import menu), choose Import from catalog…, and pick the variant. Each variant below lists the slug that identifies its published bundle. See Integrations for the full import flow.
The variants are nested — Standard is a superset of Essential, Extended a superset of Standard. Pick whichever is closest to what you need and treat it as a starting point: after import everything is a normal, editable copy, so retune thresholds, add or drop panels, and adjust queries for your environment — your edits reshape the demand automatically. Start small and re-import a larger variant later if you outgrow it.
The golden signals. 1 dashboard · 4 panels · 3 alerts — traffic, errors, latency, and event-loop saturation at a glance.
Import this variant from the catalog. Its demand slug:
nodejs-otel-demand-essentialDashboard — HTTP request rate, HTTP 5xx error rate, HTTP request duration p95, and Event-loop utilization.
Alerts (3)
| Alert | Severity | Fires when |
|---|---|---|
| High HTTP 5xx error rate | critical | 5xx ratio > 5% for 5m |
| High HTTP p95 latency | warning | p95 latency > 1s for 5m |
| Event-loop saturated | critical | ELU > 90% for 5m |
Well-rounded runtime coverage. 1 dashboard · 8 panels · 6 alerts — adds event-loop delay, V8 heap, and GC pauses. The recommended default.
Import this variant from the catalog. Its demand slug:
nodejs-otel-demand-standardDashboard — everything in Essential, plus Event-loop delay p99, V8 heap used, V8 heap utilization, and GC pause duration p95.
Alerts (6)
| Alert | Severity | Fires when |
|---|---|---|
| High HTTP 5xx error rate | critical | 5xx ratio > 5% for 5m |
| High HTTP p95 latency | warning | p95 latency > 1s for 5m |
| Event-loop saturated | critical | ELU > 90% for 5m |
| High event-loop delay | warning | p99 loop delay > 100ms for 5m |
| V8 heap near limit | critical | post-GC heap floor > 90% of pre-allocated for 5m |
| High GC pause duration | warning | p95 GC pause > 100ms for 10m |
Deep runtime visibility. 1 dashboard · 14 panels · 10 alerts — per-route traffic, heap spaces, and GC breakdowns for services you need to diagnose, not just watch.
Import this variant from the catalog. Its demand slug:
nodejs-otel-demand-extendedDashboard — everything in Standard, plus HTTP request duration p99, HTTP request rate by route, Event-loop delay p50, V8 heap used by space, V8 heap limit (pre-allocated), and GC collections by type.
Alerts (10)
| Alert | Severity | Fires when |
|---|---|---|
| High HTTP 5xx error rate | critical | 5xx ratio > 5% for 5m |
| High HTTP p95 latency | warning | p95 latency > 1s for 5m |
| Event-loop saturated | critical | ELU > 90% for 5m |
| High event-loop delay | warning | p99 loop delay > 100ms for 5m |
| V8 heap near limit | critical | post-GC heap floor > 90% of pre-allocated for 5m |
| High GC pause duration | warning | p95 GC pause > 100ms for 10m |
| Critical HTTP p99 latency | critical | p99 latency > 3s for 5m |
| Elevated HTTP 4xx rate | warning | 4xx ratio > 30% for 10m |
| Elevated event-loop utilization | warning | ELU > 70% for 10m |
| Sustained heap growth | warning | heap +256 MiB over 30m for 15m |
Dashboards
Section titled “Dashboards”Each variant imports one Node.js dashboard, its panels grouped into
collapsible sections. Every dashboard carries an Instance filter (on the
instance label), so one import covers the whole fleet — view every instance
at once, or focus on one. Legends are sortable tables showing last/mean/max per
series, so the outlier instance stands out. Dashboards are demand-driven:
importing one tells your agents to forward exactly the timeseries its panels
query, and nothing else. Panels are ordinary Perses panels — edit queries, add
panels, or retune them after import, and your changes reshape the demand
automatically.
Alerts
Section titled “Alerts”Thresholds are conservative starting points — tune them to your workload.
Next steps
Section titled “Next steps”- Demand-driven observability — why importing a demand also shapes what your agents collect.
- Agent configuration — the full agent config surface.
Thanks for your feedback!
Report sent — thank you!