-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat(hono)!: Change setup for @sentry/hono/node (init in external file)
#20497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import * as Sentry from '@sentry/hono/node'; | ||
|
|
||
| Sentry.init({ | ||
| dsn: process.env.E2E_TEST_DSN, | ||
| environment: 'qa', | ||
| tracesSampleRate: 1.0, | ||
| tunnel: 'http://localhost:3031/', | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| export type Runtime = 'cloudflare' | 'node' | 'bun'; | ||
|
|
||
| export const RUNTIME = (process.env.RUNTIME || 'cloudflare') as Runtime; | ||
| export const isNode = RUNTIME === 'node'; | ||
| export const RUNTIME = (process.env.RUNTIME || 'node') as Runtime; | ||
|
|
||
| export const APP_NAME = 'hono-4'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,7 +33,7 @@ npm install @sentry/hono | |
|
|
||
| Additionally to `@sentry/hono`, install the `@sentry/cloudflare` package: | ||
|
|
||
| ```bashbash | ||
| ```bash | ||
| npm install --save @sentry/cloudflare | ||
| ``` | ||
|
|
||
|
|
@@ -100,62 +100,68 @@ export default app; | |
|
|
||
| Additionally to `@sentry/hono`, install the `@sentry/node` package: | ||
|
|
||
| ```bashbash | ||
| ```bash | ||
| npm install --save @sentry/node | ||
| ``` | ||
|
|
||
| Make sure the installed version always stays in sync. The `@sentry/node` package is a required peer dependency when using `@sentry/hono/node`. | ||
| You won't import `@sentry/node` directly in your code, but it needs to be installed in your project. | ||
|
|
||
| ### 2. Initialize Sentry in your Hono app | ||
| ### 2. Initialize Sentry in a separate file | ||
|
|
||
| Initialize the Sentry Hono middleware as early as possible in your app: | ||
| Create an `instrument.mjs` (or `instrument.ts`) file that initializes Sentry before the rest of your application runs. | ||
| This ensures Sentry can wrap third-party libraries (e.g. database clients) as early as possible: | ||
|
|
||
| ```ts | ||
| import { Hono } from 'hono'; | ||
| import { serve } from '@hono/node-server'; | ||
| import { sentry } from '@sentry/hono/node'; | ||
|
|
||
| const app = new Hono(); | ||
|
|
||
| // Initialize Sentry middleware right after creating the app | ||
| app.use( | ||
| sentry(app, { | ||
| dsn: '__DSN__', // or process.env.SENTRY_DSN | ||
| tracesSampleRate: 1.0, | ||
| }), | ||
| ); | ||
|
|
||
| // ... your routes and other middleware | ||
| // instrument.mjs (or instrument.ts) | ||
| import * as Sentry from '@sentry/hono/node'; | ||
|
|
||
| serve(app); | ||
| Sentry.init({ | ||
| dsn: '__DSN__', | ||
| tracesSampleRate: 1.0, | ||
| }); | ||
| ``` | ||
|
|
||
| ### 3. Add `preload` script to start command | ||
|
|
||
| To ensure that Sentry can capture spans from third-party libraries (e.g. database clients) used in your Hono app, Sentry needs to wrap these libraries as early as possible. | ||
| ### 3. Load the instrument file with `--import` | ||
|
|
||
| When starting the Hono Node application, use the `@sentry/node/preload` hook with the `--import` CLI option to ensure modules are wrapped before the application code runs: | ||
| When starting your Hono Node application, use the `--import` CLI flag to load `instrument.mjs` before your app code: | ||
|
|
||
| ```bash | ||
| node --import @sentry/node/preload index.js | ||
| node --import ./instrument.mjs app.js | ||
| ``` | ||
|
|
||
| This option can also be added to the `NODE_OPTIONS` environment variable: | ||
|
|
||
| ```bash | ||
| NODE_OPTIONS="--import @sentry/node/preload" | ||
| NODE_OPTIONS="--import ./instrument.mjs" | ||
| ``` | ||
|
|
||
| Read more about this preload script in the docs: https://docs.sentry.io/platforms/javascript/guides/hono/install/late-initialization/#late-initialization-with-esm | ||
| ### 4. Add the Sentry middleware to your Hono app | ||
|
|
||
| Add the `sentry` middleware to your Hono app. Since Sentry was already initialized in the instrument file, no options are needed: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. m: if users provide options here again, would that be silently ignored? if that is the case I think it would be good to be a bit more explicit about that people should not use these together
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I added a note/warning about that in the JSDoc to |
||
|
|
||
| ```ts | ||
| import { Hono } from 'hono'; | ||
| import { serve } from '@hono/node-server'; | ||
| import { sentry } from '@sentry/hono/node'; | ||
|
|
||
| const app = new Hono(); | ||
|
|
||
| // Add Sentry middleware right after creating the app | ||
| app.use(sentry(app)); | ||
|
|
||
| // ... your routes and other middleware | ||
|
|
||
| serve(app); | ||
| ``` | ||
|
|
||
| ## Setup (Bun) | ||
|
|
||
| ### 1. Install Peer Dependency | ||
|
|
||
| Additionally to `@sentry/hono`, install the `@sentry/bun` package: | ||
|
|
||
| ```bashbash | ||
| ```bash | ||
| npm install --save @sentry/bun | ||
| ``` | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,13 +8,16 @@ export interface HonoNodeOptions extends Options<BaseTransportOptions> {} | |
|
|
||
| /** | ||
| * Sentry middleware for Hono running in a Node runtime environment. | ||
| * | ||
| * @param app The root Hono application instance to which the middleware will be applied. | ||
| * @param options Optional Sentry initialization options, which **should usually be omitted** when Sentry is initialized externally (e.g. in an `instrument.ts` file loaded via `--import`). | ||
| * If provided, the middleware will initialize Sentry internally using these options. If omitted, the middleware assumes Sentry has already been initialized externally. | ||
| */ | ||
| export const sentry = (app: Hono, options: HonoNodeOptions): MiddlewareHandler => { | ||
| const isDebug = options.debug; | ||
|
|
||
| isDebug && debug.log('Initialized Sentry Hono middleware (Node)'); | ||
|
|
||
| init(options); | ||
| export const sentry = (app: Hono, options?: HonoNodeOptions): MiddlewareHandler => { | ||
| if (options) { | ||
| options.debug && debug.log('Initialized Sentry Hono middleware (Node)'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. l: should this be moved to after the init call? since init might still bail
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or renaming to |
||
| init(options); | ||
| } | ||
|
|
||
| applyPatches(app); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,23 @@ | ||
| import type { Client } from '@sentry/core'; | ||
| import { applySdkMetadata } from '@sentry/core'; | ||
| import { applySdkMetadata, debug, getClient } from '@sentry/core'; | ||
| import { init as initNode } from '@sentry/node'; | ||
| import type { HonoNodeOptions } from './middleware'; | ||
| import { buildFilteredIntegrations } from '../shared/buildFilteredIntegrations'; | ||
|
|
||
| /** | ||
| * Initializes Sentry for Hono running in a Node runtime environment. | ||
| * | ||
| * In general, it is recommended to initialize Sentry via the `sentry()` middleware, as it sets up everything by default and calls `init` internally. | ||
| * | ||
| * When manually calling `init`, add the `honoIntegration` to the `integrations` array to set up the Hono integration. | ||
| * This function should be called in an `instrument.ts` file loaded via `--import` to set up Sentry globally for the application. | ||
| */ | ||
| export function init(options: HonoNodeOptions): Client | undefined { | ||
| const existingClient = getClient(); | ||
| if (existingClient) { | ||
| debug.log('Sentry is already initialized, skipping re-initialization.'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. h: should we also log this outside of debug mode? feels like this would be easy to trip over for users
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think would be great if we have this generally everywhere 🤔 |
||
| return existingClient; | ||
| } | ||
|
|
||
| applySdkMetadata(options, 'hono', ['hono', 'node']); | ||
|
|
||
| // Remove Hono from the SDK defaults to prevent double instrumentation: @sentry/node | ||
| const filteredOptions: HonoNodeOptions = { | ||
| ...options, | ||
| integrations: buildFilteredIntegrations(options.integrations, false), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
l: maybe just
Initialize Sentry?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I would rather keep this very explicit