11import type { Span } from '@opentelemetry/api' ;
22import { context , SpanStatusCode , trace } from '@opentelemetry/api' ;
3+ import type { InstrumentationConfig } from '@opentelemetry/instrumentation' ;
34import { InstrumentationBase , InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation' ;
45import { isThenable } from '@sentry/core' ;
56import { AttributeNames , HonoTypes } from './constants' ;
@@ -18,12 +19,21 @@ import type {
1819const PACKAGE_NAME = '@sentry/instrumentation-hono' ;
1920const PACKAGE_VERSION = '0.0.1' ;
2021
22+ export interface HonoResponseHookFunction {
23+ ( span : Span ) : void ;
24+ }
25+
26+ export interface HonoInstrumentationConfig extends InstrumentationConfig {
27+ /** Function for adding custom span attributes from the response */
28+ responseHook ?: HonoResponseHookFunction ;
29+ }
30+
2131/**
2232 * Hono instrumentation for OpenTelemetry
2333 */
24- export class HonoInstrumentation extends InstrumentationBase {
25- public constructor ( ) {
26- super ( PACKAGE_NAME , PACKAGE_VERSION , { } ) ;
34+ export class HonoInstrumentation extends InstrumentationBase < HonoInstrumentationConfig > {
35+ public constructor ( config : HonoInstrumentationConfig = { } ) {
36+ super ( PACKAGE_NAME , PACKAGE_VERSION , config ) ;
2737 }
2838
2939 /**
@@ -86,23 +96,13 @@ export class HonoInstrumentation extends InstrumentationBase {
8696 const handlers = args . slice ( 1 ) ;
8797 return original . apply ( this , [
8898 path ,
89- ...handlers . map ( ( handler , index ) =>
90- instrumentation . _wrapHandler (
91- index + 1 === handlers . length ? HonoTypes . REQUEST_HANDLER : HonoTypes . MIDDLEWARE ,
92- handler as Handler | MiddlewareHandler ,
93- ) ,
94- ) ,
99+ ...handlers . map ( handler => instrumentation . _wrapHandler ( handler as Handler | MiddlewareHandler ) ) ,
95100 ] ) ;
96101 }
97102
98103 return original . apply (
99104 this ,
100- args . map ( ( handler , index ) =>
101- instrumentation . _wrapHandler (
102- index + 1 === args . length ? HonoTypes . REQUEST_HANDLER : HonoTypes . MIDDLEWARE ,
103- handler as Handler | MiddlewareHandler ,
104- ) ,
105- ) ,
105+ args . map ( handler => instrumentation . _wrapHandler ( handler as Handler | MiddlewareHandler ) ) ,
106106 ) ;
107107 } ;
108108 } ;
@@ -120,12 +120,7 @@ export class HonoInstrumentation extends InstrumentationBase {
120120 const handlers = args . slice ( 2 ) ;
121121 return original . apply ( this , [
122122 ...args . slice ( 0 , 2 ) ,
123- ...handlers . map ( ( handler , index ) =>
124- instrumentation . _wrapHandler (
125- index + 1 === handlers . length ? HonoTypes . REQUEST_HANDLER : HonoTypes . MIDDLEWARE ,
126- handler as Handler | MiddlewareHandler ,
127- ) ,
128- ) ,
123+ ...handlers . map ( handler => instrumentation . _wrapHandler ( handler as Handler | MiddlewareHandler ) ) ,
129124 ] ) ;
130125 } ;
131126 } ;
@@ -149,15 +144,13 @@ export class HonoInstrumentation extends InstrumentationBase {
149144 const handlers = args . slice ( 1 ) ;
150145 return original . apply ( this , [
151146 path ,
152- ...handlers . map ( handler =>
153- instrumentation . _wrapHandler ( HonoTypes . MIDDLEWARE , handler as MiddlewareHandler ) ,
154- ) ,
147+ ...handlers . map ( handler => instrumentation . _wrapHandler ( handler as MiddlewareHandler ) ) ,
155148 ] ) ;
156149 }
157150
158151 return original . apply (
159152 this ,
160- args . map ( handler => instrumentation . _wrapHandler ( HonoTypes . MIDDLEWARE , handler as MiddlewareHandler ) ) ,
153+ args . map ( handler => instrumentation . _wrapHandler ( handler as MiddlewareHandler ) ) ,
161154 ) ;
162155 } ;
163156 } ;
@@ -166,7 +159,7 @@ export class HonoInstrumentation extends InstrumentationBase {
166159 /**
167160 * Wraps a handler or middleware handler to apply instrumentation.
168161 */
169- private _wrapHandler ( type : HonoTypes , handler : Handler | MiddlewareHandler ) : Handler | MiddlewareHandler {
162+ private _wrapHandler ( handler : Handler | MiddlewareHandler ) : Handler | MiddlewareHandler {
170163 // eslint-disable-next-line @typescript-eslint/no-this-alias
171164 const instrumentation = this ;
172165
@@ -176,17 +169,32 @@ export class HonoInstrumentation extends InstrumentationBase {
176169 }
177170
178171 const path = c . req . path ;
179- const spanName = `${ type . replace ( '_' , ' ' ) } - ${ path } ` ;
180- const span = instrumentation . tracer . startSpan ( spanName , {
181- attributes : {
182- [ AttributeNames . HONO_TYPE ] : type ,
183- [ AttributeNames . HONO_NAME ] : type === 'request_handler' ? path : handler . name || 'anonymous' ,
184- } ,
185- } ) ;
172+ const span = instrumentation . tracer . startSpan ( path ) ;
186173
187174 return context . with ( trace . setSpan ( context . active ( ) , span ) , ( ) => {
188175 return instrumentation . _safeExecute (
189- ( ) => handler . apply ( this , [ c , next ] ) ,
176+ ( ) => {
177+ const result = handler . apply ( this , [ c , next ] ) ;
178+ if ( isThenable ( result ) ) {
179+ return result . then ( result => {
180+ const type = instrumentation . _determineHandlerType ( result ) ;
181+ span . setAttributes ( {
182+ [ AttributeNames . HONO_TYPE ] : type ,
183+ [ AttributeNames . HONO_NAME ] : type === HonoTypes . REQUEST_HANDLER ? path : handler . name || 'anonymous' ,
184+ } ) ;
185+ instrumentation . getConfig ( ) . responseHook ?.( span ) ;
186+ return result ;
187+ } ) ;
188+ } else {
189+ const type = instrumentation . _determineHandlerType ( result ) ;
190+ span . setAttributes ( {
191+ [ AttributeNames . HONO_TYPE ] : type ,
192+ [ AttributeNames . HONO_NAME ] : type === HonoTypes . REQUEST_HANDLER ? path : handler . name || 'anonymous' ,
193+ } ) ;
194+ instrumentation . getConfig ( ) . responseHook ?.( span ) ;
195+ return result ;
196+ }
197+ } ,
190198 ( ) => span . end ( ) ,
191199 error => {
192200 instrumentation . _handleError ( span , error ) ;
@@ -221,6 +229,15 @@ export class HonoInstrumentation extends InstrumentationBase {
221229 }
222230 }
223231
232+ /**
233+ * Determines the handler type based on the result.
234+ * @param result
235+ * @private
236+ */
237+ private _determineHandlerType ( result : unknown ) : HonoTypes {
238+ return result === undefined ? HonoTypes . MIDDLEWARE : HonoTypes . REQUEST_HANDLER ;
239+ }
240+
224241 /**
225242 * Handles errors by setting the span status and recording the exception.
226243 */
0 commit comments