From cbe84cbce6bbd46e6206be48eb8e9aa2c5cc9a28 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Fri, 18 Sep 2026 20:45:37 +0200 Subject: [PATCH] test(cloudflare): Assert Workers AI gen_ai spans in the send-to-sentry E2E test Call a Workers AI model from the deployed Worker and check that the gen_ai.chat span reaches Sentry with its input and output messages. Co-Authored-By: Claude Opus 5 --- .../src/env.d.ts | 1 + .../src/index.ts | 6 +++- .../tests/send-to-sentry.test.ts | 29 ++++++++++++++++++- .../wrangler.jsonc | 1 + 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/env.d.ts b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/env.d.ts index eb80bafb4834..7a0baa481f45 100644 --- a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/env.d.ts +++ b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/env.d.ts @@ -1,3 +1,4 @@ interface Env { E2E_TEST_DSN: string; + AI: Ai; } diff --git a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/index.ts b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/index.ts index c48a38137713..9e0844c31dea 100644 --- a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/index.ts +++ b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/src/index.ts @@ -1,7 +1,7 @@ import * as Sentry from '@sentry/cloudflare'; export default { - async fetch(request) { + async fetch(request, env) { const url = new URL(request.url); // The handler runs inside the request span the Vite plugin's `withSentry` wrapper starts, so // this is the `http.server` span. @@ -14,6 +14,10 @@ export default { } case '/test-unhandled-error': throw new Error('E2E test unhandled error'); + case '/test-workers-ai': { + await env.AI.run('@cf/meta/llama-3.2-1b-instruct', { prompt: 'Say hi', max_tokens: 5 }); + return Response.json({ traceId: spanContext?.traceId }); + } case '/test-span': return Response.json({ spanId: spanContext?.spanId, traceId: spanContext?.traceId }); default: diff --git a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/tests/send-to-sentry.test.ts index 49813f134b10..618fa0f4fa6d 100644 --- a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/tests/send-to-sentry.test.ts @@ -1,6 +1,12 @@ import { randomBytes } from 'node:crypto'; import { expect, test } from '@playwright/test'; -import { EVENT_POLLING_OPTIONS, findErrorInTrace, findSpanInTrace, traceTarget } from '@sentry-internal/test-utils/cli'; +import { + EVENT_POLLING_OPTIONS, + fetchSpanAttributes, + findErrorInTrace, + findSpanInTrace, + traceTarget, +} from '@sentry-internal/test-utils/cli'; // Set by global-setup.mjs once the worker for this run is deployed. const workerUrl = process.env.E2E_TEST_WORKER_URL; @@ -43,3 +49,24 @@ test('Sends a request span to Sentry', async () => { .poll(() => findSpanInTrace(traceId, 'http.server'), EVENT_POLLING_OPTIONS) .toMatchObject({ event_id: spanId }); }); + +test('Sends a Workers AI gen_ai span to Sentry', async () => { + const response = await fetch(`${workerUrl}/test-workers-ai`); + expect(response.status).toBe(200); + const { traceId } = await response.json(); + + console.log(`Polling for gen_ai.chat span: sentry trace view ${traceTarget(traceId)}`); + + let spanId: string | undefined; + await expect + .poll(() => (spanId = findSpanInTrace(traceId, 'gen_ai.chat')?.event_id), EVENT_POLLING_OPTIONS) + .toBeDefined(); + + // Sentry stores `gen_ai.response.text` as `gen_ai.output.messages`. + await expect + .poll(() => fetchSpanAttributes(traceId, spanId!), EVENT_POLLING_OPTIONS) + .toMatchObject({ + 'gen_ai.input.messages': expect.stringContaining('Say hi'), + 'gen_ai.output.messages': expect.stringContaining('"role":"assistant"'), + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/wrangler.jsonc b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/wrangler.jsonc index cf5ad9bee22b..8959e80c2917 100644 --- a/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/wrangler.jsonc +++ b/dev-packages/e2e-tests/test-applications/cloudflare-workers-send-to-sentry/wrangler.jsonc @@ -6,6 +6,7 @@ "compatibility_date": "2026-05-20", "compatibility_flags": ["nodejs_compat"], "workers_dev": true, + "ai": { "binding": "AI" }, // Workers Logs keep the invocations of the last 7 days, so a failed CI run can still be inspected. "observability": { "enabled": true }, }