UNPKG

unnbound-logger-sdk

Version:

A structured logging library with TypeScript support using Pino. Provides consistent, well-typed logging with automatic logId, workflowId, traceId, and deploymentId tracking across operational contexts.

86 lines (85 loc) 3.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.traceMiddleware = void 0; const span_1 = require("./span"); const types_1 = require("./types"); const utils_1 = require("./utils"); const trace_1 = require("./trace"); const extractQueryParams = (url) => { const object = new URL(url); const query = Object.fromEntries(object.searchParams.entries()); const keys = Object.keys(query); keys.forEach((key) => object.searchParams.delete(key)); return { url: object.toString(), query: keys.length > 0 ? query : undefined }; }; const getFullUrl = (req) => { const url = req.originalUrl || req.url; if (url?.startsWith('http://') || url?.startsWith('https://')) return url; // Check if we have a workflow URL configured (preferred method) if (process.env.UNNBOUND_WORKFLOW_URL) { // Use workflow URL as the base URL return `https://${process.env.UNNBOUND_WORKFLOW_URL.replace(/\/$/, '')}${url}`; } // Fallback to constructing from request info for incoming requests const protocol = req.protocol || (req.secure ? 'https' : 'http'); const host = req.get('host') || req.get('x-forwarded-host') || 'localhost'; return `${protocol}://${host}${url}`; }; const buildIncomingHttpPayload = (req, res) => ({ type: 'http', http: { ...extractQueryParams(getFullUrl(req)), method: req.method.toLowerCase(), ip: (0, utils_1.normalizeIp)(req.ip), incoming: true, request: { headers: req.headers, body: (0, utils_1.safeJsonParse)(req.body), }, response: res ? { headers: res.headers, status: res.status, body: (0, utils_1.safeJsonParse)(res.body), } : undefined, }, }); const getNoopPayload = () => ({}); const traceMiddleware = ({ ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes, traceHeaderKey = types_1.defaultTraceHeaderKey, messageHeaderKey = types_1.defaultMessageHeaderKey, getPayload = getNoopPayload, } = { ignoreTraceRoutes: types_1.defaultIgnoreTraceRoutes, traceHeaderKey: types_1.defaultTraceHeaderKey, messageHeaderKey: types_1.defaultMessageHeaderKey, getPayload: getNoopPayload, }) => async (req, res, next) => { if ((0, utils_1.shouldIgnorePath)(req.path, ignoreTraceRoutes)) return next(); const traceId = req.header(traceHeaderKey) || (0, trace_1.getTraceId)(); const messageId = req.header(messageHeaderKey) || undefined; res.setHeader(traceHeaderKey, traceId); return await (0, trace_1.withTrace)(async () => { return await (0, span_1.startSpan)('Incoming HTTP request', async () => { return new Promise((resolve) => { // Capture response body for logging const send = res.send.bind(res); res.send = (body) => { res.locals.body = body; return send(body); }; res.on('finish', () => resolve()); return next(); }); }, (o) => { const response = o ? { status: res.statusCode, headers: res.getHeaders(), body: res.locals.body, } : undefined; return { ...buildIncomingHttpPayload(req, response), ...getPayload(req, response) }; }); }, messageId ? { traceId, messageId } : { traceId }); }; exports.traceMiddleware = traceMiddleware;