Skip to content

test(eve): Add e2e test for node-eve - #24228

Merged
mydea merged 8 commits into
developfrom
feat/e2e-eve-agent
Sep 11, 2026
Merged

mydea merged 8 commits into
developfrom
feat/e2e-eve-agent

Conversation

@mydea

@mydea mydea commented Sep 9, 2026 •

Copy link
Copy Markdown
Member

Adds an e2e test app node-eve that runs three optional scenarios:

  1. Plain eve setup - instruments ai calls
  2. Setup with orchestrion (needs --import @sentry/node/import) - instruments other orchestrion libraries too
  3. With latest versions of eve and ai to ensure this remains compatible

The setup:

1. Plain eve setup

// agent/instrumentation.ts
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: process.env.E2E_TEST_DSN,
  tracesSampleRate: 1.0,
});

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 preloaded
b. Add packages you want to instrument to externalDependencies:

// agent/agent.ts
import { defineAgent } from 'eve';

export default defineAgent({
  build: {
    externalDependencies: ['pg', 'mysql']
  },
});

In a follow up, we'll try to provide a helper to simplify this.

ref #24015

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread dev-packages/e2e-tests/test-applications/node-eve/tests/eve.test.ts
Comment thread dev-packages/e2e-tests/test-applications/node-eve/playwright.config.mjs Outdated
@github-actions

github-actions Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.92 kB - -
@sentry/browser - with treeshaking flags 27.21 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.11 kB - -
@sentry/browser (incl. Tracing) 50.42 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 50.43 kB - -
@sentry/browser (incl. Tracing, Profiling) 53.41 kB - -
@sentry/browser (incl. Tracing, Replay) 89.93 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 79.05 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 94.64 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 107.65 kB - -
@sentry/browser (incl. Feedback) 46.41 kB - -
@sentry/browser (incl. sendFeedback) 33.97 kB - -
@sentry/browser (incl. FeedbackAsync) 39.08 kB - -
@sentry/browser (incl. Metrics) 29.93 kB - -
@sentry/browser (incl. Logs) 30.2 kB - -
@sentry/browser (incl. Metrics & Logs) 30.87 kB - -
@sentry/react 30.67 kB - -
@sentry/react (incl. Tracing) 52.73 kB - -
@sentry/vue 36.16 kB - -
@sentry/vue (incl. Tracing) 52.66 kB - -
@sentry/svelte 28.93 kB - -
CDN Bundle 30.66 kB - -
CDN Bundle (incl. Tracing) 50.93 kB - -
CDN Bundle (incl. Logs, Metrics) 32.93 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 52.91 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 73.62 kB - -
CDN Bundle (incl. Tracing, Replay) 88.48 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 90.43 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 94.55 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 96.55 kB - -
CDN Bundle - uncompressed 90.73 kB - -
CDN Bundle (incl. Tracing) - uncompressed 152.17 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.31 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 158.13 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 226.72 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 271.74 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 277.69 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 285.44 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 291.38 kB - -
@sentry/nextjs (client) 55.05 kB - -
@sentry/sveltekit (client) 50.83 kB - -
@sentry/core/server 37.08 kB - -
@sentry/core/browser 13.66 kB - -
@sentry/node 128.59 kB +0.02% +14 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 81.82 kB - -
@sentry/node - without tracing 89.55 kB +0.04% +29 B 🔺
@sentry/node - without channel injection 107.52 kB +0.02% +21 B 🔺
@sentry/aws-serverless 97.77 kB +0.03% +23 B 🔺
@sentry/cloudflare (withSentry) - minified 203.02 kB - -
@sentry/cloudflare (withSentry) 505.43 kB - -

View base workflow run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

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,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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'],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Do we expect users to do this too?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 });

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Suggested change
"eve": "^0.52.3",
"eve": "latest",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a variant of this that runs with latest too, so we should cover "minimum" and latest version!

mydea and others added 8 commits September 11, 2026 10:03
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>
@mydea
mydea force-pushed the feat/e2e-eve-agent branch from bba0356 to 4998968 Compare September 11, 2026 08:03
mydea added a commit that referenced this pull request Sep 11, 2026
…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>
@mydea
mydea merged commit 41c40b3 into develop Sep 11, 2026
617 of 621 checks passed
@mydea
mydea deleted the feat/e2e-eve-agent branch September 11, 2026 10:40
mydea added a commit that referenced this pull request Sep 14, 2026
…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>
mydea added a commit to getsentry/sentry-docs that referenced this pull request Sep 16, 2026
## 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>
inventarSarah pushed a commit to getsentry/sentry-docs that referenced this pull request Sep 29, 2026
## 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants