/** * Main telemetry middleware service * This is the primary service class for creating unified telemetry middleware * * NOTE: TypeScript errors have been mostly resolved by: * - Removing conflicting local type aliases * - Using inline union types matching the core package * - Proper variable type inference with const assertions * * Remaining TypeScript warnings are related to strict type inference * and do not affect functionality. */ import { BaseFailure, Either, ProcessStepFn } from '@inh-lib/common'; import { type UnifiedMiddleware, type UnifiedHttpContext, UnifiedRouteHandler, UnifiedPreHandlerFn, UnifiedHandlerFn, UnifiedRoutePipeline } from '@inh-lib/unified-route'; import type { UnifiedTelemetryProvider, UnifiedTelemetrySpan, UnifiedTelemetryLogger, UnifiedTelemetrySpanMetadata } from '@inh-lib/unified-telemetry-core'; import type { TelemetryOperationType, TelemetryLayerType, TelemetryAttributes } from '../internal/types/telemetry.types'; import type { GetActiveSpanOptions } from '../internal/types/span-extraction.types'; import { InitializeTelemetryContextResult } from '../types/telemetry.types'; /** * Configuration for telemetry middleware */ export interface TelemetryMiddlewareConfig { /** Service name for telemetry */ serviceName: string; /** Service version for telemetry */ serviceVersion?: string; /** Enable metrics collection */ enableMetrics?: boolean; /** Enable distributed tracing */ enableTracing?: boolean; /** Enable resource tracking (CPU/Memory) */ enableResourceTracking?: boolean; /** Enable trace extraction from headers */ enableTraceExtraction?: boolean; /** Enable correlation ID generation */ enableCorrelationId?: boolean; /** Enable system metrics monitoring */ enableSystemMetrics?: boolean; /** System metrics update interval in milliseconds */ systemMetricsInterval?: number; /** Enable cleanup of registry after request (default: true) */ enableRegistryCleanup?: boolean; /** Custom attributes to add to all spans */ customAttributes?: TelemetryAttributes; } /** * Main service class for creating telemetry middleware * it must be singleton and initialized once per application */ export declare class TelemetryMiddlewareService { private readonly config; private readonly dependencies; private readonly extractor; private readonly metricsCollector; private readonly resourceTracker; private readonly systemMetricsMonitor; constructor(provider: UnifiedTelemetryProvider, config: TelemetryMiddlewareConfig); /** * Deprecated Create telemetry middleware for unified-route. * So InitializeContext and FinalizeContext methods instead */ createMiddleware(): UnifiedMiddleware; /** * Create system telemetry that runs independently */ createSystemTelemetry(serviceName: string): { start: () => void; stop: () => void; }; /** * Get trace headers for outgoing requests */ getTraceHeaders(context: UnifiedHttpContext): Record; /** * Manual telemetry recording for custom operations */ recordCustomMetrics(method: string, route: string, statusCode: number, durationSeconds: number, memoryBytes?: number, cpuSeconds?: number): void; /** * Shutdown telemetry service */ shutdown(): Promise; /** * Create child span from paraent if no parent then fall back parent as root span but no change active span in context */ createChildSpan(context: UnifiedHttpContext, operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; attributes?: TelemetryAttributes; }): { span: UnifiedTelemetrySpan; logger: UnifiedTelemetryLogger; finish: () => void; }; /** * Create child span (it will be root span when no parent) and set active span in unified context */ createActiveSpan(context: UnifiedHttpContext, operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; attributes?: TelemetryAttributes; }): { span: UnifiedTelemetrySpan; logger: UnifiedTelemetryLogger; finish: () => void; }; /** * Creates a UnifiedMiddleware that wraps an operation in a telemetry span, logs start/end, * records exceptions, and ensures the span is finished. * * The returned middleware: * - Creates an active span via createActiveSpan with the provided operation metadata. * - Optionally logs an "operation started" message when the middleware begins. * - Invokes the next middleware/handler and, on success, sets the span status to "ok" * and optionally logs a completion message including the operation duration in milliseconds. * - On error, records the exception on the span, sets the span status to "error" (including * the error message), logs the error with contextual fields, and rethrows the original error. * - Always calls finish() to end the span in a finally block. * * Note: Duration is measured using process.hrtime.bigint() and converted to milliseconds. * * @param operationName - A human-readable name for the operation (used in span and logs). * @param options - Configuration for the operation span and logging behavior. * @param options.operationType - Telemetry operation type for the span (defaults to TELEMETRY_OPERATION_TYPES.CUSTOM if not provided). * @param options.layer - Telemetry layer for the span (defaults to TELEMETRY_LAYERS.CUSTOM if not provided). * @param options.logStart - If set to false, suppresses the start log. Defaults to true. * @param options.logEnd - If set to false, suppresses the end/success log. Defaults to true. * @param options.attributes - Additional attributes to attach to the created span. * * @returns A UnifiedMiddleware function: (context, next) => Promise. The middleware manages telemetry * for the operation and must be awaited (i.e., returns a Promise that resolves when next() completes). * * @throws Re-throws any error thrown by downstream middleware/handler after recording it on the span. * * @example * // Create middleware for a business operation in the service layer: * const middleware = service.createOperationProcess('CreateOrder', { * operationType: TELEMETRY_OPERATION_TYPES.BUSINESS, * layer: TELEMETRY_LAYERS.SERVICE, * logStart: true, * logEnd: true, * attributes: { feature: 'ordering' }, * }); * * // Use the middleware in a pipeline: * await middleware(context, next); */ createOperationProcess(operationName: string, options: { operationType: TelemetryOperationType; layer: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; createHttpEndpointProcess(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; createHttpMiddlewareProcess(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; /** * Create a middleware step known as preHandler for an API endpoint operation with telemetry instrumentation. * * This is a convenience wrapper around createOperationProcess that fills common defaults * for endpoint instrumentation (operation type and layer) and default logging behavior. * * @param operationName - The name of the operation/endpoint being instrumented. Used as the primary * identifier for telemetry events produced by the middleware. * @param options - Optional configuration for the created middleware. * @param options.operationType - The telemetry operation type for this endpoint. Defaults to * TELEMETRY_OPERATION_TYPES.ENDPOINT. * @param options.layer - The telemetry layer for this operation. Defaults to TELEMETRY_LAYERS.API. * @param options.logStart - Whether to emit a "start" telemetry event when the middleware begins. * Defaults to true. * @param options.logEnd - Whether to emit an "end" telemetry event when the middleware completes. * Defaults to true. * @param options.attributes - Optional additional telemetry attributes to attach to events created * by this middleware. * * @returns A UnifiedMiddleware function that wraps the operation with telemetry collection and * logging according to the provided options. * * @example * const middleware = createApiEndpointProcess("getUser", { * layer: TELEMETRY_LAYERS.API, * logStart: true, * logEnd: true, * attributes: { featureFlag: "user-v2" } * }); */ createApiEndpointProcess(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; createApiMiddlewareProcess(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; createDataLogicProcess(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; createDatabaseProcess(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; /** * Create operation type middleware for specific operations */ createOperationTypeStep(operationName: string, options: { operationType: TelemetryOperationType; layer: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; /** * Deprecated . to keep for backward compatibility * Create API middleware for specific operations */ createBusinessLogicMiddleware(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; /** * Create API middleware for specific operations */ createApiMiddlewareStep(operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; /** * Create validation middleware with specific validation context */ createValidationMiddleware(validationName: string, options?: { layer?: TelemetryLayerType; logValidationDetails?: boolean; attributes?: TelemetryAttributes; }): UnifiedMiddleware; /** * Get current span from context (for manual span operations) */ getCurrentSpan(context: UnifiedHttpContext): UnifiedTelemetrySpan | Error; /** * Get current logger from context (creates new logger for current span) */ getCurrentLogger(context: UnifiedHttpContext): UnifiedTelemetryLogger | Error; /** * Get active span without requiring UnifiedHttpContext * Useful for framework-specific hooks and standalone operations * * Strategy: Active Span → Extract from Headers → Create Fallback */ /** * Get active span without requiring UnifiedHttpContext * Useful for framework-specific hooks and standalone operations * * Strategy: Active Span → Extract from Headers → Create Fallback */ getActiveSpanWithoutUnifiedContext(headers?: Record, fallbackOptions?: GetActiveSpanOptions): UnifiedTelemetrySpan | null; /** * Create child span without requiring UnifiedHttpContext * Useful for framework-specific hooks where UnifiedHttpContext is not available */ createChildSpanWithoutUnifiedContext(parentSpanOrHeaders: UnifiedTelemetrySpanMetadata | { headers: Record; }, operationName: string, options?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; attributes?: TelemetryAttributes; }): { span: UnifiedTelemetrySpan; logger: UnifiedTelemetryLogger; finish: () => void; }; /** * create TraceContext and Usage Request snapshot and keep it's in UnifiedHttpContext * Extract TraceContext format W3C and then B3 then if not found create new span W3C format and store it in UnifiedHttpContext * */ initializeContext(context: UnifiedHttpContext): UnifiedHttpContext; /** * Static helper to initialize telemetry context outside of instance */ getInitializeContext(context: UnifiedHttpContext): InitializeTelemetryContextResult; /** * * cleanup UnifiedHttpContext after request end and record performance data metrics * */ finalizeContext(context: UnifiedHttpContext, statusCode?: number): Promise; /** * * update Route info in UnifiedHttpContext for Lifecycle that routeInfo is available * like Fastify hooks route path is available at preHandler hook * */ updateRouteInfo(context: UnifiedHttpContext, method: string, route: string, url: string): Promise; /** * Get active telemetry (logger, span, traceId) from context * this method expect telemetry middleware is already initialized in context * using in by Handler and preHandler function of UnifiedRoutePipeline * UnifiedTelemetryProcessor will create active span and logger in context */ getActiveTelemetry(context: UnifiedHttpContext): { telemetryLogger: UnifiedTelemetryLogger; telemetrySpan: UnifiedTelemetrySpan; traceId?: string; }; createProcessStepWithTelemetry(context: UnifiedHttpContext, fn: ProcessStepFn, operationName: string, options: { operationType: TelemetryOperationType; layer: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): ProcessStepFn; executeApiLogicStep(context: UnifiedHttpContext, stepFunction: ProcessStepFn, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeDbStep(context: UnifiedHttpContext, stepFunction: ProcessStepFn, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeExternalEndpointStep(context: UnifiedHttpContext, stepFunction: ProcessStepFn, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeStep(context: UnifiedHttpContext, stepFunction: ProcessStepFn, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeFunctionWithApiLogicSpan(context: UnifiedHttpContext, fn: (params: TInput) => Either | Promise>, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeFunctionWithExternalEndpointSpan(context: UnifiedHttpContext, fn: (params: TInput) => Either | Promise>, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeFunctionWithDbSpan(context: UnifiedHttpContext, fn: (params: TInput) => Either | Promise>, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; executeFunctionWithTelemetry(context: UnifiedHttpContext, fn: (params: TInput) => Either | Promise>, input: TInput, spanOptions?: { operationType?: TelemetryOperationType; layer?: TelemetryLayerType; logStart?: boolean; logEnd?: boolean; attributes?: TelemetryAttributes; }): Promise>; } export type MakeRouteStepsInut = { propContext: { telemetryService: TelemetryMiddlewareService; }; input: { preHandlers: UnifiedPreHandlerFn[]; handler: UnifiedHandlerFn; }; }; export type MakeRouteStepsOutput = { preHandlerSteps: UnifiedPreHandlerFn[]; handlerStep: UnifiedHandlerFn; }; export declare function makeRouteSteps(params: MakeRouteStepsInut): MakeRouteStepsOutput; export type MakeEndpointHandlerInput = { propContext: { telemetryService: TelemetryMiddlewareService; }; input: { preHandlers: UnifiedPreHandlerFn[]; handler: UnifiedHandlerFn; pipeline: UnifiedRoutePipeline; }; }; export declare const makeEndpointHandler: (params: MakeEndpointHandlerInput) => UnifiedRouteHandler;