@@ -207,3 +207,81 @@ const extractLayerPathSegment = (arg: LayerPathSegment) => {
207207
208208 return ;
209209} ;
210+
211+ export function getConstructedRoute ( req : {
212+ originalUrl : PatchedRequest [ 'originalUrl' ] ;
213+ [ _LAYERS_STORE_PROPERTY ] ?: string [ ] ;
214+ } ) {
215+ const layersStore : string [ ] = Array . isArray ( req [ _LAYERS_STORE_PROPERTY ] )
216+ ? ( req [ _LAYERS_STORE_PROPERTY ] as string [ ] )
217+ : [ ] ;
218+
219+ const meaningfulPaths = layersStore . filter (
220+ path => path !== '/' && path !== '/*'
221+ ) ;
222+
223+ // Handle standalone wildcard case
224+ if ( meaningfulPaths . length === 1 && meaningfulPaths [ 0 ] === '*' ) {
225+ return '*' ;
226+ }
227+
228+ // Construct the route by joining paths and normalizing
229+ return meaningfulPaths . join ( '' ) . replace ( / \/ { 2 , } / g, '/' ) ; // Remove duplicate slashes
230+ }
231+
232+ /**
233+ * Extracts the actual matched route from Express request for OpenTelemetry instrumentation.
234+ * Returns the route that should be used as the http.route attribute.
235+ *
236+ * @param req - The Express request object with layers store
237+ * @param layersStoreProperty - The property name where layer paths are stored
238+ * @returns The matched route string or undefined if no valid route is found
239+ */
240+ export function getActualMatchedRoute ( req : {
241+ originalUrl : PatchedRequest [ 'originalUrl' ] ;
242+ [ _LAYERS_STORE_PROPERTY ] ?: string [ ] ;
243+ } ) : string | undefined {
244+ const layersStore : string [ ] = Array . isArray ( req [ _LAYERS_STORE_PROPERTY ] )
245+ ? ( req [ _LAYERS_STORE_PROPERTY ] as string [ ] )
246+ : [ ] ;
247+
248+ // If no layers are stored, no route can be determined
249+ if ( layersStore . length === 0 ) {
250+ return undefined ;
251+ }
252+
253+ // Handle root path case - if all paths are root, only return root if originalUrl is also root
254+ if ( layersStore . every ( path => path === '/' ) ) {
255+ return req . originalUrl === '/' ? '/' : undefined ;
256+ }
257+
258+ const constructedRoute = getConstructedRoute ( req ) ;
259+ if ( constructedRoute === '*' ) {
260+ return constructedRoute ;
261+ }
262+
263+ // Ensure route starts with '/' if it doesn't already
264+ const normalizedRoute = constructedRoute . startsWith ( '/' )
265+ ? constructedRoute
266+ : `/${ constructedRoute } ` ;
267+
268+ // Validate that this appears to be a matched route
269+ // A route is considered matched if:
270+ // 1. We have a constructed route
271+ // 2. The original URL matches or starts with our route pattern
272+ const isValidRoute =
273+ normalizedRoute . length > 0 &&
274+ ( req . originalUrl === normalizedRoute ||
275+ req . originalUrl . startsWith ( normalizedRoute ) ||
276+ isRoutePattern ( normalizedRoute ) ) ;
277+
278+ return isValidRoute ? normalizedRoute : undefined ;
279+ }
280+
281+ /**
282+ * Checks if a route contains parameter patterns (e.g., :id, :userId)
283+ * which are valid even if they don't exactly match the original URL
284+ */
285+ function isRoutePattern ( route : string ) : boolean {
286+ return route . includes ( ':' ) || route . includes ( '*' ) ;
287+ }
0 commit comments