feat: upgrade to OpenTelemetry 2.x and capture exception source automatically - #31
Open
bhogayatakb wants to merge 1 commit into
Open
feat: upgrade to OpenTelemetry 2.x and capture exception source automatically#31bhogayatakb wants to merge 1 commit into
bhogayatakb wants to merge 1 commit into
Conversation
…atically
Express users currently have to register an error handler by hand to get
exception code capture, and even then only Express is covered. This moves
the capture into the SDK so it works for every instrumentation, and lifts
the OTel dependencies to 2.x to make that possible.
Why the upgrade is required
---------------------------
instrumentation-express 0.42 (pinned by auto-instrumentations 0.50) ends a
route handler's layer span *before* invoking the handler, so its own
recordException lands on an ended span and is dropped. Nothing records a
route-handler throw, which is why registerErrorHandler exists. Upstream
fixed this in instrumentation-express 0.48, which depends on OTel 2.x core
and so cannot be taken on its own.
Exception source capture
------------------------
NodeSDK's traceExporter is replaced by an explicit spanProcessors array so
@middleware.io/otel-extensions can enrich exception events with
exception.stack_details before export. NodeSDK wrapped traceExporter in
exactly this BatchSpanProcessor, so batching and OTEL_BSP_* are unchanged.
errorhandler.ts drops its hand-rolled stack parsing (~60 lines) for a plain
span.recordException; the processor produces a superset of the same keys,
plus source-map resolution, whole-function capture instead of a fixed +/-10
line window, correct 1-based start_line/end_line, and node_modules frames
trimmed to location only. The handler and its docs step are kept for now --
removal is a public API change and a separate decision.
Dependency and API changes
--------------------------
17 OTel packages moved to 2.x (sdk-node 0.53 -> 0.222, sdk-trace-* /
resources / core 1.26 -> 2.11, auto-instrumentations 0.50 -> 0.80):
- Detector/DetectorSync -> ResourceDetector; *DetectorSync lost the suffix
- new Resource(attrs) -> resourceFromAttributes(attrs)
- LoggerProvider.addLogRecordProcessor removed; processors are
constructor-only, and BatchLogRecordProcessor now takes { exporter }
- ResourceAttributes type removed -> Attributes from @opentelemetry/api
engines is set to OTel 2.x's own range, ^18.19.0 || >=20.6.0. Node 14 and 16
users should move to @middleware.io/node-apm-legacy.
Instrumentation coverage
------------------------
auto-instrumentations 0.80 no longer bundles instrumentation-fastify, so it
is carried as a direct dependency and registered explicitly, honouring the
existing "fastify" disable key. The package is deprecated upstream in favour
of @fastify/otel; migrating is follow-up work.
instrumentation-redis-4 merged into instrumentation-redis; the "redis-client"
disable key now points there and keeps working.
Express 5 moved routing into the standalone `router` package, which has its
own instrumentation in the bundle. With both active every layer is traced
twice and every exception recorded on each copy -- measured at 22 spans and
3 exception events over 3 requests, against 11 and 1 with router off, with
identical routes, middleware, http.route and enriched exception. Router
instrumentation is now disabled when express is resolvable; apps using
`router` directly still get it, and "router" is a recognised disable key.
Verified
--------
Express 5 route-handler throw with no error handler registered now yields
exception.stack_details with 8 frames, 3 carrying source. Express 4 behaves
identically. Logs, metrics (including opentelemetry-node-metrics against
sdk-metrics 2.x) and vcs.* resource attributes all confirmed working. Build
clean, 24 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…atically
Express users currently have to register an error handler by hand to get exception code capture, and even then only Express is covered. This moves the capture into the SDK so it works for every instrumentation, and lifts the OTel dependencies to 2.x to make that possible.
Why the upgrade is required
instrumentation-express 0.42 (pinned by auto-instrumentations 0.50) ends a route handler's layer span before invoking the handler, so its own recordException lands on an ended span and is dropped. Nothing records a route-handler throw, which is why registerErrorHandler exists. Upstream fixed this in instrumentation-express 0.48, which depends on OTel 2.x core and so cannot be taken on its own.
Exception source capture
NodeSDK's traceExporter is replaced by an explicit spanProcessors array so @middleware.io/otel-extensions can enrich exception events with exception.stack_details before export. NodeSDK wrapped traceExporter in exactly this BatchSpanProcessor, so batching and OTEL_BSP_* are unchanged.
errorhandler.ts drops its hand-rolled stack parsing (~60 lines) for a plain span.recordException; the processor produces a superset of the same keys, plus source-map resolution, whole-function capture instead of a fixed +/-10 line window, correct 1-based start_line/end_line, and node_modules frames trimmed to location only. The handler and its docs step are kept for now -- removal is a public API change and a separate decision.
Dependency and API changes
17 OTel packages moved to 2.x (sdk-node 0.53 -> 0.222, sdk-trace-* / resources / core 1.26 -> 2.11, auto-instrumentations 0.50 -> 0.80):
engines is set to OTel 2.x's own range, ^18.19.0 || >=20.6.0. Node 14 and 16 users should move to @middleware.io/node-apm-legacy.
Instrumentation coverage
auto-instrumentations 0.80 no longer bundles instrumentation-fastify, so it is carried as a direct dependency and registered explicitly, honouring the existing "fastify" disable key. The package is deprecated upstream in favour of @fastify/otel; migrating is follow-up work.
instrumentation-redis-4 merged into instrumentation-redis; the "redis-client" disable key now points there and keeps working.
Express 5 moved routing into the standalone
routerpackage, which has its own instrumentation in the bundle. With both active every layer is traced twice and every exception recorded on each copy -- measured at 22 spans and 3 exception events over 3 requests, against 11 and 1 with router off, with identical routes, middleware, http.route and enriched exception. Router instrumentation is now disabled when express is resolvable; apps usingrouterdirectly still get it, and "router" is a recognised disable key.Verified
Express 5 route-handler throw with no error handler registered now yields exception.stack_details with 8 frames, 3 carrying source. Express 4 behaves identically. Logs, metrics (including opentelemetry-node-metrics against sdk-metrics 2.x) and vcs.* resource attributes all confirmed working. Build clean, 24 tests pass.