unnbound-logger-sdk 3.2.0 → 3.2.2
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/dist/axios.d.ts +5 -1
- package/dist/axios.js +29 -34
- package/dist/logger.js +13 -2
- package/package.json +4 -4
package/dist/axios.d.ts
CHANGED
|
@@ -21,13 +21,17 @@ interface HttpClientOptions extends HttpOptions<GetPayload> {
|
|
|
21
21
|
silent?: boolean;
|
|
22
22
|
startSpan?: typeof startSpan;
|
|
23
23
|
}
|
|
24
|
+
type TracedMethod = 'request' | 'get' | 'delete' | 'head' | 'options' | 'post' | 'put' | 'patch';
|
|
25
|
+
type TraceableAxios = Pick<AxiosInstance, 'defaults'> & Record<TracedMethod, (...args: never[]) => object>;
|
|
24
26
|
/**
|
|
25
27
|
* Wraps an axios instance to add tracing and span tracking.
|
|
26
28
|
*
|
|
27
29
|
* Repeated calls for the same instance are no-ops; the first call's options remain active.
|
|
30
|
+
* Axios 1.20+ types an ESM import and a CommonJS require with separate, mutually unassignable
|
|
31
|
+
* declarations, so the signature accepts an instance from either and returns the caller's type.
|
|
28
32
|
* @param client - The axios instance to wrap
|
|
29
33
|
* @param options - Configuration options for HTTP tracing
|
|
30
34
|
* @returns The wrapped axios instance with span tracking
|
|
31
35
|
*/
|
|
32
|
-
export declare
|
|
36
|
+
export declare function traceAxios<Client extends TraceableAxios>(client: Client, options?: HttpClientOptions): Client;
|
|
33
37
|
export {};
|
package/dist/axios.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.traceAxios =
|
|
3
|
+
exports.traceAxios = traceAxios;
|
|
4
4
|
const axios_1 = require("axios");
|
|
5
5
|
const span_1 = require("./span");
|
|
6
6
|
const storage_1 = require("./storage");
|
|
@@ -42,45 +42,33 @@ const buildOutgoingHttpPayload = (config, res, redact) => {
|
|
|
42
42
|
const getNoopPayload = () => ({});
|
|
43
43
|
const onNoopRequest = (config, callback) => callback(config);
|
|
44
44
|
const tracedMarker = Symbol.for('unnbound-logger-sdk.traceAxios.traced');
|
|
45
|
-
|
|
46
|
-
* Wraps an axios instance to add tracing and span tracking.
|
|
47
|
-
*
|
|
48
|
-
* Repeated calls for the same instance are no-ops; the first call's options remain active.
|
|
49
|
-
* @param client - The axios instance to wrap
|
|
50
|
-
* @param options - Configuration options for HTTP tracing
|
|
51
|
-
* @returns The wrapped axios instance with span tracking
|
|
52
|
-
*/
|
|
53
|
-
const traceAxios = (client, { ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes, traceHeaderKey = types_1.defaultTraceHeaderKey, getPayload = getNoopPayload, onRequest = onNoopRequest, redact: redactOptions, silent = false, startSpan: startSpanImpl = span_1.startSpan, } = {
|
|
45
|
+
function traceAxios(client, { ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes, traceHeaderKey = types_1.defaultTraceHeaderKey, getPayload = getNoopPayload, onRequest = onNoopRequest, redact: redactOptions, silent = false, startSpan: startSpanImpl = span_1.startSpan, } = {
|
|
54
46
|
ignoreTraceRoutes: types_1.defaultIgnoreTraceRoutes,
|
|
55
47
|
traceHeaderKey: types_1.defaultTraceHeaderKey,
|
|
56
48
|
getPayload: getNoopPayload,
|
|
57
49
|
onRequest: onNoopRequest,
|
|
58
|
-
})
|
|
50
|
+
}) {
|
|
59
51
|
if (tracedMarker in client)
|
|
60
52
|
return client;
|
|
61
53
|
const redact = redactOptions === true || redactOptions === false
|
|
62
54
|
? { request: redactOptions, response: redactOptions }
|
|
63
55
|
: redactOptions;
|
|
56
|
+
// Axios keeps its response defaults private; proxies preserve the original method signatures.
|
|
64
57
|
const createSpanWrappedRequest = (originalMethod, method) => {
|
|
65
58
|
const { headers: defaultHeaders, ...partialDefaultConfig } = client.defaults;
|
|
66
59
|
const headers = { ...defaultHeaders.common, ...(method && defaultHeaders[method]) };
|
|
67
60
|
const defaultConfig = { ...partialDefaultConfig, headers };
|
|
68
|
-
return
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return onRequest(config, (config) =>
|
|
79
|
-
}
|
|
80
|
-
// SAFETY: startSpan resolves to the originalMethod promise, typed as Axios R
|
|
81
|
-
return onRequest(config, (config) => {
|
|
82
|
-
// Execute the request within a span
|
|
83
|
-
return startSpanImpl('Outgoing HTTP request', () => originalMethod(config), (options) => {
|
|
61
|
+
return new Proxy(originalMethod, {
|
|
62
|
+
async apply(request, _thisArg, [config]) {
|
|
63
|
+
config = (0, axios_1.mergeConfig)(defaultConfig, config);
|
|
64
|
+
const url = buildUrl(config.baseURL, config.url);
|
|
65
|
+
if ((0, utils_1.shouldIgnorePath)(url, ignoreTraceRoutes))
|
|
66
|
+
return request(config);
|
|
67
|
+
const traceId = storage_1.storage.getStore()?.traceId;
|
|
68
|
+
config = { ...config, headers: { ...config.headers, [traceHeaderKey]: traceId } };
|
|
69
|
+
if (silent)
|
|
70
|
+
return onRequest(config, (config) => request(config));
|
|
71
|
+
return onRequest(config, (config) => startSpanImpl('Outgoing HTTP request', () => request(config), (options) => {
|
|
84
72
|
const response = options
|
|
85
73
|
? options.error
|
|
86
74
|
? (0, axios_1.isAxiosError)(options.error)
|
|
@@ -92,22 +80,29 @@ const traceAxios = (client, { ignoreTraceRoutes = types_1.defaultIgnoreTraceRout
|
|
|
92
80
|
...buildOutgoingHttpPayload(config, response, redact),
|
|
93
81
|
...getPayload(config, response),
|
|
94
82
|
};
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
};
|
|
83
|
+
}));
|
|
84
|
+
},
|
|
85
|
+
});
|
|
98
86
|
};
|
|
99
87
|
const request = client.request.bind(client);
|
|
100
88
|
const tracedRequest = createSpanWrappedRequest(request);
|
|
101
89
|
client.request = tracedRequest;
|
|
102
90
|
['post', 'put', 'patch'].forEach((method) => {
|
|
103
91
|
const func = createSpanWrappedRequest(request, method);
|
|
104
|
-
client[method] =
|
|
92
|
+
client[method] = new Proxy(client[method], {
|
|
93
|
+
apply(_target, _thisArg, [url, data, config]) {
|
|
94
|
+
return func({ ...config, method, url, data });
|
|
95
|
+
},
|
|
96
|
+
});
|
|
105
97
|
});
|
|
106
98
|
['delete', 'get', 'head', 'options'].forEach((method) => {
|
|
107
99
|
const func = createSpanWrappedRequest(request, method);
|
|
108
|
-
client[method] =
|
|
100
|
+
client[method] = new Proxy(client[method], {
|
|
101
|
+
apply(_target, _thisArg, [url, config]) {
|
|
102
|
+
return func({ ...config, method, url });
|
|
103
|
+
},
|
|
104
|
+
});
|
|
109
105
|
});
|
|
110
106
|
Object.defineProperty(client, tracedMarker, { value: true });
|
|
111
107
|
return client;
|
|
112
|
-
}
|
|
113
|
-
exports.traceAxios = traceAxios;
|
|
108
|
+
}
|
package/dist/logger.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.logger = exports.createLogger = void 0;
|
|
7
|
+
const axios_1 = require("axios");
|
|
7
8
|
const pino_1 = __importDefault(require("pino"));
|
|
8
9
|
const uuid_1 = require("uuid");
|
|
9
10
|
const encode_1 = require("./encode");
|
|
@@ -26,6 +27,16 @@ const isStringAnnotation = (value) => {
|
|
|
26
27
|
return false;
|
|
27
28
|
}
|
|
28
29
|
};
|
|
30
|
+
// An AxiosError carries its config, the Node request (whose `_header` holds every request header, credentials
|
|
31
|
+
// included), and the response. Those three are dropped; the rest of the standard error fields stay (`type`, `message`,
|
|
32
|
+
// `stack`, `code`, `status`). `traceAxios` logs the exchange itself under its own redaction.
|
|
33
|
+
const serializeError = (error) => {
|
|
34
|
+
const serialized = pino_1.default.stdSerializers.err(error);
|
|
35
|
+
if (!(0, axios_1.isAxiosError)(error) || !isBindings(serialized))
|
|
36
|
+
return serialized;
|
|
37
|
+
const { config: _config, request: _request, response: _response, ...kept } = serialized;
|
|
38
|
+
return kept;
|
|
39
|
+
};
|
|
29
40
|
const copyLogFields = (log, copy, copies, preserveErrorSerializer) => {
|
|
30
41
|
for (const key in log) {
|
|
31
42
|
if (!Object.hasOwn(log, key))
|
|
@@ -56,7 +67,7 @@ const copyLogValue = (value, copies) => {
|
|
|
56
67
|
return copy;
|
|
57
68
|
}
|
|
58
69
|
if (value instanceof Error) {
|
|
59
|
-
const serialized =
|
|
70
|
+
const serialized = serializeError(value);
|
|
60
71
|
const copy = {};
|
|
61
72
|
copies.set(value, copy);
|
|
62
73
|
copies.set(serialized, copy);
|
|
@@ -90,7 +101,7 @@ const copyBindings = (log, copies, preserveErrorSerializer) => {
|
|
|
90
101
|
const formatLog = (log) => copyBindings(log, new WeakMap(), true);
|
|
91
102
|
// `err` may be anything thrown; pino returns non-Error values unchanged, so only objects are copied.
|
|
92
103
|
const formatError = (error) => {
|
|
93
|
-
const serialized =
|
|
104
|
+
const serialized = serializeError(error);
|
|
94
105
|
if (isStringAnnotation(serialized))
|
|
95
106
|
return (0, encode_1.encode)(serialized);
|
|
96
107
|
return isBindings(serialized) ? formatLog(serialized) : serialized;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unnbound-logger-sdk",
|
|
3
3
|
"description": "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.",
|
|
4
|
-
"version": "3.2.
|
|
4
|
+
"version": "3.2.2",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"keywords": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"url": "https://github.com/unnbounddev/unnbound-sdks/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"axios": "1.
|
|
28
|
+
"axios": "1.20.0",
|
|
29
29
|
"express": "^4.0.0 || ^5.0.0",
|
|
30
30
|
"pino": "^10.3.1",
|
|
31
31
|
"uuid": "^11.1.1"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"vitest": "^4.0.15"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"axios": "^1.
|
|
40
|
+
"axios": "^1.20.0",
|
|
41
41
|
"express": "^4.0.0 || ^5.0.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "tsc",
|
|
62
62
|
"test": "vitest run src",
|
|
63
|
-
"typecheck": "tsc --noEmit",
|
|
63
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.test.json",
|
|
64
64
|
"format": "oxfmt --write .",
|
|
65
65
|
"format:check": "oxfmt --check .",
|
|
66
66
|
"start:example": "tsx watch examples/node-express.ts",
|