@backendkit-labs/observability 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +367 -0
- package/dist/index.cjs +592 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +216 -0
- package/dist/index.d.ts +216 -0
- package/dist/index.js +562 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/otel.ts","../src/correlation/correlation.service.ts","../src/observability.constants.ts","../src/logger/winston-http.transport.ts","../src/logger/logger.service.ts","../src/metrics/metrics.service.ts","../src/interceptors/correlation.interceptor.ts","../src/interceptors/performance.interceptor.ts","../src/filters/all-exceptions.filter.ts","../src/observability.module.ts","../src/decorators/track-performance.decorator.ts"],"names":["AsyncLocalStorage","CorrelationIdService","randomUUID","Injectable","TransportStream","http","https","axios","CircuitBreaker","CircuitBreakerOpenError","LoggerService","transports","winston","Optional","TRANSPORT_CB_DEFAULTS","MetricsService","http2","https2","CircuitBreakerState","Logger","Inject","CorrelationInterceptor","Observable","tap","PerformanceInterceptor","AllExceptionsFilter","HttpException","HttpStatus","Catch","ObservabilityModule","Module"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Optional OpenTelemetry shim.\n * If @opentelemetry/api is not installed all operations become no-ops,\n * so the package works without any tracing backend.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet otel: any = null;\n\ntry {\n // Dynamic require keeps OTel out of the bundle when not installed\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n otel = require('@opentelemetry/api');\n} catch {\n // OTel not installed — spans will be no-ops\n}\n\nexport const isOtelAvailable = (): boolean => otel !== null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const getTracer = (name: string): any =>\n otel?.trace?.getTracer(name) ?? noopTracer;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const getActiveSpan = (): any =>\n otel ? otel.trace.getSpan(otel.context.active()) : undefined;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const runInOtelContext = async <T>(span: any, fn: () => Promise<T>): Promise<T> => {\n if (!otel || !span) return fn();\n return otel.context.with(otel.trace.setSpan(otel.context.active(), span), fn);\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst noopSpan: any = {\n end: () => {},\n setAttribute: () => {},\n setAttributes: () => {},\n recordException: () => {},\n setStatus: () => {},\n spanContext: () => ({ traceId: '', spanId: '' }),\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst noopTracer: any = {\n startSpan: () => noopSpan,\n startActiveSpan: (_name: string, fn: (span: unknown) => unknown) => fn(noopSpan),\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { Injectable } from '@nestjs/common';\nimport { randomUUID } from 'node:crypto';\nimport { getActiveSpan } from '../internal/otel.js';\n\nconst storage = new AsyncLocalStorage<string>();\n\n@Injectable()\nexport class CorrelationIdService {\n /**\n * Run `fn` inside a context that carries `correlationId`.\n * All code executed within `fn` (including async continuations) can call\n * `get()` and receive the same ID without passing it explicitly.\n */\n run<T>(correlationId: string, fn: () => T): T {\n return storage.run(correlationId, fn);\n }\n\n /** Current correlation ID, or a fresh UUID when called outside a context. */\n get(): string {\n return storage.getStore() ?? randomUUID();\n }\n\n /**\n * Current correlation ID, or `undefined` when called outside a context.\n * Prefer `get()` for logging; use this only when you need to distinguish\n * \"no context\" from \"context with a random ID\".\n */\n getOrUndefined(): string | undefined {\n return storage.getStore();\n }\n\n /**\n * Active OTel trace + span IDs when @opentelemetry/api is installed and a\n * span is active; `undefined` otherwise.\n */\n getTraceContext(): { traceId: string; spanId: string } | undefined {\n const span = getActiveSpan();\n if (!span) return undefined;\n const ctx = span.spanContext?.();\n if (!ctx?.traceId) return undefined;\n return { traceId: ctx.traceId, spanId: ctx.spanId };\n }\n}\n","export const OBSERVABILITY_OPTIONS = 'OBSERVABILITY_OPTIONS' as const;\n","import TransportStream, { TransportStreamOptions } from 'winston-transport';\nimport axios, { AxiosInstance } from 'axios';\nimport * as http from 'node:http';\nimport * as https from 'node:https';\nimport {\n CircuitBreaker,\n CircuitBreakerConfig,\n CircuitBreakerOpenError,\n} from '@backendkit-labs/circuit-breaker';\n\nexport interface WinstonHttpTransportOptions extends TransportStreamOptions {\n /** Full URL of the log-ingest endpoint. */\n url: string;\n\n /** Bearer token sent in `Authorization` header. */\n authToken?: string;\n\n /** Additional static headers merged into every request. */\n headers?: Record<string, string>;\n\n /** Flush batch when it reaches this many entries (default 100). */\n batchSize?: number;\n\n /** Maximum entries held in the in-memory buffer (default 2000). */\n maxBufferSize?: number;\n\n /** Flush interval in ms — also flushes on `close()` (default 5000). */\n flushIntervalMs?: number;\n\n /** Request timeout in ms (default 5000). */\n timeoutMs?: number;\n\n /**\n * Override any circuit breaker config fields.\n * `name` and `isFailure` are set internally and cannot be overridden.\n *\n * Transport defaults: failureThreshold 60%, slidingWindowSize 5,\n * minimumCalls 3, openTimeoutMs 30 000, halfOpenMaxCalls 1.\n */\n circuitBreaker?: Partial<Omit<CircuitBreakerConfig, 'name' | 'isFailure'>>;\n}\n\ninterface LogEntry {\n level: string;\n message: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\nconst TRANSPORT_CB_DEFAULTS: Omit<CircuitBreakerConfig, 'name' | 'isFailure'> = {\n failureThreshold: 60,\n slowCallThreshold: 100,\n slowCallDurationMs: 60_000,\n minimumCalls: 3,\n slidingWindowSize: 5,\n halfOpenMaxCalls: 1,\n openTimeoutMs: 30_000,\n};\n\nexport class WinstonHttpTransport extends TransportStream {\n private readonly client: AxiosInstance;\n private readonly cb: CircuitBreaker;\n private readonly buffer: LogEntry[] = [];\n private readonly batchSize: number;\n private readonly maxBufferSize: number;\n private readonly flushTimer: ReturnType<typeof setInterval>;\n\n constructor(opts: WinstonHttpTransportOptions) {\n super(opts);\n\n this.batchSize = opts.batchSize ?? 100;\n this.maxBufferSize = opts.maxBufferSize ?? 2_000;\n\n const keepAlive = new http.Agent({ keepAlive: true });\n const keepAliveHttps = new https.Agent({ keepAlive: true });\n\n this.client = axios.create({\n baseURL: opts.url,\n timeout: opts.timeoutMs ?? 5_000,\n httpAgent: keepAlive,\n httpsAgent: keepAliveHttps,\n headers: {\n 'Content-Type': 'application/json',\n ...(opts.authToken ? { Authorization: `Bearer ${opts.authToken}` } : {}),\n ...opts.headers,\n },\n });\n\n this.cb = new CircuitBreaker({\n ...TRANSPORT_CB_DEFAULTS,\n ...opts.circuitBreaker,\n name: 'WinstonHttpTransport',\n isFailure: () => true,\n });\n\n this.flushTimer = setInterval(\n () => { void this.flush(); },\n opts.flushIntervalMs ?? 5_000,\n );\n this.flushTimer.unref?.();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n override log(info: any, callback: () => void): void {\n setImmediate(() => this.emit('logged', info));\n\n if (this.buffer.length < this.maxBufferSize) {\n this.buffer.push(info as LogEntry);\n }\n // silently drop when full — buffer-full warn would cause infinite recursion\n\n if (this.buffer.length >= this.batchSize) {\n void this.flush();\n }\n\n callback();\n }\n\n /** Flush remaining buffer on graceful shutdown. */\n override async close(): Promise<void> {\n clearInterval(this.flushTimer);\n await this.flush();\n }\n\n private async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n\n const batch = this.buffer.splice(0, this.batchSize);\n\n try {\n await this.cb.execute(() => this.client.post('', batch));\n } catch (err) {\n // Re-queue the batch (whether CB was open or the request failed)\n const room = this.maxBufferSize - this.buffer.length;\n if (room > 0) this.buffer.unshift(...batch.slice(0, room));\n\n if (!(err instanceof CircuitBreakerOpenError)) {\n // Network errors are worth logging; CB-open state was already surfaced\n // via onStateChange in the CircuitBreaker itself\n console.error(`[WinstonHttpTransport] flush failed — re-queued ${batch.length} entries`, err);\n }\n }\n }\n}\n","import { Injectable, Inject, Optional, LoggerService as NestLoggerService } from '@nestjs/common';\nimport * as winston from 'winston';\nimport { CorrelationIdService } from '../correlation/correlation.service.js';\nimport { OBSERVABILITY_OPTIONS } from '../observability.constants.js';\nimport { ObservabilityOptions } from '../observability.types.js';\nimport { WinstonHttpTransport } from './winston-http.transport.js';\n\n@Injectable()\nexport class LoggerService implements NestLoggerService {\n private readonly winston: winston.Logger;\n\n constructor(\n @Inject(OBSERVABILITY_OPTIONS)\n private readonly opts: ObservabilityOptions,\n @Optional()\n private readonly correlationSvc?: CorrelationIdService,\n ) {\n const transports: winston.transport[] = [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const extra = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';\n return `${timestamp} [${level}] ${message}${extra}`;\n }),\n ),\n }),\n ];\n\n if (opts.http) {\n transports.push(\n new WinstonHttpTransport({\n ...opts.http,\n format: winston.format.json(),\n }),\n );\n }\n\n this.winston = winston.createLogger({\n level: opts.logLevel ?? 'info',\n transports,\n format: winston.format.json(),\n });\n }\n\n log(message: string, context?: string): void {\n this.winston.info(message, this.buildMeta(context));\n }\n\n error(message: string, trace?: string, context?: string): void {\n this.winston.error(message, { ...this.buildMeta(context), trace });\n }\n\n warn(message: string, context?: string): void {\n this.winston.warn(message, this.buildMeta(context));\n }\n\n debug(message: string, context?: string): void {\n this.winston.debug(message, this.buildMeta(context));\n }\n\n verbose(message: string, context?: string): void {\n this.winston.verbose(message, this.buildMeta(context));\n }\n\n /** Log with additional arbitrary metadata. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n logWithMeta(level: string, message: string, meta: Record<string, any>): void {\n this.winston.log(level, message, { ...this.buildMeta(), ...meta });\n }\n\n private buildMeta(context?: string): Record<string, unknown> {\n const base: Record<string, unknown> = {\n service: this.opts.serviceName,\n environment: this.opts.environment ?? 'production',\n correlationId: this.correlationSvc?.get(),\n };\n if (context) base.context = context;\n return base;\n }\n}\n","import { Injectable, Inject, Optional, OnModuleDestroy, Logger } from '@nestjs/common';\nimport axios, { AxiosInstance } from 'axios';\nimport * as http from 'node:http';\nimport * as https from 'node:https';\nimport {\n CircuitBreaker,\n CircuitBreakerConfig,\n CircuitBreakerOpenError,\n CircuitBreakerState,\n} from '@backendkit-labs/circuit-breaker';\nimport { CorrelationIdService } from '../correlation/correlation.service.js';\nimport { OBSERVABILITY_OPTIONS } from '../observability.constants.js';\nimport { ObservabilityOptions, MetricEvent } from '../observability.types.js';\n\nconst TRANSPORT_CB_DEFAULTS: Omit<CircuitBreakerConfig, 'name' | 'isFailure'> = {\n failureThreshold: 60,\n slowCallThreshold: 100,\n slowCallDurationMs: 60_000,\n minimumCalls: 3,\n slidingWindowSize: 5,\n halfOpenMaxCalls: 1,\n openTimeoutMs: 30_000,\n};\n\n@Injectable()\nexport class MetricsService implements OnModuleDestroy {\n private readonly client: AxiosInstance | null = null;\n private readonly cb: CircuitBreaker | null = null;\n private readonly logger = new Logger(MetricsService.name);\n private readonly buffer: MetricEvent[] = [];\n private readonly maxBufferSize: number = 5_000;\n private readonly flushTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(\n @Inject(OBSERVABILITY_OPTIONS)\n private readonly opts: ObservabilityOptions,\n @Optional()\n private readonly correlationSvc?: CorrelationIdService,\n ) {\n if (!opts.metrics) return;\n\n const m = opts.metrics;\n this.maxBufferSize = m.maxBufferSize ?? 5_000;\n\n const keepAlive = new http.Agent({ keepAlive: true });\n const keepAliveHttps = new https.Agent({ keepAlive: true });\n\n this.client = axios.create({\n baseURL: m.url,\n timeout: m.timeoutMs ?? 5_000,\n httpAgent: keepAlive,\n httpsAgent: keepAliveHttps,\n headers: {\n 'Content-Type': 'application/json',\n ...(m.authToken ? { Authorization: `Bearer ${m.authToken}` } : {}),\n ...m.headers,\n },\n });\n\n this.cb = new CircuitBreaker({\n ...TRANSPORT_CB_DEFAULTS,\n ...m.circuitBreaker,\n name: 'MetricsService',\n isFailure: () => true,\n onStateChange: (from, to, metrics) => {\n if (to === CircuitBreakerState.OPEN) {\n this.logger.warn(\n `[MetricsService] circuit breaker OPEN — pausing metric sends for ${(m.circuitBreaker?.openTimeoutMs ?? TRANSPORT_CB_DEFAULTS.openTimeoutMs) / 1_000}s`,\n metrics,\n );\n } else if (to === CircuitBreakerState.CLOSED && from !== CircuitBreakerState.HALF_OPEN) {\n this.logger.log(`[MetricsService] circuit breaker CLOSED — recovered`);\n }\n m.circuitBreaker?.onStateChange?.(from, to, metrics);\n },\n });\n\n this.flushTimer = setInterval(\n () => { void this.flush(); },\n m.flushIntervalMs ?? 10_000,\n );\n this.flushTimer.unref?.();\n }\n\n /**\n * Enqueue a metric event. Fire-and-forget; batched and sent on the next\n * flush interval or when the buffer reaches `maxBufferSize`.\n */\n record(\n name: string,\n value: number,\n options?: { unit?: string; tags?: Record<string, string> },\n ): void {\n if (!this.client) return;\n\n if (this.buffer.length >= this.maxBufferSize) {\n this.logger.warn('[MetricsService] buffer full — dropping metric');\n return;\n }\n\n this.buffer.push({\n name,\n value,\n unit: options?.unit,\n tags: options?.tags,\n timestamp: new Date().toISOString(),\n serviceName: this.opts.serviceName,\n environment: this.opts.environment ?? 'production',\n correlationId: this.correlationSvc?.getOrUndefined(),\n });\n }\n\n /** Flush on graceful shutdown. */\n async onModuleDestroy(): Promise<void> {\n if (this.flushTimer) clearInterval(this.flushTimer);\n await this.flush();\n }\n\n private async flush(): Promise<void> {\n if (!this.client || this.buffer.length === 0) return;\n\n const batch = this.buffer.splice(0, 500);\n\n try {\n await this.cb!.execute(() => this.client!.post('', batch));\n } catch (err) {\n // Re-queue in both cases (CB open or network error)\n const room = this.maxBufferSize - this.buffer.length;\n if (room > 0) this.buffer.unshift(...batch.slice(0, room));\n\n if (!(err instanceof CircuitBreakerOpenError)) {\n this.logger.warn(\n `[MetricsService] flush failed — re-queueing ${batch.length} events`,\n err,\n );\n }\n }\n }\n}\n","import {\n Injectable,\n NestInterceptor,\n ExecutionContext,\n CallHandler,\n Inject,\n} from '@nestjs/common';\nimport { Observable } from 'rxjs';\nimport { tap } from 'rxjs/operators';\nimport { randomUUID } from 'node:crypto';\nimport { CorrelationIdService } from '../correlation/correlation.service.js';\n\nconst CORRELATION_HEADER = 'x-correlation-id';\n\n@Injectable()\nexport class CorrelationInterceptor implements NestInterceptor {\n constructor(\n @Inject(CorrelationIdService)\n private readonly correlationSvc: CorrelationIdService,\n ) {}\n\n intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown> {\n const req = ctx.switchToHttp().getRequest<Record<string, unknown>>();\n const res = ctx.switchToHttp().getResponse<{\n setHeader(name: string, value: string): void;\n }>();\n\n const incomingId =\n (req.headers as Record<string, string | undefined>)?.[CORRELATION_HEADER];\n const correlationId = (typeof incomingId === 'string' && incomingId)\n ? incomingId\n : randomUUID();\n\n res.setHeader(CORRELATION_HEADER, correlationId);\n\n return new Observable(subscriber => {\n this.correlationSvc.run(correlationId, () => {\n next.handle().pipe(\n tap({ error: () => {} }),\n ).subscribe(subscriber);\n });\n });\n }\n}\n","import {\n Injectable,\n NestInterceptor,\n ExecutionContext,\n CallHandler,\n Inject,\n Optional,\n} from '@nestjs/common';\nimport { Observable } from 'rxjs';\nimport { tap } from 'rxjs/operators';\nimport { LoggerService } from '../logger/logger.service.js';\nimport { MetricsService } from '../metrics/metrics.service.js';\nimport { CorrelationIdService } from '../correlation/correlation.service.js';\nimport { getActiveSpan } from '../internal/otel.js';\n\n@Injectable()\nexport class PerformanceInterceptor implements NestInterceptor {\n constructor(\n @Inject(LoggerService)\n private readonly logger: LoggerService,\n @Optional()\n @Inject(MetricsService)\n private readonly metrics: MetricsService | undefined,\n @Optional()\n @Inject(CorrelationIdService)\n private readonly correlationSvc: CorrelationIdService | undefined,\n ) {}\n\n intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown> {\n const start = Date.now();\n const req = ctx.switchToHttp().getRequest<{\n method: string;\n url: string;\n }>();\n const method = req.method ?? 'UNKNOWN';\n const path = req.url ?? 'UNKNOWN';\n\n return next.handle().pipe(\n tap({\n next: () => {\n const durationMs = Date.now() - start;\n this.record(method, path, 'success', durationMs);\n },\n error: () => {\n const durationMs = Date.now() - start;\n this.record(method, path, 'error', durationMs);\n },\n }),\n );\n }\n\n private record(\n method: string,\n path: string,\n outcome: 'success' | 'error',\n durationMs: number,\n ): void {\n const correlationId = this.correlationSvc?.getOrUndefined();\n const span = getActiveSpan();\n\n span?.setAttribute('http.method', method);\n span?.setAttribute('http.target', path);\n span?.setAttribute('http.duration_ms', durationMs);\n\n this.logger.logWithMeta('info', `${method} ${path} [${outcome}] ${durationMs}ms`, {\n method,\n path,\n outcome,\n durationMs,\n correlationId,\n });\n\n this.metrics?.record('http.request.duration', durationMs, {\n unit: 'ms',\n tags: { method, path, outcome },\n });\n }\n}\n","import {\n ExceptionFilter,\n Catch,\n ArgumentsHost,\n HttpException,\n HttpStatus,\n Inject,\n Optional,\n} from '@nestjs/common';\nimport { LoggerService } from '../logger/logger.service.js';\nimport { CorrelationIdService } from '../correlation/correlation.service.js';\nimport { getActiveSpan } from '../internal/otel.js';\n\nexport type ErrorMapper = (error: unknown) => {\n statusCode: number;\n message: string;\n code?: string;\n} | null;\n\n@Catch()\nexport class AllExceptionsFilter implements ExceptionFilter {\n private readonly mappers: ErrorMapper[] = [];\n\n constructor(\n @Inject(LoggerService)\n private readonly logger: LoggerService,\n @Optional()\n @Inject(CorrelationIdService)\n private readonly correlationSvc: CorrelationIdService | undefined,\n ) {}\n\n /**\n * Register a custom error mapper.\n * Mappers are tried in order; the first non-null result wins.\n * Return `null` to fall through to the next mapper.\n */\n addMapper(mapper: ErrorMapper): this {\n this.mappers.push(mapper);\n return this;\n }\n\n catch(exception: unknown, host: ArgumentsHost): void {\n const ctx = host.switchToHttp();\n const res = ctx.getResponse<{\n status(code: number): { json(body: unknown): void };\n }>();\n\n const mapped = this.resolveError(exception);\n\n const correlationId = this.correlationSvc?.getOrUndefined();\n const span = getActiveSpan();\n span?.recordException(exception instanceof Error ? exception : new Error(String(exception)));\n\n this.logger.error(\n mapped.message,\n exception instanceof Error ? exception.stack : undefined,\n AllExceptionsFilter.name,\n );\n\n res.status(mapped.statusCode).json({\n ok: false,\n statusCode: mapped.statusCode,\n message: mapped.message,\n code: mapped.code,\n correlationId,\n timestamp: new Date().toISOString(),\n });\n }\n\n private resolveError(exception: unknown): {\n statusCode: number;\n message: string;\n code?: string;\n } {\n for (const mapper of this.mappers) {\n const result = mapper(exception);\n if (result !== null) return result;\n }\n\n if (exception instanceof HttpException) {\n const body = exception.getResponse();\n const message =\n typeof body === 'string'\n ? body\n : (body as { message?: string }).message ?? exception.message;\n return { statusCode: exception.getStatus(), message };\n }\n\n return {\n statusCode: HttpStatus.INTERNAL_SERVER_ERROR,\n message: 'Internal server error',\n };\n }\n}\n","import { DynamicModule, Module, Provider } from '@nestjs/common';\nimport { CorrelationIdService } from './correlation/correlation.service.js';\nimport { LoggerService } from './logger/logger.service.js';\nimport { MetricsService } from './metrics/metrics.service.js';\nimport { CorrelationInterceptor } from './interceptors/correlation.interceptor.js';\nimport { PerformanceInterceptor } from './interceptors/performance.interceptor.js';\nimport { AllExceptionsFilter } from './filters/all-exceptions.filter.js';\nimport { OBSERVABILITY_OPTIONS } from './observability.constants.js';\nimport { ObservabilityOptions } from './observability.types.js';\n\n@Module({})\nexport class ObservabilityModule {\n static forRoot(options: ObservabilityOptions): DynamicModule {\n const optionsProvider: Provider = {\n provide: OBSERVABILITY_OPTIONS,\n useValue: options,\n };\n\n const providers: Provider[] = [\n optionsProvider,\n CorrelationIdService,\n LoggerService,\n MetricsService,\n CorrelationInterceptor,\n PerformanceInterceptor,\n AllExceptionsFilter,\n ];\n\n return {\n module: ObservabilityModule,\n global: true,\n providers,\n exports: [\n CorrelationIdService,\n LoggerService,\n MetricsService,\n CorrelationInterceptor,\n PerformanceInterceptor,\n AllExceptionsFilter,\n ],\n };\n }\n}\n","import { getTracer, runInOtelContext } from '../internal/otel.js';\n\nexport interface TrackPerformanceOptions {\n /** OTel span / log operation name. Defaults to `ClassName.methodName`. */\n operation?: string;\n\n /** Attributes added to the OTel span. */\n attributes?: Record<string, string | number | boolean>;\n}\n\n/**\n * Method decorator that wraps the decorated async method in an OTel span\n * (when @opentelemetry/api is available) and records its duration.\n * Works with regular methods and NestJS service methods.\n *\n * @example\n * \\@TrackPerformance()\n * async processPayment(id: string) { ... }\n */\nexport function TrackPerformance(options: TrackPerformanceOptions = {}): MethodDecorator {\n return function (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n ): PropertyDescriptor {\n const original = descriptor.value as (...args: unknown[]) => Promise<unknown>;\n const operationName =\n options.operation ?? `${target.constructor.name}.${String(propertyKey)}`;\n\n descriptor.value = async function (...args: unknown[]): Promise<unknown> {\n const tracer = getTracer('@backendkit-labs/observability');\n const span = tracer.startSpan(operationName);\n\n if (options.attributes) {\n span.setAttributes(options.attributes);\n }\n\n try {\n const result = await runInOtelContext(span, () => original.apply(this, args));\n span.setStatus({ code: 1 }); // SpanStatusCode.OK\n return result;\n } catch (err) {\n span.recordException(err instanceof Error ? err : new Error(String(err)));\n span.setStatus({ code: 2, message: String(err) }); // SpanStatusCode.ERROR\n throw err;\n } finally {\n span.end();\n }\n };\n\n return descriptor;\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { DynamicModule, LoggerService as LoggerService$1, OnModuleDestroy, NestInterceptor, ExecutionContext, CallHandler, ExceptionFilter, ArgumentsHost } from '@nestjs/common';
|
|
2
|
+
import { CircuitBreakerConfig } from '@backendkit-labs/circuit-breaker';
|
|
3
|
+
import TransportStream, { TransportStreamOptions } from 'winston-transport';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
interface WinstonHttpTransportOptions extends TransportStreamOptions {
|
|
7
|
+
/** Full URL of the log-ingest endpoint. */
|
|
8
|
+
url: string;
|
|
9
|
+
/** Bearer token sent in `Authorization` header. */
|
|
10
|
+
authToken?: string;
|
|
11
|
+
/** Additional static headers merged into every request. */
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
/** Flush batch when it reaches this many entries (default 100). */
|
|
14
|
+
batchSize?: number;
|
|
15
|
+
/** Maximum entries held in the in-memory buffer (default 2000). */
|
|
16
|
+
maxBufferSize?: number;
|
|
17
|
+
/** Flush interval in ms — also flushes on `close()` (default 5000). */
|
|
18
|
+
flushIntervalMs?: number;
|
|
19
|
+
/** Request timeout in ms (default 5000). */
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Override any circuit breaker config fields.
|
|
23
|
+
* `name` and `isFailure` are set internally and cannot be overridden.
|
|
24
|
+
*
|
|
25
|
+
* Transport defaults: failureThreshold 60%, slidingWindowSize 5,
|
|
26
|
+
* minimumCalls 3, openTimeoutMs 30 000, halfOpenMaxCalls 1.
|
|
27
|
+
*/
|
|
28
|
+
circuitBreaker?: Partial<Omit<CircuitBreakerConfig, 'name' | 'isFailure'>>;
|
|
29
|
+
}
|
|
30
|
+
declare class WinstonHttpTransport extends TransportStream {
|
|
31
|
+
private readonly client;
|
|
32
|
+
private readonly cb;
|
|
33
|
+
private readonly buffer;
|
|
34
|
+
private readonly batchSize;
|
|
35
|
+
private readonly maxBufferSize;
|
|
36
|
+
private readonly flushTimer;
|
|
37
|
+
constructor(opts: WinstonHttpTransportOptions);
|
|
38
|
+
log(info: any, callback: () => void): void;
|
|
39
|
+
/** Flush remaining buffer on graceful shutdown. */
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
private flush;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ObservabilityOptions {
|
|
45
|
+
/** Identifies this service in every log entry and metric. */
|
|
46
|
+
serviceName: string;
|
|
47
|
+
/** E.g. "production", "staging". Defaults to "production". */
|
|
48
|
+
environment?: string;
|
|
49
|
+
/** Minimum log level (winston levels). Defaults to "info". */
|
|
50
|
+
logLevel?: 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
|
|
51
|
+
/**
|
|
52
|
+
* When present, logs are also shipped to a remote HTTP endpoint.
|
|
53
|
+
* Omit to keep logs local-only.
|
|
54
|
+
*/
|
|
55
|
+
http?: Omit<WinstonHttpTransportOptions, 'format'>;
|
|
56
|
+
/**
|
|
57
|
+
* When present, metrics are pushed to a remote HTTP endpoint.
|
|
58
|
+
* Omit to disable metric shipping.
|
|
59
|
+
*/
|
|
60
|
+
metrics?: MetricsOptions;
|
|
61
|
+
}
|
|
62
|
+
interface MetricsOptions {
|
|
63
|
+
/** Full URL of the metrics-ingest endpoint. */
|
|
64
|
+
url: string;
|
|
65
|
+
/** Bearer token sent in `Authorization` header. */
|
|
66
|
+
authToken?: string;
|
|
67
|
+
/** Additional static headers merged into every request. */
|
|
68
|
+
headers?: Record<string, string>;
|
|
69
|
+
/** Flush interval in ms (default 10 000). */
|
|
70
|
+
flushIntervalMs?: number;
|
|
71
|
+
/** Maximum events held in the in-memory buffer (default 5000). */
|
|
72
|
+
maxBufferSize?: number;
|
|
73
|
+
/** Request timeout in ms (default 5000). */
|
|
74
|
+
timeoutMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Override any circuit breaker config fields.
|
|
77
|
+
* `name` and `isFailure` are set internally and cannot be overridden.
|
|
78
|
+
*
|
|
79
|
+
* Transport defaults: failureThreshold 60%, slidingWindowSize 5,
|
|
80
|
+
* minimumCalls 3, openTimeoutMs 30 000, halfOpenMaxCalls 1.
|
|
81
|
+
*/
|
|
82
|
+
circuitBreaker?: Partial<Omit<CircuitBreakerConfig, 'name' | 'isFailure'>>;
|
|
83
|
+
}
|
|
84
|
+
interface MetricEvent {
|
|
85
|
+
name: string;
|
|
86
|
+
value: number;
|
|
87
|
+
unit?: string;
|
|
88
|
+
tags?: Record<string, string>;
|
|
89
|
+
timestamp: string;
|
|
90
|
+
serviceName: string;
|
|
91
|
+
environment: string;
|
|
92
|
+
correlationId?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
declare class ObservabilityModule {
|
|
96
|
+
static forRoot(options: ObservabilityOptions): DynamicModule;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
declare class CorrelationIdService {
|
|
100
|
+
/**
|
|
101
|
+
* Run `fn` inside a context that carries `correlationId`.
|
|
102
|
+
* All code executed within `fn` (including async continuations) can call
|
|
103
|
+
* `get()` and receive the same ID without passing it explicitly.
|
|
104
|
+
*/
|
|
105
|
+
run<T>(correlationId: string, fn: () => T): T;
|
|
106
|
+
/** Current correlation ID, or a fresh UUID when called outside a context. */
|
|
107
|
+
get(): string;
|
|
108
|
+
/**
|
|
109
|
+
* Current correlation ID, or `undefined` when called outside a context.
|
|
110
|
+
* Prefer `get()` for logging; use this only when you need to distinguish
|
|
111
|
+
* "no context" from "context with a random ID".
|
|
112
|
+
*/
|
|
113
|
+
getOrUndefined(): string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Active OTel trace + span IDs when @opentelemetry/api is installed and a
|
|
116
|
+
* span is active; `undefined` otherwise.
|
|
117
|
+
*/
|
|
118
|
+
getTraceContext(): {
|
|
119
|
+
traceId: string;
|
|
120
|
+
spanId: string;
|
|
121
|
+
} | undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
declare class LoggerService implements LoggerService$1 {
|
|
125
|
+
private readonly opts;
|
|
126
|
+
private readonly correlationSvc?;
|
|
127
|
+
private readonly winston;
|
|
128
|
+
constructor(opts: ObservabilityOptions, correlationSvc?: CorrelationIdService | undefined);
|
|
129
|
+
log(message: string, context?: string): void;
|
|
130
|
+
error(message: string, trace?: string, context?: string): void;
|
|
131
|
+
warn(message: string, context?: string): void;
|
|
132
|
+
debug(message: string, context?: string): void;
|
|
133
|
+
verbose(message: string, context?: string): void;
|
|
134
|
+
/** Log with additional arbitrary metadata. */
|
|
135
|
+
logWithMeta(level: string, message: string, meta: Record<string, any>): void;
|
|
136
|
+
private buildMeta;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
declare class MetricsService implements OnModuleDestroy {
|
|
140
|
+
private readonly opts;
|
|
141
|
+
private readonly correlationSvc?;
|
|
142
|
+
private readonly client;
|
|
143
|
+
private readonly cb;
|
|
144
|
+
private readonly logger;
|
|
145
|
+
private readonly buffer;
|
|
146
|
+
private readonly maxBufferSize;
|
|
147
|
+
private readonly flushTimer;
|
|
148
|
+
constructor(opts: ObservabilityOptions, correlationSvc?: CorrelationIdService | undefined);
|
|
149
|
+
/**
|
|
150
|
+
* Enqueue a metric event. Fire-and-forget; batched and sent on the next
|
|
151
|
+
* flush interval or when the buffer reaches `maxBufferSize`.
|
|
152
|
+
*/
|
|
153
|
+
record(name: string, value: number, options?: {
|
|
154
|
+
unit?: string;
|
|
155
|
+
tags?: Record<string, string>;
|
|
156
|
+
}): void;
|
|
157
|
+
/** Flush on graceful shutdown. */
|
|
158
|
+
onModuleDestroy(): Promise<void>;
|
|
159
|
+
private flush;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
declare class CorrelationInterceptor implements NestInterceptor {
|
|
163
|
+
private readonly correlationSvc;
|
|
164
|
+
constructor(correlationSvc: CorrelationIdService);
|
|
165
|
+
intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
declare class PerformanceInterceptor implements NestInterceptor {
|
|
169
|
+
private readonly logger;
|
|
170
|
+
private readonly metrics;
|
|
171
|
+
private readonly correlationSvc;
|
|
172
|
+
constructor(logger: LoggerService, metrics: MetricsService | undefined, correlationSvc: CorrelationIdService | undefined);
|
|
173
|
+
intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
174
|
+
private record;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
type ErrorMapper = (error: unknown) => {
|
|
178
|
+
statusCode: number;
|
|
179
|
+
message: string;
|
|
180
|
+
code?: string;
|
|
181
|
+
} | null;
|
|
182
|
+
declare class AllExceptionsFilter implements ExceptionFilter {
|
|
183
|
+
private readonly logger;
|
|
184
|
+
private readonly correlationSvc;
|
|
185
|
+
private readonly mappers;
|
|
186
|
+
constructor(logger: LoggerService, correlationSvc: CorrelationIdService | undefined);
|
|
187
|
+
/**
|
|
188
|
+
* Register a custom error mapper.
|
|
189
|
+
* Mappers are tried in order; the first non-null result wins.
|
|
190
|
+
* Return `null` to fall through to the next mapper.
|
|
191
|
+
*/
|
|
192
|
+
addMapper(mapper: ErrorMapper): this;
|
|
193
|
+
catch(exception: unknown, host: ArgumentsHost): void;
|
|
194
|
+
private resolveError;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface TrackPerformanceOptions {
|
|
198
|
+
/** OTel span / log operation name. Defaults to `ClassName.methodName`. */
|
|
199
|
+
operation?: string;
|
|
200
|
+
/** Attributes added to the OTel span. */
|
|
201
|
+
attributes?: Record<string, string | number | boolean>;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Method decorator that wraps the decorated async method in an OTel span
|
|
205
|
+
* (when @opentelemetry/api is available) and records its duration.
|
|
206
|
+
* Works with regular methods and NestJS service methods.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* \@TrackPerformance()
|
|
210
|
+
* async processPayment(id: string) { ... }
|
|
211
|
+
*/
|
|
212
|
+
declare function TrackPerformance(options?: TrackPerformanceOptions): MethodDecorator;
|
|
213
|
+
|
|
214
|
+
declare const OBSERVABILITY_OPTIONS: "OBSERVABILITY_OPTIONS";
|
|
215
|
+
|
|
216
|
+
export { AllExceptionsFilter, CorrelationIdService, CorrelationInterceptor, type ErrorMapper, LoggerService, type MetricEvent, type MetricsOptions, MetricsService, OBSERVABILITY_OPTIONS, ObservabilityModule, type ObservabilityOptions, PerformanceInterceptor, TrackPerformance, type TrackPerformanceOptions, WinstonHttpTransport, type WinstonHttpTransportOptions };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { DynamicModule, LoggerService as LoggerService$1, OnModuleDestroy, NestInterceptor, ExecutionContext, CallHandler, ExceptionFilter, ArgumentsHost } from '@nestjs/common';
|
|
2
|
+
import { CircuitBreakerConfig } from '@backendkit-labs/circuit-breaker';
|
|
3
|
+
import TransportStream, { TransportStreamOptions } from 'winston-transport';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
|
|
6
|
+
interface WinstonHttpTransportOptions extends TransportStreamOptions {
|
|
7
|
+
/** Full URL of the log-ingest endpoint. */
|
|
8
|
+
url: string;
|
|
9
|
+
/** Bearer token sent in `Authorization` header. */
|
|
10
|
+
authToken?: string;
|
|
11
|
+
/** Additional static headers merged into every request. */
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
/** Flush batch when it reaches this many entries (default 100). */
|
|
14
|
+
batchSize?: number;
|
|
15
|
+
/** Maximum entries held in the in-memory buffer (default 2000). */
|
|
16
|
+
maxBufferSize?: number;
|
|
17
|
+
/** Flush interval in ms — also flushes on `close()` (default 5000). */
|
|
18
|
+
flushIntervalMs?: number;
|
|
19
|
+
/** Request timeout in ms (default 5000). */
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Override any circuit breaker config fields.
|
|
23
|
+
* `name` and `isFailure` are set internally and cannot be overridden.
|
|
24
|
+
*
|
|
25
|
+
* Transport defaults: failureThreshold 60%, slidingWindowSize 5,
|
|
26
|
+
* minimumCalls 3, openTimeoutMs 30 000, halfOpenMaxCalls 1.
|
|
27
|
+
*/
|
|
28
|
+
circuitBreaker?: Partial<Omit<CircuitBreakerConfig, 'name' | 'isFailure'>>;
|
|
29
|
+
}
|
|
30
|
+
declare class WinstonHttpTransport extends TransportStream {
|
|
31
|
+
private readonly client;
|
|
32
|
+
private readonly cb;
|
|
33
|
+
private readonly buffer;
|
|
34
|
+
private readonly batchSize;
|
|
35
|
+
private readonly maxBufferSize;
|
|
36
|
+
private readonly flushTimer;
|
|
37
|
+
constructor(opts: WinstonHttpTransportOptions);
|
|
38
|
+
log(info: any, callback: () => void): void;
|
|
39
|
+
/** Flush remaining buffer on graceful shutdown. */
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
private flush;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ObservabilityOptions {
|
|
45
|
+
/** Identifies this service in every log entry and metric. */
|
|
46
|
+
serviceName: string;
|
|
47
|
+
/** E.g. "production", "staging". Defaults to "production". */
|
|
48
|
+
environment?: string;
|
|
49
|
+
/** Minimum log level (winston levels). Defaults to "info". */
|
|
50
|
+
logLevel?: 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
|
|
51
|
+
/**
|
|
52
|
+
* When present, logs are also shipped to a remote HTTP endpoint.
|
|
53
|
+
* Omit to keep logs local-only.
|
|
54
|
+
*/
|
|
55
|
+
http?: Omit<WinstonHttpTransportOptions, 'format'>;
|
|
56
|
+
/**
|
|
57
|
+
* When present, metrics are pushed to a remote HTTP endpoint.
|
|
58
|
+
* Omit to disable metric shipping.
|
|
59
|
+
*/
|
|
60
|
+
metrics?: MetricsOptions;
|
|
61
|
+
}
|
|
62
|
+
interface MetricsOptions {
|
|
63
|
+
/** Full URL of the metrics-ingest endpoint. */
|
|
64
|
+
url: string;
|
|
65
|
+
/** Bearer token sent in `Authorization` header. */
|
|
66
|
+
authToken?: string;
|
|
67
|
+
/** Additional static headers merged into every request. */
|
|
68
|
+
headers?: Record<string, string>;
|
|
69
|
+
/** Flush interval in ms (default 10 000). */
|
|
70
|
+
flushIntervalMs?: number;
|
|
71
|
+
/** Maximum events held in the in-memory buffer (default 5000). */
|
|
72
|
+
maxBufferSize?: number;
|
|
73
|
+
/** Request timeout in ms (default 5000). */
|
|
74
|
+
timeoutMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Override any circuit breaker config fields.
|
|
77
|
+
* `name` and `isFailure` are set internally and cannot be overridden.
|
|
78
|
+
*
|
|
79
|
+
* Transport defaults: failureThreshold 60%, slidingWindowSize 5,
|
|
80
|
+
* minimumCalls 3, openTimeoutMs 30 000, halfOpenMaxCalls 1.
|
|
81
|
+
*/
|
|
82
|
+
circuitBreaker?: Partial<Omit<CircuitBreakerConfig, 'name' | 'isFailure'>>;
|
|
83
|
+
}
|
|
84
|
+
interface MetricEvent {
|
|
85
|
+
name: string;
|
|
86
|
+
value: number;
|
|
87
|
+
unit?: string;
|
|
88
|
+
tags?: Record<string, string>;
|
|
89
|
+
timestamp: string;
|
|
90
|
+
serviceName: string;
|
|
91
|
+
environment: string;
|
|
92
|
+
correlationId?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
declare class ObservabilityModule {
|
|
96
|
+
static forRoot(options: ObservabilityOptions): DynamicModule;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
declare class CorrelationIdService {
|
|
100
|
+
/**
|
|
101
|
+
* Run `fn` inside a context that carries `correlationId`.
|
|
102
|
+
* All code executed within `fn` (including async continuations) can call
|
|
103
|
+
* `get()` and receive the same ID without passing it explicitly.
|
|
104
|
+
*/
|
|
105
|
+
run<T>(correlationId: string, fn: () => T): T;
|
|
106
|
+
/** Current correlation ID, or a fresh UUID when called outside a context. */
|
|
107
|
+
get(): string;
|
|
108
|
+
/**
|
|
109
|
+
* Current correlation ID, or `undefined` when called outside a context.
|
|
110
|
+
* Prefer `get()` for logging; use this only when you need to distinguish
|
|
111
|
+
* "no context" from "context with a random ID".
|
|
112
|
+
*/
|
|
113
|
+
getOrUndefined(): string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Active OTel trace + span IDs when @opentelemetry/api is installed and a
|
|
116
|
+
* span is active; `undefined` otherwise.
|
|
117
|
+
*/
|
|
118
|
+
getTraceContext(): {
|
|
119
|
+
traceId: string;
|
|
120
|
+
spanId: string;
|
|
121
|
+
} | undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
declare class LoggerService implements LoggerService$1 {
|
|
125
|
+
private readonly opts;
|
|
126
|
+
private readonly correlationSvc?;
|
|
127
|
+
private readonly winston;
|
|
128
|
+
constructor(opts: ObservabilityOptions, correlationSvc?: CorrelationIdService | undefined);
|
|
129
|
+
log(message: string, context?: string): void;
|
|
130
|
+
error(message: string, trace?: string, context?: string): void;
|
|
131
|
+
warn(message: string, context?: string): void;
|
|
132
|
+
debug(message: string, context?: string): void;
|
|
133
|
+
verbose(message: string, context?: string): void;
|
|
134
|
+
/** Log with additional arbitrary metadata. */
|
|
135
|
+
logWithMeta(level: string, message: string, meta: Record<string, any>): void;
|
|
136
|
+
private buildMeta;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
declare class MetricsService implements OnModuleDestroy {
|
|
140
|
+
private readonly opts;
|
|
141
|
+
private readonly correlationSvc?;
|
|
142
|
+
private readonly client;
|
|
143
|
+
private readonly cb;
|
|
144
|
+
private readonly logger;
|
|
145
|
+
private readonly buffer;
|
|
146
|
+
private readonly maxBufferSize;
|
|
147
|
+
private readonly flushTimer;
|
|
148
|
+
constructor(opts: ObservabilityOptions, correlationSvc?: CorrelationIdService | undefined);
|
|
149
|
+
/**
|
|
150
|
+
* Enqueue a metric event. Fire-and-forget; batched and sent on the next
|
|
151
|
+
* flush interval or when the buffer reaches `maxBufferSize`.
|
|
152
|
+
*/
|
|
153
|
+
record(name: string, value: number, options?: {
|
|
154
|
+
unit?: string;
|
|
155
|
+
tags?: Record<string, string>;
|
|
156
|
+
}): void;
|
|
157
|
+
/** Flush on graceful shutdown. */
|
|
158
|
+
onModuleDestroy(): Promise<void>;
|
|
159
|
+
private flush;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
declare class CorrelationInterceptor implements NestInterceptor {
|
|
163
|
+
private readonly correlationSvc;
|
|
164
|
+
constructor(correlationSvc: CorrelationIdService);
|
|
165
|
+
intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
declare class PerformanceInterceptor implements NestInterceptor {
|
|
169
|
+
private readonly logger;
|
|
170
|
+
private readonly metrics;
|
|
171
|
+
private readonly correlationSvc;
|
|
172
|
+
constructor(logger: LoggerService, metrics: MetricsService | undefined, correlationSvc: CorrelationIdService | undefined);
|
|
173
|
+
intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
174
|
+
private record;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
type ErrorMapper = (error: unknown) => {
|
|
178
|
+
statusCode: number;
|
|
179
|
+
message: string;
|
|
180
|
+
code?: string;
|
|
181
|
+
} | null;
|
|
182
|
+
declare class AllExceptionsFilter implements ExceptionFilter {
|
|
183
|
+
private readonly logger;
|
|
184
|
+
private readonly correlationSvc;
|
|
185
|
+
private readonly mappers;
|
|
186
|
+
constructor(logger: LoggerService, correlationSvc: CorrelationIdService | undefined);
|
|
187
|
+
/**
|
|
188
|
+
* Register a custom error mapper.
|
|
189
|
+
* Mappers are tried in order; the first non-null result wins.
|
|
190
|
+
* Return `null` to fall through to the next mapper.
|
|
191
|
+
*/
|
|
192
|
+
addMapper(mapper: ErrorMapper): this;
|
|
193
|
+
catch(exception: unknown, host: ArgumentsHost): void;
|
|
194
|
+
private resolveError;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface TrackPerformanceOptions {
|
|
198
|
+
/** OTel span / log operation name. Defaults to `ClassName.methodName`. */
|
|
199
|
+
operation?: string;
|
|
200
|
+
/** Attributes added to the OTel span. */
|
|
201
|
+
attributes?: Record<string, string | number | boolean>;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Method decorator that wraps the decorated async method in an OTel span
|
|
205
|
+
* (when @opentelemetry/api is available) and records its duration.
|
|
206
|
+
* Works with regular methods and NestJS service methods.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* \@TrackPerformance()
|
|
210
|
+
* async processPayment(id: string) { ... }
|
|
211
|
+
*/
|
|
212
|
+
declare function TrackPerformance(options?: TrackPerformanceOptions): MethodDecorator;
|
|
213
|
+
|
|
214
|
+
declare const OBSERVABILITY_OPTIONS: "OBSERVABILITY_OPTIONS";
|
|
215
|
+
|
|
216
|
+
export { AllExceptionsFilter, CorrelationIdService, CorrelationInterceptor, type ErrorMapper, LoggerService, type MetricEvent, type MetricsOptions, MetricsService, OBSERVABILITY_OPTIONS, ObservabilityModule, type ObservabilityOptions, PerformanceInterceptor, TrackPerformance, type TrackPerformanceOptions, WinstonHttpTransport, type WinstonHttpTransportOptions };
|