Skip to content

test(e2e): Add node-anthropic-send-to-sentry test app - #24856

Open
RulaKhaled wants to merge 1 commit into
fix/anthropic-stream-helper-header-casefrom
test/anthropic-send-to-sentry-e2e
Open

RulaKhaled wants to merge 1 commit into
fix/anthropic-stream-helper-header-casefrom
test/anthropic-send-to-sentry-e2e

Conversation

@RulaKhaled

Copy link
Copy Markdown
Collaborator

An e2e app that uses the Anthropic integration the way a user does and sends the data to a real Sentry project, per #24748. Same shape as the OpenAI one in #24824.

Stacked on #24855. The latest variant needs that fix; this PR targets its branch and retargets to develop once it merges.

The app. A plain Sentry.init on an express app, preloaded with node --import, no tunnel. The stock @anthropic-ai/sdk client points at OpenRouter's Anthropic-compatible endpoint (bearer token via authToken) and four routes make one real request each: a message, a streamed message via create({ stream: true }), one via the messages.stream() helper, and a forced tool use.

The tests. Each one polls Sentry for the request's gen_ai.chat span through the organization trace endpoint, then reads its attributes through the project trace-items endpoint, the same way the other *-send-to-sentry apps look events up. tests/utils/sentry-api.ts is the node-express copy plus fetchSpanAttributes. Asserted per span: op, name, origin, status, provider, request and response model, response id, output and total tokens, and that the prompts and answers arrived. The stream tests also check stop reasons and the streaming flag, and the helper test checks there is exactly one gen_ai.chat span in the trace. The plain-message test checks the span sits below the http.server span.

Variants. @anthropic-ai/sdk is pinned to 0.63.0, the version the integration suite uses. The node-anthropic-send-to-sentry (latest) variant runs the same suite against @anthropic-ai/sdk@latest. The app is optional, like the other send-to-sentry apps.

What the latest variant found. On 0.129 the stream helper produced two nested gen_ai.chat spans. The SDK lowercased the header the integration uses to skip the helper's internal create; fixed in #24855.

Two things the tests do not assert, on purpose.

  • Input token usage on streamed calls. OpenRouter reports input_tokens: 0 in message_start and the real count in message_delta; the streaming instrumentation reads input usage only from message_start, so the stored value is 0. The Anthropic API also carries cumulative usage on message_delta, so reading it there would be a small improvement. Separate from this PR.
  • gen_ai.response.tool_calls and gen_ai.request.max_tokens, which ingest does not store under those names (same as for OpenAI).

Verified. Both variants pass against a real project: 4 of 4 on 0.63.0 and, with #24855 applied, 4 of 4 on 0.129.0.

Closes #24748

🤖 Generated with Claude Code

An e2e app that uses the Anthropic integration the way a user does and
sends the data to a real Sentry project. A plain Sentry.init on an express
app, no tunnel, and the stock @anthropic-ai/sdk client making real
requests through OpenRouter's Anthropic-compatible endpoint: a message, a
streamed message, one through the messages.stream() helper, and a forced
tool use. The tests read the gen_ai spans back through the Sentry API,
like the other *-send-to-sentry apps, and check op, name, origin, status,
token usage, stop reasons and the recorded prompts and answers. A latest
variant runs the same suite against @anthropic-ai/sdk@latest.

The stream-helper test asserts a single gen_ai.chat span; that is what
caught the duplicate span on current SDK versions fixed in the commit this
sits on. The streamed tests do not assert input token usage: OpenRouter
reports 0 in message_start and the real count in message_delta, which the
streaming instrumentation does not read.

Closes #24748

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@github-actions

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.24 kB - -
@sentry/browser - with treeshaking flags 27.5 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.4 kB - -
@sentry/browser (incl. Tracing) 51.15 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 51.18 kB - -
@sentry/browser (incl. Tracing, Profiling) 54.18 kB - -
@sentry/browser (incl. Tracing, Replay) 90.76 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 79.86 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 95.46 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 108.41 kB - -
@sentry/browser (incl. Feedback) 46.76 kB - -
@sentry/browser (incl. sendFeedback) 34.3 kB - -
@sentry/browser (incl. FeedbackAsync) 39.41 kB - -
@sentry/browser (incl. Metrics) 30.25 kB - -
@sentry/browser (incl. Logs) 30.53 kB - -
@sentry/browser (incl. Metrics & Logs) 31.2 kB - -
@sentry/react 31.08 kB - -
@sentry/react (incl. Tracing) 53.54 kB - -
@sentry/vue 36.74 kB - -
@sentry/vue (incl. Tracing) 53.7 kB - -
@sentry/svelte 29.26 kB - -
CDN Bundle 31.05 kB - -
CDN Bundle (incl. Tracing) 51.8 kB - -
CDN Bundle (incl. Logs, Metrics) 33.31 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 53.77 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 74.02 kB - -
CDN Bundle (incl. Tracing, Replay) 89.39 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.36 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 95.55 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 97.53 kB - -
CDN Bundle - uncompressed 91.7 kB - -
CDN Bundle (incl. Tracing) - uncompressed 154.08 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 98.27 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 160.04 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 227.84 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 273.81 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 279.75 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 287.51 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 293.44 kB - -
@sentry/nextjs (client) 55.78 kB - -
@sentry/sveltekit (client) 51.6 kB - -
@sentry/core/server 39.99 kB - -
@sentry/core/browser 13.63 kB - -
@sentry/node 142.3 kB +0.05% +70 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 82.88 kB - -
@sentry/node - without tracing 91.25 kB +0.02% +13 B 🔺
@sentry/node - without channel injection 120.7 kB +0.06% +69 B 🔺
@sentry/aws-serverless 99.52 kB +0.01% +8 B 🔺
@sentry/cloudflare (withSentry) - minified 206.64 kB - -
@sentry/cloudflare (withSentry) 514.04 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 3b49445. Configure here.


// The request span is the segment; it ends last, so it can land after its children.
await expect.poll(() => isModelSpanUnderRequestSpan(traceId, span.event_id!), EVENT_POLLING_OPTIONS).toBe(true);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Test timeout too short for polls

Medium Severity

The first test runs two sequential 180s Sentry polls, but the Playwright timeout is only 210s. If the gen_ai.chat span becomes queryable late, the follow-up parent-span poll is cut short and the test fails even when the http.server span would still arrive.

Additional Locations (2)
Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

Reviewed by Cursor Bugbot for commit 3b49445. Configure here.

return undefined;
}

if (response.status === 401 || response.status === 403) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: The waitForSpan poll can succeed prematurely because fetchSpanAttributes may return a truthy empty object {}, causing subsequent assertions to fail.
Severity: MEDIUM

Suggested Fix

Update the condition in waitForSpan to ensure the attributes object is not empty before considering the poll successful. A suggested implementation is: found = span && attributes && Object.keys(attributes).length > 0 ? { span, attributes } : undefined;.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location:
dev-packages/e2e-tests/test-applications/node-anthropic-send-to-sentry/tests/utils/sentry-api.ts#L113

Potential issue: The `fetchSpanAttributes` function can return an empty object `{}` if
the Sentry API returns an empty `attributes` array, which can happen due to race
conditions during data ingestion. In the `waitForSpan` function, the truthiness check
`span && attributes` evaluates to true because an empty object is truthy in JavaScript.
This causes the polling mechanism to succeed prematurely. Consequently, subsequent
assertions that expect specific properties on the `attributes` object fail with
misleading errors, as they are attempting to access properties on an empty object,
leading to flaky tests.

Also affects:

  • dev-packages/e2e-tests/test-applications/node-anthropic-send-to-sentry/tests/utils/sentry-api.ts:89~89

Did we get this right? 👍 / 👎 to inform future reviews.

This branch has not been deployed

No deployments
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.

1 participant