UNPKG

@unito/integration-sdk

Version:

Integration SDK

55 lines (47 loc) 1.78 kB
import { Request, Response, NextFunction } from 'express'; import { Error as ApiError } from '@unito/integration-api'; import { default as Logger, Metadata } from '../resources/logger.js'; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Express { interface Locals { logger: Logger; error?: ApiError; requestStartTime: bigint; } } } function onFinish(req: Request, res: Response, next: NextFunction) { res.on('finish', function () { const logger = res.locals.logger ?? new Logger(); const error = res.locals.error; const durationInNs = Number(process.hrtime.bigint() - res.locals.requestStartTime); const durationInMs = (durationInNs / 1_000_000) | 0; const message = `${req.method} ${req.originalUrl} ${res.statusCode} - ${durationInMs} ms`; const metadata: Metadata = { duration: durationInNs, // Use reserved and standard attributes of Datadog // https://app.datadoghq.com/logs/pipelines/standard-attributes http: { method: req.method, status_code: res.statusCode, url_details: { path: req.originalUrl } }, ...(error ? { error: { kind: error.message, stack: (error.originalError?.details?.stack ?? error.details?.stack) as string, message: error.originalError?.message ?? error.message, }, } : {}), }; if ([404, 429].includes(res.statusCode)) { logger.warn(message, metadata); } else if (res.statusCode >= 400) { logger.error(message, metadata); } else if (req.originalUrl !== '/health') { // Don't log successful health check requests logger.info(message, metadata); } }); next(); } export default onFinish;