http-logger.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import type { IncomingMessage, ServerResponse } from 'node:http';
  2. import type { HttpLogger, Options as PinoHttpOptions } from 'pino-http';
  3. import { loggerFactory } from './logger-factory';
  4. interface HttpLoggerOptions {
  5. /** Logger namespace, defaults to 'express' */
  6. namespace?: string;
  7. /** Auto-logging configuration (e.g., route ignore patterns) */
  8. autoLogging?: {
  9. ignore: (req: { url?: string }) => boolean;
  10. };
  11. }
  12. /**
  13. * Create Express middleware for HTTP request logging.
  14. * In dev: uses pino-http with morgan-like formatting (dynamically imported).
  15. * In prod: uses pino-http with default formatting.
  16. *
  17. * The pino-http dependency is encapsulated here — consumer apps
  18. * should not import pino-http directly.
  19. */
  20. export async function createHttpLoggerMiddleware(
  21. options?: HttpLoggerOptions,
  22. ): Promise<HttpLogger<IncomingMessage, ServerResponse>> {
  23. const namespace = options?.namespace ?? 'express';
  24. const logger = loggerFactory(namespace);
  25. const httpOptions: PinoHttpOptions = {
  26. // Logger<string> → pino-http's expected Logger type
  27. logger: logger as unknown as PinoHttpOptions['logger'],
  28. ...(options?.autoLogging != null
  29. ? { autoLogging: options.autoLogging }
  30. : {}),
  31. };
  32. // In development, dynamically import morgan-like format options
  33. if (process.env.NODE_ENV !== 'production') {
  34. const { morganLikeFormatOptions } = await import(
  35. './dev/morgan-like-format-options'
  36. );
  37. Object.assign(httpOptions, morganLikeFormatOptions);
  38. }
  39. const { default: pinoHttp } = await import('pino-http');
  40. return pinoHttp(httpOptions);
  41. }