diff --git a/packages/hono/src/node/middleware.ts b/packages/hono/src/node/middleware.ts index 625667f2e41d..90cf69a116ed 100644 --- a/packages/hono/src/node/middleware.ts +++ b/packages/hono/src/node/middleware.ts @@ -1,4 +1,4 @@ -import { type BaseTransportOptions, debug, type Options, getClient } from '@sentry/core'; +import { type BaseTransportOptions, consoleSandbox, debug, getClient, type Options } from '@sentry/core'; import type { Env, Hono, MiddlewareHandler } from 'hono'; import { requestHandler, responseHandler } from '../shared/middlewareHandlers'; import { applyPatches } from '../shared/applyPatches'; @@ -17,12 +17,26 @@ export interface HonoNodeOptions extends Options {} export const sentry = (app: Hono, options?: SentryHonoMiddlewareOptions): MiddlewareHandler => { const sentryClient = getClient(); if (sentryClient === undefined) { - debug.warn( - 'Sentry is not initialized. Call `init()` from @sentry/hono/node in an `instrument.ts` file loaded via `--import` to set up Sentry for your application.', - ); + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[@sentry/hono] Sentry is not initialized. Call `init()` from `@sentry/hono/node` in an `instrument.ts` file loaded via `--import` to set up Sentry for your application.', + ); + }); } else { - sentryClient.getOptions().debug && - debug.log('Sentry is initialized, proceeding to set up Hono `sentry` middleware.'); + const isInitializedWithHonoSdk = sentryClient.getOptions()._metadata?.sdk?.name === 'sentry.javascript.hono'; + + if (!isInitializedWithHonoSdk) { + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[Sentry] Sentry was not initialized with `@sentry/hono/node`. Please import from `@sentry/hono/node` to ensure Hono-specific instrumentation is applied correctly.', + ); + }); + } else { + sentryClient.getOptions().debug && + debug.log('Sentry is initialized, proceeding to set up Hono `sentry` middleware.'); + } } applyPatches(app); diff --git a/packages/hono/test/node/middleware.test.ts b/packages/hono/test/node/middleware.test.ts index 443d1b48ea3b..4bd0f0a66e78 100644 --- a/packages/hono/test/node/middleware.test.ts +++ b/packages/hono/test/node/middleware.test.ts @@ -62,25 +62,61 @@ describe('Hono Node Middleware', () => { expect(middleware.constructor.name).toBe('AsyncFunction'); }); - it('emits a warning when Sentry is not initialized', () => { - const warnSpy = vi.spyOn(SentryCore.debug, 'warn'); + it('emits a console.warn when Sentry is not initialized', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); vi.spyOn(SentryCore, 'getClient').mockReturnValue(undefined); const app = new Hono(); sentry(app); - expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Sentry is not initialized')); + expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('Sentry is not initialized')); + consoleWarnSpy.mockRestore(); }); - it('does not emit a warning when Sentry is already initialized', () => { - const warnSpy = vi.spyOn(SentryCore.debug, 'warn'); + it('does not emit a warning when Sentry is already initialized with @sentry/hono/node', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); + const fakeClient = { + getOptions: () => ({ + debug: false, + _metadata: { sdk: { name: 'sentry.javascript.hono' } }, + }), + }; + vi.spyOn(SentryCore, 'getClient').mockReturnValue(fakeClient as unknown as SentryCore.Client); + + const app = new Hono(); + sentry(app); + + expect(consoleWarnSpy).not.toHaveBeenCalled(); + consoleWarnSpy.mockRestore(); + }); + + it('emits a console.warn when Sentry is initialized with @sentry/node instead of @sentry/hono/node', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); + const fakeClient = { + getOptions: () => ({ + debug: false, + _metadata: { sdk: { name: 'sentry.javascript.node' } }, + }), + }; + vi.spyOn(SentryCore, 'getClient').mockReturnValue(fakeClient as unknown as SentryCore.Client); + + const app = new Hono(); + sentry(app); + + expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('not initialized with `@sentry/hono/node`')); + consoleWarnSpy.mockRestore(); + }); + + it('emits a console.warn when Sentry is initialized without any SDK metadata', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); const fakeClient = { getOptions: () => ({ debug: false }) }; vi.spyOn(SentryCore, 'getClient').mockReturnValue(fakeClient as unknown as SentryCore.Client); const app = new Hono(); sentry(app); - expect(warnSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('not initialized with `@sentry/hono/node`')); + consoleWarnSpy.mockRestore(); }); }); @@ -135,26 +171,33 @@ describe('Hono Node Middleware', () => { expect(middleware.constructor.name).toBe('AsyncFunction'); }); - it('emits a warning when Sentry is not initialized', () => { - const warnSpy = vi.spyOn(SentryCore.debug, 'warn'); + it('emits a console.warn when Sentry is not initialized', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); vi.spyOn(SentryCore, 'getClient').mockReturnValue(undefined); const app = new Hono(); sentry(app); - expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Sentry is not initialized')); + expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('Sentry is not initialized')); + consoleWarnSpy.mockRestore(); }); - it('does not emit a warning when Sentry is already initialized', () => { - const warnSpy = vi.spyOn(SentryCore.debug, 'warn'); - const fakeClient = { getOptions: () => ({ debug: false }) }; + it('does not emit a warning when Sentry is already initialized with @sentry/hono/node', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); + const fakeClient = { + getOptions: () => ({ + debug: false, + _metadata: { sdk: { name: 'sentry.javascript.hono' } }, + }), + }; vi.spyOn(SentryCore, 'getClient').mockReturnValue(fakeClient as unknown as SentryCore.Client); const app = new Hono(); const middleware = sentry(app); - expect(warnSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); expect(middleware.constructor.name).toBe('AsyncFunction'); + consoleWarnSpy.mockRestore(); }); });