test(eve): Add e2e test for node-eve - #24228
Conversation
size-limit report 📦
|
f011d0e to
157f3bb
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 157f3bb. Configure here.
| const { sessionId } = (await createRes.json()) as { sessionId: string }; | ||
|
|
||
| const controller = new AbortController(); | ||
| const timer = setTimeout(() => controller.abort(), 25_000); |
There was a problem hiding this comment.
Stream abort undercuts test timeout
Medium Severity
runAgentTurn aborts the session stream after 25s, which is tighter than the 90s Playwright timeout added because a slow OpenRouter tool-calling turn does not fit in 30s. A slow two-call turn can hit this abort and fail even though the suite still has time left. Flagged because the review rules call out timeout-based e2e flakes.
Triggered by project rule: PR Review Guidelines for Cursor Bot
Reviewed by Cursor Bugbot for commit 157f3bb. Configure here.
| // e2e test needs only a single OpenRouter key. eve resolves this authored | ||
| // `LanguageModel` at runtime. | ||
| const openrouter = createOpenRouter({ | ||
| apiKey: process.env.E2E_OPENROUTER_API_KEY, |
There was a problem hiding this comment.
super-l: Might be worth throwing if the key is absent
| // loader instruments regardless (so the "bundled ... uninstrumented" | ||
| // warning is a false positive), and externalizing it makes eve's dev | ||
| // host fail to resolve its `/register` subpath (`eve dev` only). | ||
| externalDependencies: ['dataloader'], |
There was a problem hiding this comment.
q: Do we expect users to do this too?
There was a problem hiding this comment.
Ah just saw the comment in the pr descr 👍
|
|
||
| // clean up (although this is tmp, still nice to do) | ||
| await rm(tmpDirPath, { recursive: true }); | ||
| await rm(tmpDirPath, { recursive: true, force: true, maxRetries: 5, retryDelay: 300 }); |
There was a problem hiding this comment.
yeah, the test failed to cleanup once here, because mastra kept something alive slightly longer somehow. should be safe to do I guess!
| "@sentry/node": "file:../../packed/sentry-node-packed.tgz", | ||
| "ai": "^7.0.82", | ||
| "dataloader": "^2.2.3", | ||
| "eve": "^0.52.3", |
There was a problem hiding this comment.
l: Should we maybe go with latest while it is with v0? Otherwise we might not see if future minor versions break. Had the same issue with the Agents SDK
| "eve": "^0.52.3", | |
| "eve": "latest", |
There was a problem hiding this comment.
there is a variant of this that runs with latest too, so we should cover "minimum" and latest version!
Registration-only orchestrion configs (native-channel libraries — ai v7, ioredis, @redis/client, mysql2, mongoose) carry a custom transform wired into the bundler plugins only. The runtime loader (`@sentry/server-runtime-injection` `register`) has no custom transforms, so transforming these modules threw `TypeError: transform is not a function`, which the diagnostics callback misreported as the always-on "`@sentry/server-runtime-injection` was bundled ... loads uninstrumented" warning — even though the libraries are correctly instrumented via their native channel (`setupOnce` / `waitForTracingChannelBinding`). Exclude registration-only configs from the runtime instrumentation set (`SENTRY_RUNTIME_INSTRUMENTATIONS`). This is lossless: at runtime the snippet would only trigger a no-op subscription to `orchestrion:*` channels these versions never publish. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…time loader" This reverts commit fe004a2.
bba0356 to
4998968
Compare
…der (#24240) Registration-only orchestrion configs — native-channel libraries such as `ai` v7, `ioredis`, `@redis/client`, `mysql2` and `mongoose` — carry the custom `MODULE_REGISTRATION_TRANSFORM`. That transform is wired into the bundler plugins only (`orchestrion/bundler/moduleInjectedTransform.ts`, via `bundler/options.ts`'s `customTransforms`); the runtime loader (`@sentry/server-runtime-injection`'s `register`) passes no custom transforms to `initialize()`. So when one of these modules loads through the runtime hook, `getTransformer` returns a transformer whose `.transform` is undefined and the loader throws `TypeError: transform is not a function`. The diagnostics callback treats any `TypeError` as a stripped/bundled transformer and emits the always-on warning: ``` [Sentry] `@sentry/server-runtime-injection` was bundled into your application, so <module> and any other instrumented dependency load uninstrumented. ... ``` …even though nothing is wrong: these libraries publish their own tracing channels and are instrumented via `setupOnce()` / `waitForTracingChannelBinding`, independently of the module-registration snippet. This excludes registration-only configs from a new `SENTRY_RUNTIME_INSTRUMENTATIONS` set used by the runtime loader; the bundler keeps the full `SENTRY_INSTRUMENTATIONS`. Skipping them at runtime is lossless rather than a workaround: the registration snippet only fires `orchestrion.module-injected`, which drives the `orchestrion:*` subscription these native versions never publish (a no-op at runtime). The snippet earns its keep only on the bundler path (e.g. bundler-only SDKs like `@sentry/cloudflare` that discover a loaded module via that event); `@sentry/node` registers its integrations statically. _Root cause_: the `sentryModuleRegistration` custom transform used by registration-only configs is registered in `orchestrion/bundler/*` but never in the runtime path, so the runtime code transformer cannot apply it. Noticed this here: #24228 Tests: - `server-utils` unit test — `SENTRY_RUNTIME_INSTRUMENTATIONS` drops every registration-only config and keeps the rest, and asserts the exclusion is per-config, not per-module. - node-integration-test — loading a native-channel library (`mysql2` ≥ 3.20) with the runtime loader active emits no transformer-unavailable warning (via `ensureNoErrorOutput`); it fails against the unfiltered set and passes with this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y conversations (#24247) Stacked on #24228 (base branch `feat/e2e-eve-agent`). Adds `eveConversationHook()`, used as the default export of an eve `agent/hooks/sentry.ts`: ```ts import * as Sentry from '@sentry/node'; import { defineHook } from 'eve/hooks'; export default defineHook(Sentry.eveConversationHook()); ``` It tags every turn of an eve session with the durable session id (`ctx.session.id`) as the Sentry conversation id, so the session's AI spans — which land in separate traces, since each eve turn is its own durable workflow — group into one conversation in the Agents "Conversations" view. _Root cause / why this shape:_ - **Scope, not the AI call.** eve's session id never reaches the AI SDK's telemetry diagnostics channel (the channel event only carries `recordInputs`/`recordOutputs`/`functionId`; `runtimeContext`/metadata go to eve's own OTel integration, which Sentry bypasses). So the id can only be attached via the isolation scope, where the always-on `conversationIdIntegration` picks it up and stamps `gen_ai.conversation.id` onto the gen_ai spans. - **Both `turn.started` and `step.started`.** Each turn is a fresh request with its own isolation scope, and a turn that parks and resumes (approvals, compaction) resumes in another request where `turn.started` won't re-fire. `step.started` runs before every model call, so together they cover every request that produces spans. Re-setting the same id is idempotent. - **Lives in `@sentry/server-utils`.** The helper only needs `setConversationId` from core, so it belongs in the framework-agnostic shared layer, not `@sentry/node`. `@sentry/node` re-exports it (so every `export * from '@sentry/node'` SDK — astro, **nitro** (eve's own base), nestjs, hono, effect — surfaces it automatically); it is added explicitly to the node-based `@sentry/bun`, `@sentry/aws-serverless`, `@sentry/google-cloud-serverless`, and to the server-utils-based `@sentry/deno` and `@sentry/cloudflare`. - **Structural typing.** The eve hook context is typed structurally rather than imported from `eve`, so the SDK keeps no dependency on the framework; the shape is checked at the `defineHook(...)` call site. An optional `getConversationId` lets users override the default (e.g. to use a root/parent session id for subagents). The `node-eve` e2e app now uses the hook and asserts `gen_ai.conversation.id` on each gen_ai span equals the eve session id returned by the session endpoint. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## DESCRIBE YOUR PR Adds a standalone **Eve** JavaScript guide and lifts the old Eve Agent Tracing page into it. Based on [getsentry/sentry-javascript#24228](getsentry/sentry-javascript#24228), [#24247](getsentry/sentry-javascript#24247), and [#24254](getsentry/sentry-javascript#24254). - New guide at `/platforms/javascript/guides/eve/` that **extends the Node guide** (`fallbackGuide: javascript.node`) with Error Monitoring / Tracing / Profiling onboarding toggles. Documents the `@sentry/node` SDK-based setup (replacing the old OTLP approach), `Sentry.eveConversationHook()` for linking session turns into Conversations, and `getInstrumentedModuleNames()` for orchestrion `externalDependencies`. - Removes the old OTLP-based `common/agent-tracing/eve.mdx`, redirects the old route to the new guide, and keeps the Eve card in the Node Agent Tracing grid (which now redirects to the guide). - Adds `javascript.eve` to every `notSupported` **and** `supported` list in JS common content wherever `javascript.node` appears. `PlatformSection` doesn't resolve a guide's `fallbackGuide`, so Eve must be enumerated alongside Node in both directions — otherwise browser-only content leaks into the Eve guide and inherited Node sections/pages render empty. - Registers the Eve sidebar/dropdown icon (`javascript-eve`). ## IS YOUR CHANGE URGENT? Help us prioritize incoming PRs by letting us know when the change needs to go live. Select exactly one option. For deadlines, replace `YYYY-MM-DD` with the due date. You can update this information later by editing the PR description. - [ ] Urgent deadline (GA date, etc.): YYYY-MM-DD - [ ] Other deadline: YYYY-MM-DD - [x] No deadline: Not urgent, can wait up to 1 week+ (blocked on the next `@sentry/node` beta release — see above) ## SLA - Teamwork makes the dream work, so please add a reviewer to your PRs. - Please give the docs team up to 1 week to review your PR unless you've supplied a deadline. Thanks in advance for your help! ## PRE-MERGE CHECKLIST _Make sure you've checked the following before merging your changes:_ - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## DESCRIBE YOUR PR Adds a standalone **Eve** JavaScript guide and lifts the old Eve Agent Tracing page into it. Based on [getsentry/sentry-javascript#24228](getsentry/sentry-javascript#24228), [#24247](getsentry/sentry-javascript#24247), and [#24254](getsentry/sentry-javascript#24254). - New guide at `/platforms/javascript/guides/eve/` that **extends the Node guide** (`fallbackGuide: javascript.node`) with Error Monitoring / Tracing / Profiling onboarding toggles. Documents the `@sentry/node` SDK-based setup (replacing the old OTLP approach), `Sentry.eveConversationHook()` for linking session turns into Conversations, and `getInstrumentedModuleNames()` for orchestrion `externalDependencies`. - Removes the old OTLP-based `common/agent-tracing/eve.mdx`, redirects the old route to the new guide, and keeps the Eve card in the Node Agent Tracing grid (which now redirects to the guide). - Adds `javascript.eve` to every `notSupported` **and** `supported` list in JS common content wherever `javascript.node` appears. `PlatformSection` doesn't resolve a guide's `fallbackGuide`, so Eve must be enumerated alongside Node in both directions — otherwise browser-only content leaks into the Eve guide and inherited Node sections/pages render empty. - Registers the Eve sidebar/dropdown icon (`javascript-eve`). ## IS YOUR CHANGE URGENT? Help us prioritize incoming PRs by letting us know when the change needs to go live. Select exactly one option. For deadlines, replace `YYYY-MM-DD` with the due date. You can update this information later by editing the PR description. - [ ] Urgent deadline (GA date, etc.): YYYY-MM-DD - [ ] Other deadline: YYYY-MM-DD - [x] No deadline: Not urgent, can wait up to 1 week+ (blocked on the next `@sentry/node` beta release — see above) ## SLA - Teamwork makes the dream work, so please add a reviewer to your PRs. - Please give the docs team up to 1 week to review your PR unless you've supplied a deadline. Thanks in advance for your help! ## PRE-MERGE CHECKLIST _Make sure you've checked the following before merging your changes:_ - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01RaYGdTstWVZKU9X4NjtYV1 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>


Adds an e2e test app
node-evethat runs three optional scenarios:--import @sentry/node/import) - instruments other orchestrion libraries tooThe setup:
1. Plain eve setup
This is enough to get basic tracing for ai itself + http/fetch as well as error monitoring working. Nothing else needs to be configured.
2. With orchestrion
When using orchestrion (e.g. you want instrumentation of other dependencies, e.g. mysql or pg or whatever), you need these additional steps:
a. Run eve with
NODE_OPTIONS='--import=@sentry/node/import'to ensure orchestrion is preloadedb. Add packages you want to instrument to
externalDependencies:In a follow up, we'll try to provide a helper to simplify this.
ref #24015