@dex-monit/observability-sdk-node 1.0.8 → 1.0.10
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/lib/error-capture.interceptor.d.ts +3 -0
- package/dist/lib/error-capture.interceptor.d.ts.map +1 -1
- package/dist/lib/error-capture.interceptor.js +69 -3
- package/dist/lib/monitoring-client.d.ts +26 -1
- package/dist/lib/monitoring-client.d.ts.map +1 -1
- package/dist/lib/monitoring-client.js +60 -0
- package/dist/lib/nest-logger-capture.d.ts.map +1 -1
- package/dist/lib/nest-logger-capture.js +104 -56
- package/dist/lib/sdk-node.module.d.ts.map +1 -1
- package/dist/lib/sdk-node.module.js +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,9 @@ export declare class ErrorCaptureInterceptor implements NestInterceptor {
|
|
|
13
13
|
constructor(monitoringClient?: MonitoringClient | undefined);
|
|
14
14
|
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
15
15
|
private captureError;
|
|
16
|
+
private getFullUrl;
|
|
16
17
|
private sanitizeHeaders;
|
|
18
|
+
private sanitizeBody;
|
|
19
|
+
private sanitizeCookies;
|
|
17
20
|
}
|
|
18
21
|
//# sourceMappingURL=error-capture.interceptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-capture.interceptor.d.ts","sourceRoot":"","sources":["../../src/lib/error-capture.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAc,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"error-capture.interceptor.d.ts","sourceRoot":"","sources":["../../src/lib/error-capture.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAc,MAAM,MAAM,CAAC;AAI9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;;;;;GAMG;AACH,qBACa,uBAAwB,YAAW,eAAe;IAE3D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAAjB,gBAAgB,CAAC,EAAE,gBAAgB,YAAA;IAGtD,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC;IAY5E,OAAO,CAAC,YAAY;IAkEpB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,eAAe;CASxB"}
|
|
@@ -2,6 +2,7 @@ import { __esDecorate, __runInitializers } from "tslib";
|
|
|
2
2
|
import { Injectable, } from '@nestjs/common';
|
|
3
3
|
import { throwError } from 'rxjs';
|
|
4
4
|
import { catchError } from 'rxjs/operators';
|
|
5
|
+
import * as os from 'os';
|
|
5
6
|
/**
|
|
6
7
|
* Error Capture Interceptor
|
|
7
8
|
*
|
|
@@ -46,11 +47,44 @@ let ErrorCaptureInterceptor = (() => {
|
|
|
46
47
|
console.log('[DEX SDK] Sending error to monitoring...');
|
|
47
48
|
this.monitoringClient
|
|
48
49
|
.captureException(errorObj, {
|
|
50
|
+
// Full request context like Sentry
|
|
49
51
|
request: {
|
|
50
|
-
url: request
|
|
52
|
+
url: this.getFullUrl(request),
|
|
51
53
|
method: request?.method,
|
|
52
54
|
headers: this.sanitizeHeaders(request?.headers || {}),
|
|
53
55
|
query: request?.query,
|
|
56
|
+
body: this.sanitizeBody(request?.body),
|
|
57
|
+
cookies: this.sanitizeCookies(request?.cookies),
|
|
58
|
+
},
|
|
59
|
+
// OS context
|
|
60
|
+
context: {
|
|
61
|
+
os: {
|
|
62
|
+
name: os.platform(),
|
|
63
|
+
version: os.release(),
|
|
64
|
+
kernelVersion: os.release(),
|
|
65
|
+
},
|
|
66
|
+
runtime: {
|
|
67
|
+
name: 'node',
|
|
68
|
+
version: process.version,
|
|
69
|
+
},
|
|
70
|
+
device: {
|
|
71
|
+
arch: os.arch(),
|
|
72
|
+
memory: os.totalmem(),
|
|
73
|
+
cpus: os.cpus().length,
|
|
74
|
+
hostname: os.hostname(),
|
|
75
|
+
},
|
|
76
|
+
app: {
|
|
77
|
+
startTime: process.uptime(),
|
|
78
|
+
memoryUsage: process.memoryUsage(),
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
// Tags for filtering
|
|
82
|
+
tags: {
|
|
83
|
+
'http.method': request?.method || 'unknown',
|
|
84
|
+
'http.status_code': '500',
|
|
85
|
+
'runtime': 'node',
|
|
86
|
+
'runtime.version': process.version,
|
|
87
|
+
'os': os.platform(),
|
|
54
88
|
},
|
|
55
89
|
})
|
|
56
90
|
.then(() => {
|
|
@@ -64,12 +98,20 @@ let ErrorCaptureInterceptor = (() => {
|
|
|
64
98
|
console.log('[DEX SDK] No monitoring client configured');
|
|
65
99
|
}
|
|
66
100
|
}
|
|
101
|
+
getFullUrl(request) {
|
|
102
|
+
if (!request)
|
|
103
|
+
return 'unknown';
|
|
104
|
+
const protocol = request.protocol || 'http';
|
|
105
|
+
const host = request.get?.('host') || request.hostname || 'localhost';
|
|
106
|
+
const path = request.originalUrl || request.url || '/';
|
|
107
|
+
return `${protocol}://${host}${path}`;
|
|
108
|
+
}
|
|
67
109
|
sanitizeHeaders(headers) {
|
|
68
|
-
const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-dex-key'];
|
|
110
|
+
const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-dex-key', 'x-auth-token'];
|
|
69
111
|
const sanitized = {};
|
|
70
112
|
for (const [key, value] of Object.entries(headers)) {
|
|
71
113
|
if (sensitiveHeaders.includes(key.toLowerCase())) {
|
|
72
|
-
sanitized[key] = '[
|
|
114
|
+
sanitized[key] = '[Filtered]';
|
|
73
115
|
}
|
|
74
116
|
else if (typeof value === 'string') {
|
|
75
117
|
sanitized[key] = value;
|
|
@@ -77,6 +119,30 @@ let ErrorCaptureInterceptor = (() => {
|
|
|
77
119
|
}
|
|
78
120
|
return sanitized;
|
|
79
121
|
}
|
|
122
|
+
sanitizeBody(body) {
|
|
123
|
+
if (!body || typeof body !== 'object')
|
|
124
|
+
return undefined;
|
|
125
|
+
const sensitiveKeys = ['password', 'token', 'secret', 'apiKey', 'api_key', 'credit_card', 'cvv'];
|
|
126
|
+
const sanitized = {};
|
|
127
|
+
for (const [key, value] of Object.entries(body)) {
|
|
128
|
+
if (sensitiveKeys.some(k => key.toLowerCase().includes(k.toLowerCase()))) {
|
|
129
|
+
sanitized[key] = '[Filtered]';
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
sanitized[key] = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return sanitized;
|
|
136
|
+
}
|
|
137
|
+
sanitizeCookies(cookies) {
|
|
138
|
+
if (!cookies || typeof cookies !== 'object')
|
|
139
|
+
return undefined;
|
|
140
|
+
const sanitized = {};
|
|
141
|
+
for (const key of Object.keys(cookies)) {
|
|
142
|
+
sanitized[key] = '[Filtered]';
|
|
143
|
+
}
|
|
144
|
+
return sanitized;
|
|
145
|
+
}
|
|
80
146
|
};
|
|
81
147
|
return ErrorCaptureInterceptor = _classThis;
|
|
82
148
|
})();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ErrorEvent, EventContext, Severity } from '@dex-monit/observability-contracts';
|
|
1
|
+
import { ErrorEvent, EventContext, Severity, Breadcrumb } from '@dex-monit/observability-contracts';
|
|
2
2
|
import { ScrubberOptions } from '@dex-monit/observability-scrubber';
|
|
3
3
|
/**
|
|
4
4
|
* Monitoring client configuration
|
|
@@ -100,4 +100,29 @@ export declare class MonitoringClient {
|
|
|
100
100
|
* Create a monitoring client instance
|
|
101
101
|
*/
|
|
102
102
|
export declare function createMonitoringClient(config: MonitoringClientConfig): MonitoringClient;
|
|
103
|
+
/**
|
|
104
|
+
* Add a breadcrumb to the global breadcrumb trail
|
|
105
|
+
*/
|
|
106
|
+
export declare function addBreadcrumb(breadcrumb: Omit<Breadcrumb, 'timestamp'>): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get current breadcrumbs
|
|
109
|
+
*/
|
|
110
|
+
export declare function getBreadcrumbs(): Breadcrumb[];
|
|
111
|
+
/**
|
|
112
|
+
* Clear all breadcrumbs
|
|
113
|
+
*/
|
|
114
|
+
export declare function clearBreadcrumbs(): void;
|
|
115
|
+
/**
|
|
116
|
+
* Add an HTTP breadcrumb (convenience function)
|
|
117
|
+
*/
|
|
118
|
+
export declare function addHttpBreadcrumb(data: {
|
|
119
|
+
url: string;
|
|
120
|
+
method: string;
|
|
121
|
+
statusCode?: number;
|
|
122
|
+
duration?: number;
|
|
123
|
+
}): void;
|
|
124
|
+
/**
|
|
125
|
+
* Add a console breadcrumb (convenience function)
|
|
126
|
+
*/
|
|
127
|
+
export declare function addConsoleBreadcrumb(level: Severity, message: string, data?: Record<string, unknown>): void;
|
|
103
128
|
//# sourceMappingURL=monitoring-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitoring-client.d.ts","sourceRoot":"","sources":["../../src/lib/monitoring-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAwB,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"monitoring-client.d.ts","sourceRoot":"","sources":["../../src/lib/monitoring-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from 'uuid';
|
|
2
2
|
import { RequestContextService } from '@dex-monit/observability-request-context';
|
|
3
3
|
import { scrubSensitiveData } from '@dex-monit/observability-scrubber';
|
|
4
|
+
// Global breadcrumb storage
|
|
5
|
+
const MAX_BREADCRUMBS = 100;
|
|
6
|
+
let globalBreadcrumbs = [];
|
|
4
7
|
/**
|
|
5
8
|
* Parse stack trace into structured frames
|
|
6
9
|
*/
|
|
@@ -86,6 +89,8 @@ export class MonitoringClient {
|
|
|
86
89
|
value: error.message,
|
|
87
90
|
stacktrace: parseStackTrace(error.stack),
|
|
88
91
|
},
|
|
92
|
+
// Include breadcrumbs (events leading up to the error)
|
|
93
|
+
breadcrumbs: getBreadcrumbs(),
|
|
89
94
|
requestId: requestContext?.requestId,
|
|
90
95
|
transactionId: requestContext?.transactionId,
|
|
91
96
|
fingerprint: options.fingerprint || generateFingerprint(error),
|
|
@@ -331,3 +336,58 @@ export class MonitoringClient {
|
|
|
331
336
|
export function createMonitoringClient(config) {
|
|
332
337
|
return new MonitoringClient(config);
|
|
333
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Add a breadcrumb to the global breadcrumb trail
|
|
341
|
+
*/
|
|
342
|
+
export function addBreadcrumb(breadcrumb) {
|
|
343
|
+
const crumb = {
|
|
344
|
+
timestamp: new Date().toISOString(),
|
|
345
|
+
...breadcrumb,
|
|
346
|
+
};
|
|
347
|
+
globalBreadcrumbs.push(crumb);
|
|
348
|
+
// Keep only the last MAX_BREADCRUMBS
|
|
349
|
+
if (globalBreadcrumbs.length > MAX_BREADCRUMBS) {
|
|
350
|
+
globalBreadcrumbs = globalBreadcrumbs.slice(-MAX_BREADCRUMBS);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Get current breadcrumbs
|
|
355
|
+
*/
|
|
356
|
+
export function getBreadcrumbs() {
|
|
357
|
+
return [...globalBreadcrumbs];
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Clear all breadcrumbs
|
|
361
|
+
*/
|
|
362
|
+
export function clearBreadcrumbs() {
|
|
363
|
+
globalBreadcrumbs = [];
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Add an HTTP breadcrumb (convenience function)
|
|
367
|
+
*/
|
|
368
|
+
export function addHttpBreadcrumb(data) {
|
|
369
|
+
addBreadcrumb({
|
|
370
|
+
category: 'http',
|
|
371
|
+
type: 'http',
|
|
372
|
+
level: data.statusCode && data.statusCode >= 400 ? 'error' : 'info',
|
|
373
|
+
message: `${data.method} ${data.url}`,
|
|
374
|
+
data: {
|
|
375
|
+
url: data.url,
|
|
376
|
+
method: data.method,
|
|
377
|
+
status_code: data.statusCode,
|
|
378
|
+
duration_ms: data.duration,
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Add a console breadcrumb (convenience function)
|
|
384
|
+
*/
|
|
385
|
+
export function addConsoleBreadcrumb(level, message, data) {
|
|
386
|
+
addBreadcrumb({
|
|
387
|
+
category: 'console',
|
|
388
|
+
type: 'debug',
|
|
389
|
+
level,
|
|
390
|
+
message,
|
|
391
|
+
data,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nest-logger-capture.d.ts","sourceRoot":"","sources":["../../src/lib/nest-logger-capture.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nest-logger-capture.d.ts","sourceRoot":"","sources":["../../src/lib/nest-logger-capture.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAqF1D;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAiD/E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAuC5C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { Logger as NestLogger, ConsoleLogger } from '@nestjs/common';
|
|
2
3
|
import { RequestContextService } from '@dex-monit/observability-request-context';
|
|
3
4
|
const NEST_TO_SEVERITY = {
|
|
4
5
|
debug: 'debug',
|
|
@@ -8,8 +9,55 @@ const NEST_TO_SEVERITY = {
|
|
|
8
9
|
error: 'error',
|
|
9
10
|
fatal: 'fatal',
|
|
10
11
|
};
|
|
11
|
-
let
|
|
12
|
+
let originalStaticMethods = null;
|
|
13
|
+
let originalPrototypeMethods = null;
|
|
14
|
+
let originalConsoleLoggerMethods = null;
|
|
12
15
|
let isCapturing = false;
|
|
16
|
+
let monitoringClientRef = null;
|
|
17
|
+
/**
|
|
18
|
+
* Send log to monitoring service
|
|
19
|
+
*/
|
|
20
|
+
function sendToMonitoring(severity, message, context) {
|
|
21
|
+
if (!monitoringClientRef)
|
|
22
|
+
return;
|
|
23
|
+
// Skip SDK internal logs to avoid loops
|
|
24
|
+
if (context?.startsWith('DEX') || message.startsWith('[DEX') || message.startsWith('[MonitoringClient]')) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const requestContext = RequestContextService.get();
|
|
28
|
+
monitoringClientRef.captureLog(severity, message, {
|
|
29
|
+
source: 'nest-logger',
|
|
30
|
+
context,
|
|
31
|
+
requestId: requestContext?.requestId,
|
|
32
|
+
transactionId: requestContext?.transactionId,
|
|
33
|
+
}).catch(() => {
|
|
34
|
+
// Silently ignore
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract message and context from NestJS logger arguments
|
|
39
|
+
*/
|
|
40
|
+
function extractMessageAndContext(message, optionalParams) {
|
|
41
|
+
const messageStr = typeof message === 'string' ? message : JSON.stringify(message);
|
|
42
|
+
// Last param is usually the context
|
|
43
|
+
const lastParam = optionalParams[optionalParams.length - 1];
|
|
44
|
+
const context = typeof lastParam === 'string' ? lastParam : undefined;
|
|
45
|
+
return { message: messageStr, context };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create a wrapped method that sends to monitoring
|
|
49
|
+
*/
|
|
50
|
+
function createWrappedMethod(original, severity, getContext) {
|
|
51
|
+
return function (message, ...optionalParams) {
|
|
52
|
+
// Call original method
|
|
53
|
+
original.call(this, message, ...optionalParams);
|
|
54
|
+
// Extract message and context
|
|
55
|
+
const { message: msg, context } = extractMessageAndContext(message, optionalParams);
|
|
56
|
+
const finalContext = context || (getContext ? getContext.call(this) : undefined);
|
|
57
|
+
// Send to monitoring
|
|
58
|
+
sendToMonitoring(severity, msg, finalContext);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
13
61
|
/**
|
|
14
62
|
* Start capturing NestJS native Logger output
|
|
15
63
|
*/
|
|
@@ -17,72 +65,72 @@ export function startNestLoggerCapture(monitoringClient) {
|
|
|
17
65
|
if (isCapturing) {
|
|
18
66
|
return;
|
|
19
67
|
}
|
|
20
|
-
|
|
21
|
-
originalMethods = {
|
|
22
|
-
log: NestLogger.log.bind(NestLogger),
|
|
23
|
-
error: NestLogger.error.bind(NestLogger),
|
|
24
|
-
warn: NestLogger.warn.bind(NestLogger),
|
|
25
|
-
debug: NestLogger.debug.bind(NestLogger),
|
|
26
|
-
verbose: NestLogger.verbose.bind(NestLogger),
|
|
27
|
-
fatal: NestLogger.fatal.bind(NestLogger),
|
|
28
|
-
};
|
|
68
|
+
monitoringClientRef = monitoringClient;
|
|
29
69
|
const methods = ['log', 'error', 'warn', 'debug', 'verbose', 'fatal'];
|
|
70
|
+
// 1. Patch static methods on NestLogger
|
|
71
|
+
originalStaticMethods = {};
|
|
30
72
|
for (const method of methods) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
transactionId: requestContext?.transactionId,
|
|
52
|
-
}).catch(() => {
|
|
53
|
-
// Silently ignore
|
|
54
|
-
});
|
|
55
|
-
};
|
|
73
|
+
if (typeof NestLogger[method] === 'function') {
|
|
74
|
+
originalStaticMethods[method] = NestLogger[method].bind(NestLogger);
|
|
75
|
+
NestLogger[method] = createWrappedMethod(originalStaticMethods[method], NEST_TO_SEVERITY[method]);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// 2. Patch prototype methods on NestLogger
|
|
79
|
+
originalPrototypeMethods = {};
|
|
80
|
+
for (const method of methods) {
|
|
81
|
+
if (typeof NestLogger.prototype[method] === 'function') {
|
|
82
|
+
originalPrototypeMethods[method] = NestLogger.prototype[method];
|
|
83
|
+
NestLogger.prototype[method] = createWrappedMethod(originalPrototypeMethods[method], NEST_TO_SEVERITY[method], function () { return this.context; });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 3. Patch ConsoleLogger prototype (NestJS internal logger)
|
|
87
|
+
originalConsoleLoggerMethods = {};
|
|
88
|
+
for (const method of methods) {
|
|
89
|
+
if (typeof ConsoleLogger.prototype[method] === 'function') {
|
|
90
|
+
originalConsoleLoggerMethods[method] = ConsoleLogger.prototype[method];
|
|
91
|
+
ConsoleLogger.prototype[method] = createWrappedMethod(originalConsoleLoggerMethods[method], NEST_TO_SEVERITY[method], function () { return this.context; });
|
|
92
|
+
}
|
|
56
93
|
}
|
|
57
94
|
isCapturing = true;
|
|
95
|
+
console.log('[DEX SDK] NestJS Logger capture started');
|
|
58
96
|
}
|
|
59
97
|
/**
|
|
60
98
|
* Stop capturing NestJS native Logger output
|
|
61
99
|
*/
|
|
62
100
|
export function stopNestLoggerCapture() {
|
|
63
|
-
if (!isCapturing
|
|
101
|
+
if (!isCapturing) {
|
|
64
102
|
return;
|
|
65
103
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
const methods = ['log', 'error', 'warn', 'debug', 'verbose', 'fatal'];
|
|
105
|
+
// Restore static methods
|
|
106
|
+
if (originalStaticMethods) {
|
|
107
|
+
for (const method of methods) {
|
|
108
|
+
if (originalStaticMethods[method]) {
|
|
109
|
+
NestLogger[method] = originalStaticMethods[method];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
originalStaticMethods = null;
|
|
113
|
+
}
|
|
114
|
+
// Restore prototype methods
|
|
115
|
+
if (originalPrototypeMethods) {
|
|
116
|
+
for (const method of methods) {
|
|
117
|
+
if (originalPrototypeMethods[method]) {
|
|
118
|
+
NestLogger.prototype[method] = originalPrototypeMethods[method];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
originalPrototypeMethods = null;
|
|
122
|
+
}
|
|
123
|
+
// Restore ConsoleLogger methods
|
|
124
|
+
if (originalConsoleLoggerMethods) {
|
|
125
|
+
for (const method of methods) {
|
|
126
|
+
if (originalConsoleLoggerMethods[method]) {
|
|
127
|
+
ConsoleLogger.prototype[method] = originalConsoleLoggerMethods[method];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
originalConsoleLoggerMethods = null;
|
|
84
131
|
}
|
|
85
|
-
|
|
132
|
+
monitoringClientRef = null;
|
|
133
|
+
isCapturing = false;
|
|
86
134
|
}
|
|
87
135
|
/**
|
|
88
136
|
* Check if NestJS Logger capture is active
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk-node.module.d.ts","sourceRoot":"","sources":["../../src/lib/sdk-node.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EAEb,kBAAkB,EAClB,UAAU,EACV,eAAe,EAChB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAEL,sBAAsB,EAEvB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"sdk-node.module.d.ts","sourceRoot":"","sources":["../../src/lib/sdk-node.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EAEb,kBAAkB,EAClB,UAAU,EACV,eAAe,EAChB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAEL,sBAAsB,EAEvB,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAEL,YAAY,EACZ,YAAY,EACb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,2BAA2B;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,yFAAyF;IACzF,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;;;;;;;;GAWG;AACH,qBAEa,aAAc,YAAW,UAAU,EAAE,eAAe;IAC/D,OAAO,CAAC,MAAM,CAAC,YAAY,CAA6B;IAExD;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa;IAgG1D;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAK7C;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAUvC"}
|
|
@@ -8,7 +8,7 @@ import { MonitoringClient, createMonitoringClient, } from './monitoring-client.j
|
|
|
8
8
|
import { RemoteLogger, createRemoteLogger } from './remote-logger.js';
|
|
9
9
|
import { DexLoggerService, DEX_LOGGER_TOKEN } from './dex-logger.service.js';
|
|
10
10
|
import { startConsoleCapture, stopConsoleCapture } from './console-capture.js';
|
|
11
|
-
import { startNestLoggerCapture, stopNestLoggerCapture } from './nest-logger-capture.js';
|
|
11
|
+
import { startNestLoggerCapture, stopNestLoggerCapture, } from './nest-logger-capture.js';
|
|
12
12
|
import { Logger, LOGGER_TOKEN, } from '@dex-monit/observability-logger';
|
|
13
13
|
// Re-export LOGGER_TOKEN for convenience
|
|
14
14
|
export { LOGGER_TOKEN };
|