From 500815e388fe9b9ddbaa3e0637e7710cd953db62 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 28 Jul 2026 12:16:49 +0200 Subject: [PATCH] ref(node): Remove vendored Hapi instrumentation Removes the dead OpenTelemetry `HapiInstrumentation` from `@sentry/node`. The Hapi integration is provided by the channel-based implementation in `@sentry/server-utils` (default since #22501); only the Sentry-specific `setupHapiErrorHandler` is kept here. Ref: #22346 Co-Authored-By: Claude Opus 4.8 --- .../src/integrations/tracing/hapi/index.ts | 6 - .../hapi/vendored/enums/AttributeNames.ts | 15 - .../tracing/hapi/vendored/hapi-types.ts | 86 ----- .../tracing/hapi/vendored/instrumentation.ts | 316 ------------------ .../tracing/hapi/vendored/internal-types.ts | 62 ---- .../tracing/hapi/vendored/utils.ts | 123 ------- .../test/integrations/tracing/hapi.test.ts | 90 ----- 7 files changed, 698 deletions(-) delete mode 100644 packages/node/src/integrations/tracing/hapi/vendored/enums/AttributeNames.ts delete mode 100644 packages/node/src/integrations/tracing/hapi/vendored/hapi-types.ts delete mode 100644 packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts delete mode 100644 packages/node/src/integrations/tracing/hapi/vendored/internal-types.ts delete mode 100644 packages/node/src/integrations/tracing/hapi/vendored/utils.ts delete mode 100644 packages/node/test/integrations/tracing/hapi.test.ts diff --git a/packages/node/src/integrations/tracing/hapi/index.ts b/packages/node/src/integrations/tracing/hapi/index.ts index 280af9b4dba7..214a70ee74c9 100644 --- a/packages/node/src/integrations/tracing/hapi/index.ts +++ b/packages/node/src/integrations/tracing/hapi/index.ts @@ -1,14 +1,8 @@ -import { HapiInstrumentation } from './vendored/instrumentation'; import { captureException, debug, getDefaultIsolationScope, getIsolationScope, SDK_VERSION } from '@sentry/core'; -import { generateInstrumentOnce } from '../../../otel/instrument'; import { ensureIsWrapped } from '../../../utils/ensureIsWrapped'; import { DEBUG_BUILD } from '../../../debug-build'; import type { Request, RequestEvent, Server } from './types'; -const INTEGRATION_NAME = 'Hapi' as const; - -export const instrumentHapi = generateInstrumentOnce(INTEGRATION_NAME, () => new HapiInstrumentation()); - function isErrorEvent(event: unknown): event is RequestEvent { return !!(event && typeof event === 'object' && 'error' in event && event.error); } diff --git a/packages/node/src/integrations/tracing/hapi/vendored/enums/AttributeNames.ts b/packages/node/src/integrations/tracing/hapi/vendored/enums/AttributeNames.ts deleted file mode 100644 index 9384d73ad08d..000000000000 --- a/packages/node/src/integrations/tracing/hapi/vendored/enums/AttributeNames.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-hapi - * - Upstream version: @opentelemetry/instrumentation-hapi@0.64.0 - */ -/* eslint-disable */ - -export enum AttributeNames { - HAPI_TYPE = 'hapi.type', - PLUGIN_NAME = 'hapi.plugin.name', - EXT_TYPE = 'server.ext.type', -} diff --git a/packages/node/src/integrations/tracing/hapi/vendored/hapi-types.ts b/packages/node/src/integrations/tracing/hapi/vendored/hapi-types.ts deleted file mode 100644 index 1c1419285fd0..000000000000 --- a/packages/node/src/integrations/tracing/hapi/vendored/hapi-types.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Simplified type definitions vendored from @types/hapi__hapi. - * Only includes the types actually accessed by the instrumentation. - */ -/* eslint-disable */ - -export type ServerOptions = Record; - -export declare function server(options?: ServerOptions): Server; -export declare function Server(options?: ServerOptions): Server; - -export type ServerRequestExtType = - | 'onPreAuth' - | 'onCredentials' - | 'onPostAuth' - | 'onPreHandler' - | 'onPostHandler' - | 'onPreResponse' - | 'onRequest'; - -export namespace Lifecycle { - export type Method = (request: any, h: any, err?: Error) => ReturnValue; - export type ReturnValue = any; - export type FailAction = 'error' | 'log' | 'ignore' | Method; -} - -export interface ServerRoute { - path: string; - method: string; - handler?: Lifecycle.Method | T; - options?: ((server: Server) => ServerRouteOptions) | ServerRouteOptions; - [key: string]: any; -} - -interface ServerRouteOptions { - handler?: Lifecycle.Method | any; - [key: string]: any; -} - -export interface Server { - route: (...args: any[]) => any; - ext: (...args: any[]) => any; - register: (...args: any[]) => any; - [key: string]: any; -} - -export interface Plugin { - register: (server: Server, options: T) => void | Promise; - name?: string; - pkg?: { name: string; [key: string]: any }; - [key: string]: any; -} - -export interface PluginNameVersion { - name: string; - [key: string]: any; -} - -export interface PluginPackage { - pkg: { name: string; [key: string]: any }; - [key: string]: any; -} - -export interface ServerRegisterPluginObject { - plugin: Plugin | { plugin: Plugin; [key: string]: any }; - [key: string]: any; -} - -export interface ServerRegisterOptions { - [key: string]: any; -} - -export interface ServerExtEventsObject { - type: string; - [key: string]: any; -} - -export interface ServerExtEventsRequestObject { - type: ServerRequestExtType; - method: Lifecycle.Method; - [key: string]: any; -} - -export interface ServerExtOptions { - [key: string]: any; -} diff --git a/packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts b/packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts deleted file mode 100644 index d25083f46910..000000000000 --- a/packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-hapi - * - Upstream version: @opentelemetry/instrumentation-hapi@0.64.0 - * - Types vendored from @hapi/hapi as simplified interfaces - * - Minor TypeScript strictness adjustments for this repository's compiler settings - * - Span creation migrated to the @sentry/core API; op/origin folded into span creation - */ - -import * as api from '@opentelemetry/api'; -import { setHttpServerSpanRouteAttribute } from '../../../../utils/setHttpServerSpanRouteAttribute'; -import type { InstrumentationConfig } from '@opentelemetry/instrumentation'; -import { InstrumentationBase, InstrumentationNodeModuleDefinition, isWrapped } from '@opentelemetry/instrumentation'; - -import type * as Hapi from './hapi-types'; -import { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core'; -import { AttributeNames } from './enums/AttributeNames'; -import { - HapiComponentName, - handlerPatched, - type HapiServerRouteInput, - type PatchableServerRoute, - type HapiServerRouteInputMethod, - type HapiPluginInput, - type RegisterFunction, - type PatchableExtMethod, - type ServerExtDirectInput, -} from './internal-types'; -import { - getRouteMetadata, - getPluginName, - isLifecycleExtType, - isLifecycleExtEventObj, - getExtMetadata, - isDirectExtInput, - isPatchableExtMethod, - getPluginFromInput, -} from './utils'; - -const PACKAGE_NAME = '@sentry/instrumentation-hapi'; - -/** Hapi instrumentation for OpenTelemetry */ -export class HapiInstrumentation extends InstrumentationBase { - constructor(config: InstrumentationConfig = {}) { - super(PACKAGE_NAME, SDK_VERSION, config); - } - - protected init() { - return new InstrumentationNodeModuleDefinition( - HapiComponentName, - ['>=17.0.0 <22'], - (module: any) => { - const moduleExports: typeof Hapi = module[Symbol.toStringTag] === 'Module' ? module.default : module; - if (!isWrapped(moduleExports.server)) { - this._wrap(moduleExports, 'server', this._getServerPatch.bind(this)); - } - - if (!isWrapped(moduleExports.Server)) { - this._wrap(moduleExports, 'Server', this._getServerPatch.bind(this)); - } - return moduleExports; - }, - (module: any) => { - const moduleExports: typeof Hapi = module[Symbol.toStringTag] === 'Module' ? module.default : module; - this._massUnwrap([moduleExports], ['server', 'Server']); - }, - ); - } - - /** - * Patches the Hapi.server and Hapi.Server functions in order to instrument - * the server.route, server.ext, and server.register functions via calls to the - * @function _getServerRoutePatch, @function _getServerExtPatch, and - * @function _getServerRegisterPatch functions - * @param original - the original Hapi Server creation function - */ - private _getServerPatch(original: (options?: Hapi.ServerOptions) => Hapi.Server) { - const instrumentation: HapiInstrumentation = this; - const self = this; - return function server(this: Hapi.Server, opts?: Hapi.ServerOptions) { - const newServer: Hapi.Server = original.apply(this, [opts]); - - self._wrap(newServer, 'route', originalRouter => { - return instrumentation._getServerRoutePatch.bind(instrumentation)(originalRouter); - }); - - // Casting as any is necessary here due to multiple overloads on the Hapi.ext - // function, which requires supporting a variety of different parameters - // as extension inputs - self._wrap(newServer, 'ext', originalExtHandler => { - return instrumentation._getServerExtPatch.bind(instrumentation)(originalExtHandler as any); - }); - - // Casting as any is necessary here due to multiple overloads on the Hapi.Server.register - // function, which requires supporting a variety of different types of Plugin inputs - self._wrap(newServer, 'register', instrumentation._getServerRegisterPatch.bind(instrumentation)); - return newServer; - }; - } - - /** - * Patches the plugin register function used by the Hapi Server. This function - * goes through each plugin that is being registered and adds instrumentation - * via a call to the @function _wrapRegisterHandler function. - * @param {RegisterFunction} original - the original register function which - * registers each plugin on the server - */ - private _getServerRegisterPatch(original: RegisterFunction): RegisterFunction { - const instrumentation: HapiInstrumentation = this; - return function register(this: Hapi.Server, pluginInput: HapiPluginInput, options?: Hapi.ServerRegisterOptions) { - if (Array.isArray(pluginInput)) { - for (const pluginObj of pluginInput) { - const plugin = getPluginFromInput(pluginObj); - instrumentation._wrapRegisterHandler(plugin); - } - } else { - const plugin = getPluginFromInput(pluginInput); - instrumentation._wrapRegisterHandler(plugin); - } - return original.apply(this, [pluginInput, options]); - }; - } - - /** - * Patches the Server.ext function which adds extension methods to the specified - * point along the request lifecycle. This function accepts the full range of - * accepted input into the standard Hapi `server.ext` function. For each extension, - * it adds instrumentation to the handler via a call to the @function _wrapExtMethods - * function. - * @param original - the original ext function which adds the extension method to the server - * @param {string} [pluginName] - if present, represents the name of the plugin responsible - * for adding this server extension. Else, signifies that the extension was added directly - */ - private _getServerExtPatch(original: (...args: unknown[]) => unknown, pluginName?: string) { - const instrumentation: HapiInstrumentation = this; - - return function ext(this: ThisParameterType, ...args: Parameters) { - if (Array.isArray(args[0])) { - const eventsList: Hapi.ServerExtEventsObject[] | Hapi.ServerExtEventsRequestObject[] = args[0]; - for (let i = 0; i < eventsList.length; i++) { - const eventObj = eventsList[i]!; - if (isLifecycleExtType(eventObj.type)) { - const lifecycleEventObj = eventObj as Hapi.ServerExtEventsRequestObject; - const handler = instrumentation._wrapExtMethods(lifecycleEventObj.method, eventObj.type, pluginName); - lifecycleEventObj.method = handler; - eventsList[i] = lifecycleEventObj; - } - } - return original.apply(this, args); - } else if (isDirectExtInput(args)) { - const extInput: ServerExtDirectInput = args; - const method: PatchableExtMethod = extInput[1]; - const handler = instrumentation._wrapExtMethods(method, extInput[0], pluginName); - return original.apply(this, [extInput[0], handler, extInput[2]]); - } else if (isLifecycleExtEventObj(args[0])) { - const lifecycleEventObj = args[0]; - const handler = instrumentation._wrapExtMethods(lifecycleEventObj.method, lifecycleEventObj.type, pluginName); - lifecycleEventObj.method = handler; - return original.call(this, lifecycleEventObj); - } - return original.apply(this, args); - }; - } - - /** - * Patches the Server.route function. This function accepts either one or an array - * of Hapi.ServerRoute objects and adds instrumentation on each route via a call to - * the @function _wrapRouteHandler function. - * @param {HapiServerRouteInputMethod} original - the original route function which adds - * the route to the server - * @param {string} [pluginName] - if present, represents the name of the plugin responsible - * for adding this server route. Else, signifies that the route was added directly - */ - private _getServerRoutePatch(original: HapiServerRouteInputMethod, pluginName?: string) { - const instrumentation: HapiInstrumentation = this; - return function route(this: Hapi.Server, route: HapiServerRouteInput): void { - if (Array.isArray(route)) { - for (let i = 0; i < route.length; i++) { - const newRoute = instrumentation._wrapRouteHandler.call(instrumentation, route[i]!, pluginName); - route[i] = newRoute; - } - } else { - // oxlint-disable-next-line no-param-reassign - route = instrumentation._wrapRouteHandler.call(instrumentation, route, pluginName); - } - return original.apply(this, [route]); - }; - } - - /** - * Wraps newly registered plugins to add instrumentation to the plugin's clone of - * the original server. Specifically, wraps the server.route and server.ext functions - * via calls to @function _getServerRoutePatch and @function _getServerExtPatch - * @param {Hapi.Plugin} plugin - the new plugin which is being instrumented - */ - private _wrapRegisterHandler(plugin: Hapi.Plugin): void { - const instrumentation: HapiInstrumentation = this; - const pluginName = getPluginName(plugin); - const oldRegister = plugin.register; - const self = this; - const newRegisterHandler = function (this: typeof plugin, server: Hapi.Server, options: T) { - self._wrap(server, 'route', original => { - return instrumentation._getServerRoutePatch.bind(instrumentation)(original, pluginName); - }); - - // Casting as any is necessary here due to multiple overloads on the Hapi.ext - // function, which requires supporting a variety of different parameters - // as extension inputs - self._wrap(server, 'ext', originalExtHandler => { - return instrumentation._getServerExtPatch.bind(instrumentation)(originalExtHandler as any, pluginName); - }); - return oldRegister.call(this, server, options); - }; - plugin.register = newRegisterHandler; - } - - /** - * Wraps request extension methods to add instrumentation to each new extension handler. - * Patches each individual extension in order to create the - * span and propagate context. It does not create spans when there is no parent span. - * @param {PatchableExtMethod | PatchableExtMethod[]} method - the request extension - * handler which is being instrumented - * @param {Hapi.ServerRequestExtType} extPoint - the point in the Hapi request lifecycle - * which this extension targets - * @param {string} [pluginName] - if present, represents the name of the plugin responsible - * for adding this server route. Else, signifies that the route was added directly - */ - private _wrapExtMethods( - method: T, - extPoint: Hapi.ServerRequestExtType, - pluginName?: string, - ): T { - const instrumentation: HapiInstrumentation = this; - if (method instanceof Array) { - for (let i = 0; i < method.length; i++) { - method[i] = instrumentation._wrapExtMethods(method[i]!, extPoint); - } - return method; - } else if (isPatchableExtMethod(method)) { - if (method[handlerPatched] === true) return method; - method[handlerPatched] = true; - - const newHandler: PatchableExtMethod = function (this: any, ...params: Parameters) { - if (api.trace.getSpan(api.context.active()) === undefined) { - return method.apply(this, params); - } - const metadata = getExtMetadata(extPoint, pluginName, method.name); - return startSpan( - { - name: metadata.name, - op: `${metadata.attributes[AttributeNames.HAPI_TYPE]}.hapi`, - attributes: { - ...metadata.attributes, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.hapi', - }, - }, - () => method.apply(undefined, params), - ); - }; - return newHandler as T; - } - return method; - } - - /** - * Patches each individual route handler method in order to create the - * span and propagate context. It does not create spans when there is no parent span. - * @param {PatchableServerRoute} route - the route handler which is being instrumented - * @param {string} [pluginName] - if present, represents the name of the plugin responsible - * for adding this server route. Else, signifies that the route was added directly - */ - private _wrapRouteHandler(route: PatchableServerRoute, pluginName?: string): PatchableServerRoute { - if (route[handlerPatched] === true) return route; - route[handlerPatched] = true; - - const wrapHandler: (oldHandler: Hapi.Lifecycle.Method) => Hapi.Lifecycle.Method = oldHandler => { - return function (this: any, ...params: Parameters) { - if (api.trace.getSpan(api.context.active()) === undefined) { - return oldHandler.call(this, ...params); - } - setHttpServerSpanRouteAttribute(route.path); - const metadata = getRouteMetadata(route, pluginName); - return startSpan( - { - name: metadata.name, - op: `${metadata.attributes[AttributeNames.HAPI_TYPE]}.hapi`, - attributes: { - ...metadata.attributes, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.hapi', - }, - }, - () => oldHandler.call(this, ...params), - ); - }; - }; - - if (typeof route.handler === 'function') { - route.handler = wrapHandler(route.handler as Hapi.Lifecycle.Method); - } else if (typeof route.options === 'function') { - const oldOptions = route.options; - route.options = function (server) { - const options = oldOptions(server); - if (typeof options.handler === 'function') { - options.handler = wrapHandler(options.handler as Hapi.Lifecycle.Method); - } - return options; - }; - } else if (typeof route.options?.handler === 'function') { - route.options.handler = wrapHandler(route.options.handler as Hapi.Lifecycle.Method); - } - return route; - } -} diff --git a/packages/node/src/integrations/tracing/hapi/vendored/internal-types.ts b/packages/node/src/integrations/tracing/hapi/vendored/internal-types.ts deleted file mode 100644 index 4c76706c3e2e..000000000000 --- a/packages/node/src/integrations/tracing/hapi/vendored/internal-types.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-hapi - * - Upstream version: @opentelemetry/instrumentation-hapi@0.64.0 - * - Types vendored from @hapi/hapi as simplified interfaces - */ -/* eslint-disable */ - -import type * as Hapi from './hapi-types'; - -export const HapiComponentName = '@hapi/hapi'; - -/** - * This symbol is used to mark a Hapi route handler or server extension handler as - * already patched, since its possible to use these handlers multiple times - * i.e. when allowing multiple versions of one plugin, or when registering a plugin - * multiple times on different servers. - */ -export const handlerPatched: unique symbol = Symbol('hapi-handler-patched'); - -export type HapiServerRouteInputMethod = (route: HapiServerRouteInput) => void; - -export type HapiServerRouteInput = PatchableServerRoute | PatchableServerRoute[]; - -export type PatchableServerRoute = Hapi.ServerRoute & { - [handlerPatched]?: boolean; -}; - -export type HapiPluginObject = Hapi.ServerRegisterPluginObject; - -export type HapiPluginInput = HapiPluginObject | Array>; - -export type RegisterFunction = (plugin: HapiPluginInput, options?: Hapi.ServerRegisterOptions) => Promise; - -export type PatchableExtMethod = Hapi.Lifecycle.Method & { - [handlerPatched]?: boolean; -}; - -export type ServerExtDirectInput = [ - Hapi.ServerRequestExtType, - Hapi.Lifecycle.Method, - (Hapi.ServerExtOptions | undefined)?, -]; - -export const HapiLayerType = { - ROUTER: 'router', - PLUGIN: 'plugin', - EXT: 'server.ext', -}; - -export const HapiLifecycleMethodNames = new Set([ - 'onPreAuth', - 'onCredentials', - 'onPostAuth', - 'onPreHandler', - 'onPostHandler', - 'onPreResponse', - 'onRequest', -]); diff --git a/packages/node/src/integrations/tracing/hapi/vendored/utils.ts b/packages/node/src/integrations/tracing/hapi/vendored/utils.ts deleted file mode 100644 index 0b35c8bac885..000000000000 --- a/packages/node/src/integrations/tracing/hapi/vendored/utils.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-hapi - * - Upstream version: @opentelemetry/instrumentation-hapi@0.64.0 - * - Types vendored from @hapi/hapi as simplified interfaces - */ - -import type { Attributes } from '@opentelemetry/api'; -import { HTTP_METHOD, HTTP_ROUTE } from '@sentry/conventions/attributes'; -import type * as Hapi from './hapi-types'; -import { - HapiLayerType, - HapiLifecycleMethodNames, - type HapiPluginObject, - type PatchableExtMethod, - type ServerExtDirectInput, -} from './internal-types'; -import { AttributeNames } from './enums/AttributeNames'; - -export function getPluginName(plugin: Hapi.Plugin): string { - if ((plugin as Hapi.PluginNameVersion).name) { - return (plugin as Hapi.PluginNameVersion).name; - } else { - return (plugin as Hapi.PluginPackage).pkg.name; - } -} - -export const isLifecycleExtType = (variableToCheck: unknown): variableToCheck is Hapi.ServerRequestExtType => { - return typeof variableToCheck === 'string' && HapiLifecycleMethodNames.has(variableToCheck); -}; - -export const isLifecycleExtEventObj = ( - variableToCheck: unknown, -): variableToCheck is Hapi.ServerExtEventsRequestObject => { - const event = (variableToCheck as Hapi.ServerExtEventsRequestObject)?.type; - return event !== undefined && isLifecycleExtType(event); -}; - -export const isDirectExtInput = (variableToCheck: unknown): variableToCheck is ServerExtDirectInput => { - return ( - Array.isArray(variableToCheck) && - variableToCheck.length <= 3 && - isLifecycleExtType(variableToCheck[0]) && - typeof variableToCheck[1] === 'function' - ); -}; - -export const isPatchableExtMethod = ( - variableToCheck: PatchableExtMethod | PatchableExtMethod[], -): variableToCheck is PatchableExtMethod => { - return !Array.isArray(variableToCheck); -}; - -export const getRouteMetadata = ( - route: Hapi.ServerRoute, - pluginName?: string, -): { - attributes: Attributes; - name: string; -} => { - const attributes: Attributes = { - [HTTP_ROUTE]: route.path, - // eslint-disable-next-line typescript/no-deprecated - [HTTP_METHOD]: route.method, - }; - - let name; - if (pluginName) { - attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.PLUGIN; - attributes[AttributeNames.PLUGIN_NAME] = pluginName; - name = `${pluginName}: route - ${route.path}`; - } else { - attributes[AttributeNames.HAPI_TYPE] = HapiLayerType.ROUTER; - name = `route - ${route.path}`; - } - - return { attributes, name }; -}; - -export const getExtMetadata = ( - extPoint: Hapi.ServerRequestExtType, - pluginName?: string, - methodName?: string, -): { - attributes: Attributes; - name: string; -} => { - let baseName = `ext - ${extPoint}`; - if (methodName && methodName !== 'method') { - // method is the default name for the extension in the ServerExtEventsObject format. - baseName = `ext - ${extPoint} - ${methodName}`; - } - if (pluginName) { - return { - attributes: { - [AttributeNames.EXT_TYPE]: extPoint, - [AttributeNames.HAPI_TYPE]: HapiLayerType.EXT, - [AttributeNames.PLUGIN_NAME]: pluginName, - }, - name: `${pluginName}: ${baseName}`, - }; - } - return { - attributes: { - [AttributeNames.EXT_TYPE]: extPoint, - [AttributeNames.HAPI_TYPE]: HapiLayerType.EXT, - }, - name: baseName, - }; -}; - -export const getPluginFromInput = (pluginObj: HapiPluginObject): Hapi.Plugin => { - if ('plugin' in pluginObj) { - if ('plugin' in pluginObj.plugin) { - return pluginObj.plugin.plugin; - } - return pluginObj.plugin; - } - return pluginObj; -}; diff --git a/packages/node/test/integrations/tracing/hapi.test.ts b/packages/node/test/integrations/tracing/hapi.test.ts deleted file mode 100644 index a11d93099d62..000000000000 --- a/packages/node/test/integrations/tracing/hapi.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { - getExtMetadata, - getPluginName, - getRouteMetadata, - isDirectExtInput, - isLifecycleExtType, - isPatchableExtMethod, -} from '../../../src/integrations/tracing/hapi/vendored/utils'; - -describe('getRouteMetadata', () => { - const route = { path: '/users/{id}', method: 'get' } as any; - - it('describes a directly-registered route as a router layer', () => { - expect(getRouteMetadata(route)).toEqual({ - name: 'route - /users/{id}', - attributes: { - 'http.route': '/users/{id}', - 'http.method': 'get', - 'hapi.type': 'router', - }, - }); - }); - - it('describes a plugin-registered route as a plugin layer', () => { - expect(getRouteMetadata(route, 'my-plugin')).toEqual({ - name: 'my-plugin: route - /users/{id}', - attributes: { - 'http.route': '/users/{id}', - 'http.method': 'get', - 'hapi.type': 'plugin', - 'hapi.plugin.name': 'my-plugin', - }, - }); - }); -}); - -describe('getExtMetadata', () => { - it('names an extension by its point', () => { - expect(getExtMetadata('onPreHandler')).toEqual({ - name: 'ext - onPreHandler', - attributes: { 'server.ext.type': 'onPreHandler', 'hapi.type': 'server.ext' }, - }); - }); - - it('includes the method name when it is not the default `method`', () => { - expect(getExtMetadata('onPreHandler', undefined, 'myHandler').name).toBe('ext - onPreHandler - myHandler'); - expect(getExtMetadata('onPreHandler', undefined, 'method').name).toBe('ext - onPreHandler'); - }); - - it('includes the plugin name and prefixes the span name', () => { - expect(getExtMetadata('onPreHandler', 'my-plugin')).toEqual({ - name: 'my-plugin: ext - onPreHandler', - attributes: { - 'server.ext.type': 'onPreHandler', - 'hapi.type': 'server.ext', - 'hapi.plugin.name': 'my-plugin', - }, - }); - }); -}); - -describe('getPluginName', () => { - it('reads the name property when present', () => { - expect(getPluginName({ name: 'direct-name' } as any)).toBe('direct-name'); - }); - - it('falls back to the package name', () => { - expect(getPluginName({ pkg: { name: 'pkg-name' } } as any)).toBe('pkg-name'); - }); -}); - -describe('ext type guards', () => { - it('isLifecycleExtType recognizes lifecycle points', () => { - expect(isLifecycleExtType('onPreHandler')).toBe(true); - expect(isLifecycleExtType('onPreStart')).toBe(false); - expect(isLifecycleExtType(undefined)).toBe(false); - }); - - it('isDirectExtInput recognizes the [type, method] tuple form', () => { - expect(isDirectExtInput(['onPreHandler', () => {}])).toBe(true); - expect(isDirectExtInput(['onPreHandler', 'not-a-fn'])).toBe(false); - expect(isDirectExtInput({ type: 'onPreHandler' })).toBe(false); - }); - - it('isPatchableExtMethod is false for arrays', () => { - expect(isPatchableExtMethod((() => {}) as any)).toBe(true); - expect(isPatchableExtMethod([() => {}] as any)).toBe(false); - }); -});