getsentry / getsentry/sentry-javascript

@sentry/astro: Cloudflare Worker server wrap not applied with @astrojs/cloudflare v14 (transform targets `astrojs-ssr-virtual-entry`, adapter now emits `virtual:cloudflare/worker-entry`)

Abierto
#21,901 4 comentarios 0 reacciones 1 asignado Reclamado por @JPeer264 Ver en GitHub
Astro Cloudflare Workers Feature
Lenguaje dominante
TypeScript
Estrellas
8.7k
Forks
1.8k
Merge medio
1 d 17 h
PR fusionados (30 d)
515

Descripción

## Summary

With `@astrojs/cloudflare` v14, `@sentry/astro`'s server-side init is never applied to the deployed Cloudflare Worker. The Worker's default export is left un-wrapped by `withSentry`, so server-side error/log capture does not initialize at the fetch boundary — server-side Sentry silently does nothing.

## Versions

- `@sentry/astro` 10.62.0
- `@sentry/cloudflare` 10.62.0
- `@astrojs/cloudflare` 14.0.1
- `astro` 7.0.3
- `output: 'server'`, Cloudflare **Workers** (not Pages)

## Root cause

`sentryCloudflareVitePlugin` (`packages/astro/src/integration/cloudflare.ts`) wraps the Worker by transforming the module whose id contains `astrojs-ssr-virtual-entry`:

```js
transform(code, id) {
if (!id.includes("astrojs-ssr-virtual-entry")) {
return undefined;
}
// ...rewrites `export default X;` -> `export default withSentry(() => undefined, X);`
}
```

`@astrojs/cloudflare` v14 builds the Worker through `@cloudflare/vite-plugin`, whose entry virtual module id is `virtual:cloudflare/worker-entry` (its generated body ends with `export default mod.default ?? {};`). The old `astrojs-ssr-virtual-entry` id is no longer produced, so the `transform` guard always returns early and the entry is never wrapped.

## Effect

With an app configured per the [Astro + Cloudflare docs](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/astro/) (the `sentry()` integration in `astro.config` plus a `sentry.server.config.ts` doing `export default Sentry.withSentry((env) => ({ ... }), handler)`), the generated `dist/server/entry.mjs` default export is the **raw** Astro handler. Grepping all of `dist/server` for `withSentry(() =>` finds no match — the plugin's wrap never ran.

The only remaining server wiring is the injected `import "sentry.server.config.(ts|js)"` (`injectScript("page-ssr", ...)`). That runs lazily during a page render, so it doesn't deterministically instrument the Worker's fetch entry:

- errors on the first request (before any page module has evaluated the config) aren't captured;
- routes that don't pull the page-ssr module graph (e.g. API endpoints) aren't covered;
- for a Worker whose first traffic is an API route, `Sentry.init` may never run at all.

## Repro

1. Scaffold an Astro app with `output: 'server'` and the `@astrojs/cloudflare` v14 adapter (Workers, not Pages).
2. `npm i @sentry/astro @sentry/cloudflare`; add `sentry()` to `integrations`; create `sentry.server.config.ts` per the docs:
```ts
import * as Sentry from '@sentry/cloudflare'
import handler from '@astrojs/cloudflare/entrypoints/server'
export default Sentry.withSentry((env) => ({ dsn: env.SENTRY_DSN, enableLogs: true }), handler)
```
3. `astro build`.
4. Inspect `dist/server/entry.mjs`: the default export is the un-wrapped Astro handler, and `grep -r "withSentry(() =>" dist/server` returns nothing.

## Suggested fix

Have `sentryCloudflareVitePlugin`'s `transform` also match the `@cloudflare/vite-plugin` entry id `virtual:cloudflare/worker-entry` (whose default-export expression is `mod.default ?? {}`), in addition to `astrojs-ssr-virtual-entry`, so the wrap applies on `@astrojs/cloudflare` v14+.

## Workaround

For anyone hitting this before a fix lands: a tiny build-only Vite plugin that transforms the `virtual:cloudflare/worker-entry` module and wraps its `export default mod.default ?? {};` with your own `withSentry(optionsCallback, handler)` restores deterministic, eager wrapping of the Worker entry.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.