-
-
Notifications
You must be signed in to change notification settings - Fork 34.9k
otel: add new module #61907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
otel: add new module #61907
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3531,6 +3531,47 @@ added: v6.11.0 | |
|
|
||
| When set to `1`, process warnings are silenced. | ||
|
|
||
| ### `NODE_OTEL=value` | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| > Stability: 1 - Experimental | ||
|
|
||
| When set to a non-empty value, enables the built-in OpenTelemetry tracing | ||
| subsystem using the default collector endpoint (`http://localhost:4318`). Also | ||
| makes the `node:otel` module available without the `--experimental-otel` flag. | ||
| If `NODE_OTEL_ENDPOINT` is also set, it takes precedence for the endpoint. See | ||
| the [`node:otel`][] documentation for details. | ||
|
|
||
| ### `NODE_OTEL_ENDPOINT=url` | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| > Stability: 1 - Experimental | ||
|
|
||
| When set to a non-empty value, enables the built-in OpenTelemetry tracing | ||
| subsystem and directs spans to the specified OTLP/HTTP collector endpoint. The | ||
| `/v1/traces` path is appended automatically. Also makes the `node:otel` module | ||
|
Comment on lines
+3557
to
+3558
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a full URI with path is provided, then |
||
| available without the `--experimental-otel` flag. See the [`node:otel`][] | ||
| documentation for details. | ||
|
|
||
| ### `NODE_OTEL_FILTER=module[,…]` | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| > Stability: 1 - Experimental | ||
|
|
||
| Comma-separated list of core modules to instrument when OpenTelemetry tracing | ||
| is active. When not set, all supported modules are instrumented. Supported | ||
| values: `node:http`, `node:undici`, `node:fetch`. See the [`node:otel`][] | ||
| documentation for details. | ||
|
|
||
| ### `NODE_OPTIONS=options...` | ||
|
|
||
| <!-- YAML | ||
|
|
@@ -4240,6 +4281,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12 | |
| [`import.meta.url`]: esm.md#importmetaurl | ||
| [`import` specifier]: esm.md#import-specifiers | ||
| [`net.getDefaultAutoSelectFamilyAttemptTimeout()`]: net.md#netgetdefaultautoselectfamilyattempttimeout | ||
| [`node:otel`]: otel.md | ||
| [`node:sqlite`]: sqlite.md | ||
| [`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn | ||
| [`tls.DEFAULT_MAX_VERSION`]: tls.md#tlsdefault_max_version | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,235 @@ | ||
| # OpenTelemetry | ||
|
|
||
| <!--introduced_in=REPLACEME--> | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| > Stability: 1 - Experimental | ||
| <!-- source_link=lib/otel.js --> | ||
|
|
||
| The `node:otel` module provides built-in [OpenTelemetry][] tracing support for | ||
| Node.js core components. When enabled, it automatically creates spans for HTTP | ||
| server and client operations and exports them using the [OTLP/HTTP JSON][] | ||
| protocol. | ||
|
|
||
| To access it: | ||
|
|
||
| ```cjs | ||
| const otel = require('node:otel'); | ||
| ``` | ||
|
|
||
| ```mjs | ||
| import otel from 'node:otel'; | ||
| ``` | ||
|
|
||
| This module is only available under the `node:` scheme. It requires the | ||
| `--experimental-otel` CLI flag or one of the `NODE_OTEL` / `NODE_OTEL_ENDPOINT` | ||
| environment variables. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should clearly mention the limitations of the current state like
I guess a user has to decide to use either the one or the other OTel variant and avoid to use both in the same node.js process. |
||
|
|
||
| ## Activation | ||
|
|
||
| There are two ways to activate OpenTelemetry tracing: | ||
|
|
||
| ### Environment variables | ||
|
|
||
| Setting `NODE_OTEL=1` enables tracing with the default collector endpoint | ||
| (`http://localhost:4318`): | ||
|
|
||
| ```bash | ||
| NODE_OTEL=1 node app.js | ||
| ``` | ||
|
|
||
| To use a custom collector endpoint, set `NODE_OTEL_ENDPOINT` instead (or in | ||
| addition): | ||
|
|
||
| ```bash | ||
| NODE_OTEL_ENDPOINT=http://collector.example.com:4318 node app.js | ||
| ``` | ||
|
|
||
| Both variables also make the `node:otel` module available without requiring the | ||
| `--experimental-otel` flag. | ||
|
|
||
| ### Programmatic API | ||
|
|
||
| ```cjs | ||
| const otel = require('node:otel'); | ||
|
|
||
| // Start with the default endpoint (http://localhost:4318): | ||
| otel.start(); | ||
|
|
||
| // Or with a custom endpoint: | ||
| otel.start({ endpoint: 'http://collector.example.com:4318' }); | ||
|
|
||
| // ... application code ... | ||
| otel.stop(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More a style nit... feel free to ignore. I find this const stop = otel.start();
stop();which also allows for... {
using session = otel.start();
// automatically stops
}
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While |
||
| ``` | ||
|
|
||
| ## Environment variables | ||
|
|
||
| ### `NODE_OTEL` | ||
|
|
||
| When set to a non-empty value, enables the OpenTelemetry tracing subsystem | ||
| using the default collector endpoint (`http://localhost:4318`). If | ||
| `NODE_OTEL_ENDPOINT` is also set, it takes precedence. | ||
|
|
||
| ### `NODE_OTEL_ENDPOINT` | ||
|
|
||
| When set to a non-empty value, enables the OpenTelemetry tracing subsystem and | ||
| directs spans to the specified OTLP collector endpoint. The endpoint should be | ||
| the base URL of an | ||
| OTLP/HTTP collector (e.g. `http://localhost:4318`). The `/v1/traces` path is | ||
| appended automatically. | ||
|
|
||
| ### `NODE_OTEL_FILTER` | ||
|
|
||
| Accepts a comma-separated list of core modules to instrument. When not set, all | ||
| supported modules are instrumented. For example, setting | ||
| `NODE_OTEL_FILTER=node:http` would enable tracing only for the `node:http` | ||
| module. | ||
|
|
||
| Supported module filter values: | ||
|
|
||
| * `node:http` — HTTP server and client operations | ||
| * `node:undici` — Undici HTTP client operations | ||
| * `node:fetch` — Fetch API operations (alias for undici) | ||
|
|
||
| ### `OTEL_SERVICE_NAME` | ||
|
|
||
| Standard OpenTelemetry environment variable used to set the service name in | ||
| exported resource attributes. Defaults to `node-<pid>`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have to load the |
||
|
|
||
| ## `otel.start(options)` | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| * `options` {Object} | ||
| * `endpoint` {string} The OTLP collector endpoint URL. | ||
| **Default:** `'http://localhost:4318'`. | ||
| * `filter` {string|string\[]} Optional comma-separated string or array of | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: can we pick one? I'd prefer just
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the way it is for consistency with the environment variable. It could be an array here in the API and then comma-separated in the environment variable. |
||
| core module names to instrument (e.g. `['node:http']` or | ||
| `'node:http,node:undici'`). When omitted, all supported modules are | ||
| instrumented. | ||
| * `maxBufferSize` {number} Maximum number of spans buffered in memory before | ||
| triggering an immediate flush to the collector. Must be a positive integer. | ||
| **Default:** `100`. | ||
| * `flushInterval` {number} Interval in milliseconds between periodic flushes | ||
| of buffered spans to the collector. Must be a positive integer. | ||
| **Default:** `10000`. | ||
|
|
||
| Enables the OpenTelemetry tracing subsystem. Spans are created for supported | ||
| core module operations and exported to the specified collector using the | ||
| OTLP/HTTP JSON protocol. | ||
|
|
||
| If tracing is already active, calling `start()` will stop the current session | ||
| and start a new one with the provided options. | ||
|
|
||
| ## `otel.stop()` | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| Disables the OpenTelemetry tracing subsystem. Any buffered spans are sent to | ||
| the collector before stopping. Because the export is asynchronous, delivery is | ||
| not confirmed before `stop()` returns. After calling `stop()`, no new spans are | ||
| created. | ||
|
|
||
| Calling `stop()` when tracing is not active is a no-op. | ||
|
|
||
| ## `otel.active` | ||
|
|
||
| <!-- YAML | ||
| added: REPLACEME | ||
| --> | ||
|
|
||
| * {boolean} | ||
|
|
||
| Returns `true` if the OpenTelemetry tracing subsystem is currently active. | ||
|
|
||
| ## Instrumented operations | ||
|
|
||
| When tracing is active, spans are automatically created for the following | ||
| operations: | ||
|
|
||
| ### HTTP server | ||
|
|
||
| A span with kind `SERVER` is created for each incoming HTTP request. The span | ||
| starts when the request is received and ends when the response finishes. If the | ||
| client disconnects before the response completes, the span ends with an error | ||
| status. | ||
|
|
||
| Server spans receive error status (`STATUS_ERROR`) for 5xx response codes. 4xx | ||
| responses are not treated as server errors per OpenTelemetry semantic | ||
| conventions. | ||
|
|
||
| Attributes set on server spans: | ||
|
|
||
| | Attribute | Description | Condition | | ||
| | --------------------------- | -------------------------------- | ----------------------------- | | ||
| | `http.request.method` | HTTP method (e.g. `GET`, `POST`) | Always | | ||
| | `url.path` | Request URL path (without query) | Always | | ||
| | `url.query` | Query string (without `?`) | When query string is present | | ||
| | `url.scheme` | `http` or `https` | Always | | ||
| | `server.address` | Host header value | When `Host` header is present | | ||
| | `network.protocol.version` | HTTP version (e.g. `1.1`) | Always | | ||
| | `http.response.status_code` | Response status code | When response finishes | | ||
| | `error.type` | HTTP status code as string | On 5xx responses | | ||
|
|
||
| ### HTTP client | ||
|
|
||
| A span with kind `CLIENT` is created for each outgoing HTTP request made via | ||
| `node:http`. The span starts when the request is created and ends when the | ||
| response finishes or an error occurs. | ||
|
|
||
| Client spans receive error status (`STATUS_ERROR`) for 4xx and 5xx response | ||
| codes. On connection errors, an `exception` event is added to the span with | ||
| `exception.type`, `exception.message`, and `exception.stacktrace` attributes. | ||
|
|
||
| Attributes set on client spans: | ||
|
|
||
| | Attribute | Description | Condition | | ||
| | --------------------------- | ------------------------- | ------------------------- | | ||
| | `http.request.method` | HTTP method | Always | | ||
| | `url.full` | Full request URL | Always | | ||
| | `server.address` | Target host | Always | | ||
| | `server.port` | Target port | When available | | ||
| | `http.response.status_code` | Response status code | When response is received | | ||
| | `network.protocol.version` | HTTP version | When response is received | | ||
| | `error.type` | Status code or error name | On 4xx/5xx or errors | | ||
|
|
||
| ### Undici/Fetch client | ||
|
|
||
| A span with kind `CLIENT` is created for each outgoing request made via | ||
| `fetch()` or undici's `request()`. | ||
|
|
||
| Error status and `exception` event behavior is the same as for HTTP client | ||
| spans above. | ||
|
|
||
| Attributes set on undici/fetch client spans: | ||
|
|
||
| | Attribute | Description | Condition | | ||
| | --------------------------- | ------------------------- | ------------------------- | | ||
| | `http.request.method` | HTTP method | Always | | ||
| | `url.full` | Full request URL | Always | | ||
| | `server.address` | Target origin | Always | | ||
| | `http.response.status_code` | Response status code | When response is received | | ||
| | `error.type` | Status code or error name | On 4xx/5xx or errors | | ||
|
|
||
| ## W3C Trace Context propagation | ||
|
|
||
| The tracing subsystem automatically propagates [W3C Trace Context][] across HTTP | ||
| boundaries: | ||
|
|
||
| * **Incoming requests**: The `traceparent` header is read from incoming HTTP | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should either include There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With |
||
| requests. Child spans created during request processing inherit the trace ID. | ||
| * **Outgoing requests**: The `traceparent` header is injected into outgoing HTTP | ||
| and undici/fetch requests, enabling distributed tracing across services. | ||
|
|
||
| [OTLP/HTTP JSON]: https://opentelemetry.io/docs/specs/otlp/#otlphttp | ||
| [OpenTelemetry]: https://opentelemetry.io/ | ||
| [W3C Trace Context]: https://www.w3.org/TR/trace-context/ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
really any value? e.g. having
NODE_OTEL=disableorNODE_OTEL=0to enable it seems a bit uncommon.Quite some other node env vars check on the value
1.