SMOODEV-1067: Node SDK capture handlers + Hono middleware - #3
Merged
Conversation
Wire the node-side TODO stubs into real implementations:
- `registerNodeGlobalHandlers({ flush, exitOnUncaught })` attaches
`uncaughtException` + `unhandledRejection` listeners that forward to
`Client.captureException`, plus SIGTERM / SIGINT / `beforeExit` flushing
so a Lambda container shutdown drains the in-memory queue. Idempotent.
- `makeNodeTransport(options)` returns a node-flavored `Transport` (fetch
with keepalive, no Beacon). Caller keeps the instance so the global
handlers can hook its `flush()` into the process lifecycle.
- `observabilityMiddleware({ resolveUser, requestHeaderAllowlist })` —
Hono-shaped middleware. Per request: hydrates the active `Scope` from
`c.get('auth')` (matches `@smooai/auth`), adds a `request` context
with method/path/allow-listed-headers, wraps the handler chain in
`withScope` so any `captureException` from a downstream handler picks
up that request's identity, and captures thrown errors before re-
throwing so Hono's `onError` still renders the response.
- `Client.init` on node now auto-wires the transport + global handlers
(override with `autoInstrumentation: false`).
Also fixed a latent bug in `withScope`: previously the cloned scope was
popped before any `await` inside the callback resolved, so request-scoped
state was gone by the time async handlers ran. `withScope` now defers the
pop until a returned thenable settles, while keeping the synchronous fast
path unchanged.
24 tests (was 13). Build + typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 5422d89 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
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.
Summary
Wires the node-side TODO stubs into real implementations so
@smooai/observabilityworks end-to-end on Lambda / long-running Node services. Closes the th-bafeb7 follow-up under the SMOODEV-1067 Phase 1 epic and unblocks the logger ↔ observability integration tracked separately.What lands
registerNodeGlobalHandlers({ flush, exitOnUncaught })— attachesuncaughtException+unhandledRejectionlisteners forwarding toClient.captureException, plus SIGTERM / SIGINT /beforeExitflushing so a Lambda container shutdown drains the queue. Idempotent.makeNodeTransport(options)— node-flavored Transport (fetch + keepalive; no Beacon).observabilityMiddleware({ resolveUser, requestHeaderAllowlist })— Hono-shaped middleware. Hydrates the request Scope with the authenticated user (default reader matches@smooai/auth'sc.get('auth')), recordsrequestcontext, wraps the chain inwithScope, captures thrown errors before re-throwing so Hono'sonErrorstill renders the response.Client.initon node auto-wires transport + handlers (autoInstrumentation: falseto opt out).Latent bug fix
withScopeused to pop the cloned scope insidefinally, which ran BEFORE awaits inside an async callback resolved — request-scoped user/tags were gone by the time async handlers ran. Now: if the callback returns a thenable, the pop is deferred until that thenable settles. Sync callers are unchanged (the pop still runs infinallyif no thenable was returned).Test plan
pnpm --filter @smooai/observability exec vitest run— 24/24 green (was 13).pnpm --filter @smooai/observability typecheckclean.pnpm --filter @smooai/observability buildclean.🤖 Generated with Claude Code