From e9cf19b9593f147df491fcb399b1c54d6332de89 Mon Sep 17 00:00:00 2001 From: Tucker Fitzgerald Date: Mon, 4 Nov 2024 16:04:12 -0500 Subject: [PATCH 1/2] Adding ignored routes and descriptive operations names --- src/telemetry/instrumentations.ts | 50 ++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/telemetry/instrumentations.ts b/src/telemetry/instrumentations.ts index 5988746..aa01ba7 100644 --- a/src/telemetry/instrumentations.ts +++ b/src/telemetry/instrumentations.ts @@ -1,13 +1,16 @@ import type { Instrumentation } from '@opentelemetry/instrumentation'; import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns'; -import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; +import { ExpressInstrumentation, ExpressInstrumentationConfig } from '@opentelemetry/instrumentation-express'; import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici'; import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool'; -import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; +import { HttpInstrumentation, HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http'; import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'; import { NetInstrumentation } from '@opentelemetry/instrumentation-net'; import { PgInstrumentation } from '@opentelemetry/instrumentation-pg'; import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; +import { Span } from '@opentelemetry/api'; +import { IncomingMessage, ClientRequest } from 'http'; +import { Request } from 'express'; const InstrumentationMap = { '@opentelemetry/instrumentation-http': HttpInstrumentation, @@ -25,17 +28,56 @@ const InstrumentationMap = { type ConfigArg = T extends new (...args: infer U) => unknown ? U[0] : never; export type InstrumentationConfigMap = { [Name in keyof typeof InstrumentationMap]?: ConfigArg<(typeof InstrumentationMap)[Name]>; +} & { + // Add optional global ignore patterns + ignoreIncomingPaths?: string[]; }; +// Add default ignored endpoints +const DEFAULT_IGNORED_ENDPOINTS = ['/health', '/metrics']; + +// Add helper function to create span names +function createSpanName(method: string, route: string): string { + return `${method.toUpperCase()} ${route}`; +} + export function getAutoInstrumentations( inputConfigs: InstrumentationConfigMap = {}, ): Instrumentation[] { const keys = Object.keys(InstrumentationMap) as Array; + const ignorePaths = [...DEFAULT_IGNORED_ENDPOINTS, ...(inputConfigs.ignoreIncomingPaths || [])]; + return keys .map((name) => { const Instance = InstrumentationMap[name]; - // Defaults are defined by the instrumentation itself - const userConfig = inputConfigs[name] ?? {}; + // Create a base config from user input or empty object + const userConfig = { ...(inputConfigs[name] || {}) }; + + // Configure HTTP instrumentation + if (name === '@opentelemetry/instrumentation-http') { + const httpConfig = userConfig as HttpInstrumentationConfig; + httpConfig.ignoreIncomingRequestHook = (request) => { + const path = request.url?.split('?')[0] || '/'; + return ignorePaths.includes(path); + }; + httpConfig.requestHook = (span, request) => { + const method = request.method || 'UNKNOWN'; + const path = (request instanceof IncomingMessage ? request.url : request.path)?.split('?')[0] || '/'; + span.updateName(createSpanName(method, path)); + }; + } + + // Configure Express instrumentation + if (name === '@opentelemetry/instrumentation-express') { + const expressConfig = userConfig as ExpressInstrumentationConfig; + expressConfig.ignoreLayers = ignorePaths; + expressConfig.requestHook = (span, req) => { + const method = req.request?.method || 'UNKNOWN'; + // Use the matched route path instead of raw URL if available + const route = (req.request as any).route?.path || req.request?.url?.split('?')[0] || '/'; + span.updateName(createSpanName(method, route)); + }; + } try { return new Instance(userConfig); From b6f68fadbbf84783ac7ef6d037e89354742b8837 Mon Sep 17 00:00:00 2001 From: Tucker Fitzgerald Date: Mon, 4 Nov 2024 16:18:07 -0500 Subject: [PATCH 2/2] Addressing linting errors --- src/telemetry/instrumentations.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/telemetry/instrumentations.ts b/src/telemetry/instrumentations.ts index aa01ba7..065bc5e 100644 --- a/src/telemetry/instrumentations.ts +++ b/src/telemetry/instrumentations.ts @@ -1,3 +1,6 @@ +import { IncomingMessage} from 'http'; + +import type { Request } from 'express'; import type { Instrumentation } from '@opentelemetry/instrumentation'; import { DnsInstrumentation } from '@opentelemetry/instrumentation-dns'; import { ExpressInstrumentation, ExpressInstrumentationConfig } from '@opentelemetry/instrumentation-express'; @@ -8,9 +11,6 @@ import { IORedisInstrumentation } from '@opentelemetry/instrumentation-ioredis'; import { NetInstrumentation } from '@opentelemetry/instrumentation-net'; import { PgInstrumentation } from '@opentelemetry/instrumentation-pg'; import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; -import { Span } from '@opentelemetry/api'; -import { IncomingMessage, ClientRequest } from 'http'; -import { Request } from 'express'; const InstrumentationMap = { '@opentelemetry/instrumentation-http': HttpInstrumentation, @@ -74,7 +74,7 @@ export function getAutoInstrumentations( expressConfig.requestHook = (span, req) => { const method = req.request?.method || 'UNKNOWN'; // Use the matched route path instead of raw URL if available - const route = (req.request as any).route?.path || req.request?.url?.split('?')[0] || '/'; + const route = (req.request as Request).route?.path || req.request?.url?.split('?')[0] || '/'; span.updateName(createSpanName(method, route)); }; }