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.

89 lines (88 loc) 3.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.traceAxios = void 0; const axios_1 = require("axios"); const types_1 = require("./types"); const storage_1 = require("./storage"); const utils_1 = require("./utils"); const span_1 = require("./span"); const buildUrl = (baseUrl, url) => { return url?.startsWith('http') ? url : [baseUrl, url].filter(Boolean).join(''); }; const extractQueryParams = (url, config) => { const object = new URL(url); const query = { ...Object.fromEntries(object.searchParams.entries()), ...config.params }; const keys = Object.keys(query); keys.forEach((key) => object.searchParams.delete(key)); return { url: object.toString(), query: keys.length > 0 ? query : undefined }; }; const buildOutgoingHttpPayload = (config, res) => ({ type: 'http', http: { ...extractQueryParams(buildUrl(config.baseURL, config.url), config), method: config.method?.toLowerCase() ?? 'get', incoming: false, request: { headers: config.headers, body: (0, utils_1.safeJsonParse)(config.data), }, response: res ? { headers: res?.headers, status: res.status, body: (0, utils_1.safeJsonParse)(res.data), } : undefined, }, }); const getNoopPayload = () => ({}); /** * Wraps an axios instance to add tracing and span tracking * @param axios - The axios instance to wrap * @param options - Configuration options for HTTP tracing * @returns The wrapped axios instance with span tracking */ const traceAxios = (client, { ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes, traceHeaderKey = types_1.defaultTraceHeaderKey, getPayload = getNoopPayload, } = { ignoreTraceRoutes: types_1.defaultIgnoreTraceRoutes, traceHeaderKey: types_1.defaultTraceHeaderKey, getPayload: getNoopPayload, }) => { const createSpanWrappedRequest = (originalMethod, method) => { const { headers: defaultHeaders, ...partialDefaultConfig } = client.defaults; const headers = { ...defaultHeaders.common, ...(method && defaultHeaders[method]) }; const defaultConfig = { ...partialDefaultConfig, headers }; return async (config) => { config = (0, axios_1.mergeConfig)(defaultConfig, config); const url = buildUrl(config.baseURL, config.url); // Check if this request should be ignored if ((0, utils_1.shouldIgnorePath)(url, ignoreTraceRoutes)) return originalMethod(config); const traceId = storage_1.storage.getStore()?.traceId; config = { ...config, headers: { ...config.headers, [traceHeaderKey]: traceId } }; // Execute the request within a span return (0, span_1.startSpan)(`Outgoing HTTP request`, () => originalMethod(config), (options) => { const response = options ? options.error ? (0, axios_1.isAxiosError)(options.error) ? options.error.response : undefined : options.result : undefined; return { ...buildOutgoingHttpPayload(config, response), ...getPayload(config, response) }; }); }; }; const request = client.request.bind(client); const tracedRequest = createSpanWrappedRequest(request); client.request = tracedRequest; ['post', 'put', 'patch'].forEach((method) => { const func = createSpanWrappedRequest(request, method); client[method] = (url, data, config) => func({ ...config, method, url, data }); }); ['delete', 'get', 'head', 'options'].forEach((method) => { const func = createSpanWrappedRequest(request, method); client[method] = (url, config) => func({ ...config, method, url }); }); return client; }; exports.traceAxios = traceAxios;