From 602e6e13c6f3b4b1ce0d116de58d1306da230553 Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:23:09 +0800 Subject: [PATCH 1/8] docs: add privacy and span attribute config options for OpenTelemetry plugin Document the new headersToSpanAttributes, spanUrlRedaction, recordBody, and checkIfShouldTrace options introduced in elysiajs/opentelemetry#74. Adds a "Privacy and span attributes" usage section to the patterns page with migration tips for the breaking change (headers no longer recorded by default). Made-with: Cursor --- docs/patterns/opentelemetry.md | 84 +++++++++++++++++++++++++ docs/plugins/opentelemetry.md | 111 +++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/docs/patterns/opentelemetry.md b/docs/patterns/opentelemetry.md index b4ad1b75..7146048b 100644 --- a/docs/patterns/opentelemetry.md +++ b/docs/patterns/opentelemetry.md @@ -152,6 +152,90 @@ function utility() { This is a syntax sugar for `getCurrentSpan().setAttributes` +## Privacy and span attributes + +By default the plugin follows the [OpenTelemetry HTTP semantic conventions](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) guidance: no request or response headers are recorded, sensitive query parameters and URL credentials are redacted, and body content is omitted. + +### Controlling which headers appear in spans + +Pass `headersToSpanAttributes` to opt-in to recording specific request or response headers: + +```typescript +import { Elysia } from 'elysia' +import { opentelemetry } from '@elysiajs/opentelemetry' + +new Elysia().use( + opentelemetry({ + headersToSpanAttributes: { + requestHeaders: ['content-type', 'x-request-id'], + responseHeaders: ['content-type'] + } + }) +) +``` + +Use `['*']` to capture all headers (handy during development): + +```typescript +opentelemetry({ + headersToSpanAttributes: { + requestHeaders: ['*'] + } +}) +``` + +::: tip Migration +Previous versions recorded every header by default. If you are upgrading and need the old behavior, set `requestHeaders: ['*']` and `responseHeaders: ['*']`. +::: + +### URL redaction + +URL redaction is enabled by default. Known sensitive query keys such as `token`, `password`, `secret`, `api_key` and others are replaced with `[REDACTED]`, and `user:pass@` credentials are stripped from `url.full`. + +You can add your own keys or disable redaction entirely: + +```typescript +// Add custom sensitive keys +opentelemetry({ + spanUrlRedaction: { + sensitiveQueryParams: ['session_token'] + } +}) + +// Disable redaction (not recommended in production) +opentelemetry({ + spanUrlRedaction: false +}) +``` + +### Recording request and response bodies + +Body content is not recorded by default. Opt in with `recordBody`: + +```typescript +// Record both request and response bodies +opentelemetry({ + recordBody: true +}) + +// Record only request bodies +opentelemetry({ + recordBody: { request: true } +}) +``` + +Body serialization is wrapped in a try/catch so circular structures or BigInt values produce `[Unserializable]` instead of crashing the tracing path. + +### Skipping traces for specific requests + +Use `checkIfShouldTrace` to skip tracing for health checks, readiness probes, or other endpoints you don't want to trace: + +```typescript +opentelemetry({ + checkIfShouldTrace: (req) => !req.url.includes('/health') +}) +``` + ## Configuration See [opentelemetry plugin](/plugins/opentelemetry) for configuration option and definition. diff --git a/docs/plugins/opentelemetry.md b/docs/plugins/opentelemetry.md index cdf8f64c..f19bee2a 100644 --- a/docs/plugins/opentelemetry.md +++ b/docs/plugins/opentelemetry.md @@ -123,3 +123,114 @@ If an exporter OR span processor is not configured programmatically, this packag ### spanLimits - SpanLimits Configure tracing parameters. These are the same trace parameters used to configure a tracer. + +### checkIfShouldTrace - (req: Request) => boolean +Optional function to determine whether a given request should be traced. + +```typescript +opentelemetry({ + checkIfShouldTrace: (req) => !req.url.includes('/health') +}) +``` + +### headersToSpanAttributes +HTTP header names (case-insensitive) to capture as span attributes. + +```typescript +headersToSpanAttributes?: { + requestHeaders?: string[] + responseHeaders?: string[] +} +``` + +- Header names are **case-insensitive**. +- Use `"*"` in either list to capture **all** headers — useful for development but may include sensitive values. +- Including `"cookie"` in `requestHeaders` also emits `http.request.cookie` when `context.cookie` is present. + +default: `undefined` (no headers recorded) + +::: warning +This is a **breaking change** from previous versions where all headers were recorded by default. To restore the old behavior, use: + +```typescript +opentelemetry({ + headersToSpanAttributes: { + requestHeaders: ['*'], + responseHeaders: ['*'] + } +}) +``` +::: + +**Example: capture specific headers** + +```typescript +opentelemetry({ + headersToSpanAttributes: { + requestHeaders: ['content-type', 'accept', 'x-request-id'], + responseHeaders: ['content-type'] + } +}) +``` + +### spanUrlRedaction +Redact credentials and sensitive query parameter values from `url.full` and `url.query` span attributes. + +```typescript +spanUrlRedaction?: false | { + stripCredentials?: boolean + sensitiveQueryParams?: string[] +} +``` + +- **Default (omitted):** redacts values of known sensitive query keys (`token`, `password`, `secret`, `api_key`, etc.) to `[REDACTED]`, and strips `user:pass@` credentials from `url.full`. +- `false`: disables all URL redaction (raw URLs recorded as-is). +- `{ stripCredentials: false }`: keeps credentials in URLs while still redacting sensitive query params. +- `{ sensitiveQueryParams: ['my-key'] }`: adds custom keys to the builtin set. + +default: enabled (redacts sensitive query params and strips credentials) + +**Example: add custom sensitive params** + +```typescript +opentelemetry({ + spanUrlRedaction: { + sensitiveQueryParams: ['session_token', 'private_key'] + } +}) +``` + +### recordBody +Record request and/or response body content on spans. + +```typescript +recordBody?: boolean | { + request?: boolean + response?: boolean +} +``` + +- `true`: record both request and response bodies (`http.request.body`, `http.response.body`, and their `.size` counterparts). +- `{ request: true }` or `{ response: true }`: record only one side. +- `false` / omitted: no body content recorded. + +default: `false` + +::: warning +Body recording can produce large span attributes. Use selectively, especially in production environments. +::: + +**Example: record request bodies only** + +```typescript +opentelemetry({ + recordBody: { request: true } +}) +``` + +## Always-on attributes + +The following standard [OpenTelemetry HTTP semantic convention](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) attributes are **always emitted** when their respective headers are present, and do not require any configuration: + +- `user_agent.original` — from the `User-Agent` request header +- `http.request_content_length` — from the `Content-Length` request header From 1452cd562d438696728d59c67c79f9b382f90a45 Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:26:36 +0800 Subject: [PATCH 2/8] docs: remove implementation detail about body serialization try/catch Made-with: Cursor --- docs/patterns/opentelemetry.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/patterns/opentelemetry.md b/docs/patterns/opentelemetry.md index 7146048b..24b05340 100644 --- a/docs/patterns/opentelemetry.md +++ b/docs/patterns/opentelemetry.md @@ -224,8 +224,6 @@ opentelemetry({ }) ``` -Body serialization is wrapped in a try/catch so circular structures or BigInt values produce `[Unserializable]` instead of crashing the tracing path. - ### Skipping traces for specific requests Use `checkIfShouldTrace` to skip tracing for health checks, readiness probes, or other endpoints you don't want to trace: From 09b97df23e36d6fef431d922d342967bed892e10 Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:28:09 +0800 Subject: [PATCH 3/8] docs: remove checkIfShouldTrace (pre-existing), fold privacy into Configuration section checkIfShouldTrace was not introduced by PR #74 so it doesn't belong here. Move the privacy/header/body/URL content under the existing Configuration section on the patterns page instead of a separate top-level section. Made-with: Cursor --- docs/patterns/opentelemetry.md | 18 +++--------------- docs/plugins/opentelemetry.md | 9 --------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/docs/patterns/opentelemetry.md b/docs/patterns/opentelemetry.md index 24b05340..a808c55b 100644 --- a/docs/patterns/opentelemetry.md +++ b/docs/patterns/opentelemetry.md @@ -152,7 +152,9 @@ function utility() { This is a syntax sugar for `getCurrentSpan().setAttributes` -## Privacy and span attributes +## Configuration + +See [opentelemetry plugin](/plugins/opentelemetry) for all configuration options. By default the plugin follows the [OpenTelemetry HTTP semantic conventions](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) guidance: no request or response headers are recorded, sensitive query parameters and URL credentials are redacted, and body content is omitted. @@ -224,20 +226,6 @@ opentelemetry({ }) ``` -### Skipping traces for specific requests - -Use `checkIfShouldTrace` to skip tracing for health checks, readiness probes, or other endpoints you don't want to trace: - -```typescript -opentelemetry({ - checkIfShouldTrace: (req) => !req.url.includes('/health') -}) -``` - -## Configuration - -See [opentelemetry plugin](/plugins/opentelemetry) for configuration option and definition. - ## Instrumentations Advanced Concept Many instrumentation libraries required that the SDK **MUST** run before importing the module. diff --git a/docs/plugins/opentelemetry.md b/docs/plugins/opentelemetry.md index f19bee2a..0278b4ba 100644 --- a/docs/plugins/opentelemetry.md +++ b/docs/plugins/opentelemetry.md @@ -124,15 +124,6 @@ If an exporter OR span processor is not configured programmatically, this packag ### spanLimits - SpanLimits Configure tracing parameters. These are the same trace parameters used to configure a tracer. -### checkIfShouldTrace - (req: Request) => boolean -Optional function to determine whether a given request should be traced. - -```typescript -opentelemetry({ - checkIfShouldTrace: (req) => !req.url.includes('/health') -}) -``` - ### headersToSpanAttributes HTTP header names (case-insensitive) to capture as span attributes. From 6c2f789070aff34e147734fc824c4b1275d344bd Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:29:28 +0800 Subject: [PATCH 4/8] docs: restore original Configuration section text Made-with: Cursor --- docs/patterns/opentelemetry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/patterns/opentelemetry.md b/docs/patterns/opentelemetry.md index a808c55b..a8890862 100644 --- a/docs/patterns/opentelemetry.md +++ b/docs/patterns/opentelemetry.md @@ -154,7 +154,7 @@ This is a syntax sugar for `getCurrentSpan().setAttributes` ## Configuration -See [opentelemetry plugin](/plugins/opentelemetry) for all configuration options. +See [opentelemetry plugin](/plugins/opentelemetry) for configuration option and definition. By default the plugin follows the [OpenTelemetry HTTP semantic conventions](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) guidance: no request or response headers are recorded, sensitive query parameters and URL credentials are redacted, and body content is omitted. From c629fe78aa6a279f018075963030c8ae9356b5dd Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:30:41 +0800 Subject: [PATCH 5/8] docs: remove duplicated config content from patterns page The plugin config reference page is the single source of truth for headersToSpanAttributes, spanUrlRedaction, and recordBody options. No need to repeat it on the patterns page. Made-with: Cursor --- docs/patterns/opentelemetry.md | 70 ---------------------------------- 1 file changed, 70 deletions(-) diff --git a/docs/patterns/opentelemetry.md b/docs/patterns/opentelemetry.md index a8890862..b4ad1b75 100644 --- a/docs/patterns/opentelemetry.md +++ b/docs/patterns/opentelemetry.md @@ -156,76 +156,6 @@ This is a syntax sugar for `getCurrentSpan().setAttributes` See [opentelemetry plugin](/plugins/opentelemetry) for configuration option and definition. -By default the plugin follows the [OpenTelemetry HTTP semantic conventions](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) guidance: no request or response headers are recorded, sensitive query parameters and URL credentials are redacted, and body content is omitted. - -### Controlling which headers appear in spans - -Pass `headersToSpanAttributes` to opt-in to recording specific request or response headers: - -```typescript -import { Elysia } from 'elysia' -import { opentelemetry } from '@elysiajs/opentelemetry' - -new Elysia().use( - opentelemetry({ - headersToSpanAttributes: { - requestHeaders: ['content-type', 'x-request-id'], - responseHeaders: ['content-type'] - } - }) -) -``` - -Use `['*']` to capture all headers (handy during development): - -```typescript -opentelemetry({ - headersToSpanAttributes: { - requestHeaders: ['*'] - } -}) -``` - -::: tip Migration -Previous versions recorded every header by default. If you are upgrading and need the old behavior, set `requestHeaders: ['*']` and `responseHeaders: ['*']`. -::: - -### URL redaction - -URL redaction is enabled by default. Known sensitive query keys such as `token`, `password`, `secret`, `api_key` and others are replaced with `[REDACTED]`, and `user:pass@` credentials are stripped from `url.full`. - -You can add your own keys or disable redaction entirely: - -```typescript -// Add custom sensitive keys -opentelemetry({ - spanUrlRedaction: { - sensitiveQueryParams: ['session_token'] - } -}) - -// Disable redaction (not recommended in production) -opentelemetry({ - spanUrlRedaction: false -}) -``` - -### Recording request and response bodies - -Body content is not recorded by default. Opt in with `recordBody`: - -```typescript -// Record both request and response bodies -opentelemetry({ - recordBody: true -}) - -// Record only request bodies -opentelemetry({ - recordBody: { request: true } -}) -``` - ## Instrumentations Advanced Concept Many instrumentation libraries required that the SDK **MUST** run before importing the module. From f95a214267262715d55abb26ad093b4f9fb8b469 Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:31:50 +0800 Subject: [PATCH 6/8] docs: remove breaking change warning from config reference Migration notes belong in release notes, not the docs site. Made-with: Cursor --- docs/plugins/opentelemetry.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/plugins/opentelemetry.md b/docs/plugins/opentelemetry.md index 0278b4ba..155e88b9 100644 --- a/docs/plugins/opentelemetry.md +++ b/docs/plugins/opentelemetry.md @@ -140,19 +140,6 @@ headersToSpanAttributes?: { default: `undefined` (no headers recorded) -::: warning -This is a **breaking change** from previous versions where all headers were recorded by default. To restore the old behavior, use: - -```typescript -opentelemetry({ - headersToSpanAttributes: { - requestHeaders: ['*'], - responseHeaders: ['*'] - } -}) -``` -::: - **Example: capture specific headers** ```typescript From 8f6dd01f1d291dc822e57b947524bd4402241d9b Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:33:11 +0800 Subject: [PATCH 7/8] docs: remove always-on attributes section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not actionable for users — these are emitted automatically and don't need to be documented in the config reference. Made-with: Cursor --- docs/plugins/opentelemetry.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/plugins/opentelemetry.md b/docs/plugins/opentelemetry.md index 155e88b9..ab1dcdf2 100644 --- a/docs/plugins/opentelemetry.md +++ b/docs/plugins/opentelemetry.md @@ -205,10 +205,3 @@ opentelemetry({ recordBody: { request: true } }) ``` - -## Always-on attributes - -The following standard [OpenTelemetry HTTP semantic convention](https://opentelemetry.io/docs/specs/semconv/http/http-spans/) attributes are **always emitted** when their respective headers are present, and do not require any configuration: - -- `user_agent.original` — from the `User-Agent` request header -- `http.request_content_length` — from the `Content-Length` request header From 89e69ea3d370e5af20596a7793533248d9e8e082 Mon Sep 17 00:00:00 2001 From: turisanapo Date: Sun, 12 Apr 2026 10:34:18 +0800 Subject: [PATCH 8/8] =?UTF-8?q?docs:=20fix=20'builtin'=20=E2=86=92=20'buil?= =?UTF-8?q?t-in'=20hyphenation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- docs/plugins/opentelemetry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/opentelemetry.md b/docs/plugins/opentelemetry.md index ab1dcdf2..597bce17 100644 --- a/docs/plugins/opentelemetry.md +++ b/docs/plugins/opentelemetry.md @@ -164,7 +164,7 @@ spanUrlRedaction?: false | { - **Default (omitted):** redacts values of known sensitive query keys (`token`, `password`, `secret`, `api_key`, etc.) to `[REDACTED]`, and strips `user:pass@` credentials from `url.full`. - `false`: disables all URL redaction (raw URLs recorded as-is). - `{ stripCredentials: false }`: keeps credentials in URLs while still redacting sensitive query params. -- `{ sensitiveQueryParams: ['my-key'] }`: adds custom keys to the builtin set. +- `{ sensitiveQueryParams: ['my-key'] }`: adds custom keys to the built-in set. default: enabled (redacts sensitive query params and strips credentials)