@dex-monit/observability-sdk-node 1.0.4 → 1.0.5
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/monitoring-client.d.ts +22 -0
- package/dist/lib/monitoring-client.d.ts.map +1 -1
- package/dist/lib/monitoring-client.js +111 -0
- package/dist/lib/remote-logger.d.ts +59 -0
- package/dist/lib/remote-logger.d.ts.map +1 -0
- package/dist/lib/remote-logger.js +160 -0
- package/dist/lib/sdk-node.module.d.ts +4 -1
- package/dist/lib/sdk-node.module.d.ts.map +1 -1
- package/dist/lib/sdk-node.module.js +16 -3
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -61,10 +61,32 @@ export declare class MonitoringClient {
|
|
|
61
61
|
* Capture a message as an event
|
|
62
62
|
*/
|
|
63
63
|
captureMessage(message: string, level?: Severity, options?: Omit<CaptureOptions, 'level'>): Promise<string | null>;
|
|
64
|
+
/**
|
|
65
|
+
* Capture a single log entry and send to monitoring service
|
|
66
|
+
*/
|
|
67
|
+
captureLog(level: Severity, message: string, data?: Record<string, unknown>, tags?: Record<string, string>): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Capture multiple log entries in batch
|
|
70
|
+
*/
|
|
71
|
+
captureLogs(logs: Array<{
|
|
72
|
+
level: Severity;
|
|
73
|
+
message: string;
|
|
74
|
+
data?: Record<string, unknown>;
|
|
75
|
+
tags?: Record<string, string>;
|
|
76
|
+
timestamp?: string;
|
|
77
|
+
}>): Promise<void>;
|
|
64
78
|
/**
|
|
65
79
|
* Send event to monitoring API
|
|
66
80
|
*/
|
|
67
81
|
private sendEvent;
|
|
82
|
+
/**
|
|
83
|
+
* Send single log to monitoring API
|
|
84
|
+
*/
|
|
85
|
+
private sendLog;
|
|
86
|
+
/**
|
|
87
|
+
* Send logs batch to monitoring API
|
|
88
|
+
*/
|
|
89
|
+
private sendLogsBatch;
|
|
68
90
|
/**
|
|
69
91
|
* Check if the client is enabled
|
|
70
92
|
*/
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"monitoring-client.d.ts","sourceRoot":"","sources":["../../src/lib/monitoring-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -173,6 +173,63 @@ export class MonitoringClient {
|
|
|
173
173
|
return null;
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Capture a single log entry and send to monitoring service
|
|
178
|
+
*/
|
|
179
|
+
async captureLog(level, message, data, tags) {
|
|
180
|
+
if (!this.config.enabled) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const requestContext = RequestContextService.get();
|
|
184
|
+
const logEvent = {
|
|
185
|
+
id: uuidv4(),
|
|
186
|
+
timestamp: new Date().toISOString(),
|
|
187
|
+
level,
|
|
188
|
+
message,
|
|
189
|
+
project: this.config.project,
|
|
190
|
+
environment: this.config.environment,
|
|
191
|
+
serverName: this.config.serverName,
|
|
192
|
+
requestId: requestContext?.requestId,
|
|
193
|
+
transactionId: requestContext?.transactionId,
|
|
194
|
+
data: data ? scrubSensitiveData(data, this.config.scrubberOptions) : undefined,
|
|
195
|
+
tags,
|
|
196
|
+
};
|
|
197
|
+
try {
|
|
198
|
+
await this.sendLog(logEvent);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
// Silently fail - don't break the app for logging issues
|
|
202
|
+
console.error('[MonitoringClient] Failed to send log:', err);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Capture multiple log entries in batch
|
|
207
|
+
*/
|
|
208
|
+
async captureLogs(logs) {
|
|
209
|
+
if (!this.config.enabled || logs.length === 0) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const requestContext = RequestContextService.get();
|
|
213
|
+
const logEvents = logs.map(log => ({
|
|
214
|
+
id: uuidv4(),
|
|
215
|
+
timestamp: log.timestamp || new Date().toISOString(),
|
|
216
|
+
level: log.level,
|
|
217
|
+
message: log.message,
|
|
218
|
+
project: this.config.project,
|
|
219
|
+
environment: this.config.environment,
|
|
220
|
+
serverName: this.config.serverName,
|
|
221
|
+
requestId: requestContext?.requestId,
|
|
222
|
+
transactionId: requestContext?.transactionId,
|
|
223
|
+
data: log.data ? scrubSensitiveData(log.data, this.config.scrubberOptions) : undefined,
|
|
224
|
+
tags: log.tags,
|
|
225
|
+
}));
|
|
226
|
+
try {
|
|
227
|
+
await this.sendLogsBatch(logEvents);
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
console.error('[MonitoringClient] Failed to send logs batch:', err);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
176
233
|
/**
|
|
177
234
|
* Send event to monitoring API
|
|
178
235
|
*/
|
|
@@ -201,6 +258,60 @@ export class MonitoringClient {
|
|
|
201
258
|
clearTimeout(timeoutId);
|
|
202
259
|
}
|
|
203
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Send single log to monitoring API
|
|
263
|
+
*/
|
|
264
|
+
async sendLog(log) {
|
|
265
|
+
const controller = new AbortController();
|
|
266
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
267
|
+
const headers = {
|
|
268
|
+
'Content-Type': 'application/json',
|
|
269
|
+
};
|
|
270
|
+
if (this.config.apiKey) {
|
|
271
|
+
headers['X-Dex-Key'] = this.config.apiKey;
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const response = await fetch(`${this.config.apiUrl}/ingest/logs`, {
|
|
275
|
+
method: 'POST',
|
|
276
|
+
headers,
|
|
277
|
+
body: JSON.stringify(log),
|
|
278
|
+
signal: controller.signal,
|
|
279
|
+
});
|
|
280
|
+
if (!response.ok) {
|
|
281
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
finally {
|
|
285
|
+
clearTimeout(timeoutId);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Send logs batch to monitoring API
|
|
290
|
+
*/
|
|
291
|
+
async sendLogsBatch(logs) {
|
|
292
|
+
const controller = new AbortController();
|
|
293
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
294
|
+
const headers = {
|
|
295
|
+
'Content-Type': 'application/json',
|
|
296
|
+
};
|
|
297
|
+
if (this.config.apiKey) {
|
|
298
|
+
headers['X-Dex-Key'] = this.config.apiKey;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const response = await fetch(`${this.config.apiUrl}/ingest/logs/batch`, {
|
|
302
|
+
method: 'POST',
|
|
303
|
+
headers,
|
|
304
|
+
body: JSON.stringify({ logs }),
|
|
305
|
+
signal: controller.signal,
|
|
306
|
+
});
|
|
307
|
+
if (!response.ok) {
|
|
308
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
finally {
|
|
312
|
+
clearTimeout(timeoutId);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
204
315
|
/**
|
|
205
316
|
* Check if the client is enabled
|
|
206
317
|
*/
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Logger, LogContext, LoggerConfig } from '@dex-monit/observability-logger';
|
|
2
|
+
import { MonitoringClient } from './monitoring-client.js';
|
|
3
|
+
import { Severity } from '@dex-monit/observability-contracts';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for remote logger
|
|
6
|
+
*/
|
|
7
|
+
export interface RemoteLoggerConfig extends LoggerConfig {
|
|
8
|
+
/** Monitoring client for remote log capture */
|
|
9
|
+
monitoringClient?: MonitoringClient;
|
|
10
|
+
/** Minimum level to send remotely (default: 'info') */
|
|
11
|
+
remoteLevel?: Severity;
|
|
12
|
+
/** Whether to buffer logs and send in batches (default: true) */
|
|
13
|
+
bufferLogs?: boolean;
|
|
14
|
+
/** Buffer flush interval in ms (default: 5000) */
|
|
15
|
+
flushInterval?: number;
|
|
16
|
+
/** Maximum buffer size before auto-flush (default: 100) */
|
|
17
|
+
maxBufferSize?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Remote Logger
|
|
21
|
+
*
|
|
22
|
+
* Extends the base Logger with automatic remote log capture.
|
|
23
|
+
* Logs are buffered and sent in batches for efficiency.
|
|
24
|
+
*/
|
|
25
|
+
export declare class RemoteLogger extends Logger {
|
|
26
|
+
private monitoringClient?;
|
|
27
|
+
private remoteLevel;
|
|
28
|
+
private bufferLogs;
|
|
29
|
+
private buffer;
|
|
30
|
+
private flushInterval;
|
|
31
|
+
private maxBufferSize;
|
|
32
|
+
private flushTimer?;
|
|
33
|
+
constructor(config: RemoteLoggerConfig);
|
|
34
|
+
private startFlushTimer;
|
|
35
|
+
private shouldSendRemotely;
|
|
36
|
+
private addToBuffer;
|
|
37
|
+
private sendLog;
|
|
38
|
+
/**
|
|
39
|
+
* Flush buffered logs to monitoring service
|
|
40
|
+
*/
|
|
41
|
+
flush(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Stop the flush timer and flush remaining logs
|
|
44
|
+
*/
|
|
45
|
+
close(): Promise<void>;
|
|
46
|
+
debug(message: string, context?: LogContext): void;
|
|
47
|
+
info(message: string, context?: LogContext): void;
|
|
48
|
+
warn(message: string, context?: LogContext): void;
|
|
49
|
+
error(message: string, context?: LogContext): void;
|
|
50
|
+
error(error: Error, context?: LogContext): void;
|
|
51
|
+
error(message: string, error: Error, context?: LogContext): void;
|
|
52
|
+
fatal(message: string, context?: LogContext): void;
|
|
53
|
+
fatal(error: Error, context?: LogContext): void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create a remote logger instance
|
|
57
|
+
*/
|
|
58
|
+
export declare function createRemoteLogger(config: RemoteLoggerConfig): RemoteLogger;
|
|
59
|
+
//# sourceMappingURL=remote-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-logger.d.ts","sourceRoot":"","sources":["../../src/lib/remote-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,uDAAuD;IACvD,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAkBD;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,MAAM;IACtC,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,WAAW,CAAW;IAC9B,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAiC;gBAExC,MAAM,EAAE,kBAAkB;IActC,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,OAAO;IAmBf;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUnB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAKlD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAKjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAKjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAClD,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAiChE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAClD,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;CAiBzD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAE3E"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Logger } from '@dex-monit/observability-logger';
|
|
2
|
+
const LEVEL_PRIORITY = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warning: 2,
|
|
6
|
+
error: 3,
|
|
7
|
+
fatal: 4,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Remote Logger
|
|
11
|
+
*
|
|
12
|
+
* Extends the base Logger with automatic remote log capture.
|
|
13
|
+
* Logs are buffered and sent in batches for efficiency.
|
|
14
|
+
*/
|
|
15
|
+
export class RemoteLogger extends Logger {
|
|
16
|
+
monitoringClient;
|
|
17
|
+
remoteLevel;
|
|
18
|
+
bufferLogs;
|
|
19
|
+
buffer = [];
|
|
20
|
+
flushInterval;
|
|
21
|
+
maxBufferSize;
|
|
22
|
+
flushTimer;
|
|
23
|
+
constructor(config) {
|
|
24
|
+
super(config);
|
|
25
|
+
this.monitoringClient = config.monitoringClient;
|
|
26
|
+
this.remoteLevel = config.remoteLevel || 'info';
|
|
27
|
+
this.bufferLogs = config.bufferLogs ?? true;
|
|
28
|
+
this.flushInterval = config.flushInterval || 5000;
|
|
29
|
+
this.maxBufferSize = config.maxBufferSize || 100;
|
|
30
|
+
// Start buffer flush timer
|
|
31
|
+
if (this.bufferLogs && this.monitoringClient) {
|
|
32
|
+
this.startFlushTimer();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
startFlushTimer() {
|
|
36
|
+
this.flushTimer = setInterval(() => {
|
|
37
|
+
this.flush().catch(console.error);
|
|
38
|
+
}, this.flushInterval);
|
|
39
|
+
}
|
|
40
|
+
shouldSendRemotely(level) {
|
|
41
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.remoteLevel];
|
|
42
|
+
}
|
|
43
|
+
addToBuffer(log) {
|
|
44
|
+
this.buffer.push(log);
|
|
45
|
+
// Auto-flush if buffer is full
|
|
46
|
+
if (this.buffer.length >= this.maxBufferSize) {
|
|
47
|
+
this.flush().catch(console.error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
sendLog(level, message, context) {
|
|
51
|
+
if (!this.monitoringClient || !this.shouldSendRemotely(level)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const log = {
|
|
55
|
+
level,
|
|
56
|
+
message,
|
|
57
|
+
data: context,
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
};
|
|
60
|
+
if (this.bufferLogs) {
|
|
61
|
+
this.addToBuffer(log);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.monitoringClient.captureLog(level, message, context).catch(console.error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Flush buffered logs to monitoring service
|
|
69
|
+
*/
|
|
70
|
+
async flush() {
|
|
71
|
+
if (!this.monitoringClient || this.buffer.length === 0) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const logsToSend = [...this.buffer];
|
|
75
|
+
this.buffer = [];
|
|
76
|
+
try {
|
|
77
|
+
await this.monitoringClient.captureLogs(logsToSend);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
// Put logs back in buffer on failure (up to max size)
|
|
81
|
+
this.buffer = [...logsToSend.slice(0, this.maxBufferSize - this.buffer.length), ...this.buffer];
|
|
82
|
+
console.error('[RemoteLogger] Failed to flush logs:', err);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Stop the flush timer and flush remaining logs
|
|
87
|
+
*/
|
|
88
|
+
async close() {
|
|
89
|
+
if (this.flushTimer) {
|
|
90
|
+
clearInterval(this.flushTimer);
|
|
91
|
+
this.flushTimer = undefined;
|
|
92
|
+
}
|
|
93
|
+
await this.flush();
|
|
94
|
+
}
|
|
95
|
+
// Override log methods to also send remotely
|
|
96
|
+
debug(message, context) {
|
|
97
|
+
super.debug(message, context);
|
|
98
|
+
this.sendLog('debug', message, context);
|
|
99
|
+
}
|
|
100
|
+
info(message, context) {
|
|
101
|
+
super.info(message, context);
|
|
102
|
+
this.sendLog('info', message, context);
|
|
103
|
+
}
|
|
104
|
+
warn(message, context) {
|
|
105
|
+
super.warn(message, context);
|
|
106
|
+
this.sendLog('warning', message, context);
|
|
107
|
+
}
|
|
108
|
+
error(messageOrError, errorOrContext, context) {
|
|
109
|
+
// Call parent error method
|
|
110
|
+
if (messageOrError instanceof Error) {
|
|
111
|
+
super.error(messageOrError, errorOrContext);
|
|
112
|
+
this.sendLog('error', messageOrError.message, {
|
|
113
|
+
error: {
|
|
114
|
+
name: messageOrError.name,
|
|
115
|
+
message: messageOrError.message,
|
|
116
|
+
stack: messageOrError.stack,
|
|
117
|
+
},
|
|
118
|
+
...errorOrContext,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else if (errorOrContext instanceof Error) {
|
|
122
|
+
super.error(messageOrError, errorOrContext, context);
|
|
123
|
+
this.sendLog('error', messageOrError, {
|
|
124
|
+
error: {
|
|
125
|
+
name: errorOrContext.name,
|
|
126
|
+
message: errorOrContext.message,
|
|
127
|
+
stack: errorOrContext.stack,
|
|
128
|
+
},
|
|
129
|
+
...context,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
super.error(messageOrError, errorOrContext);
|
|
134
|
+
this.sendLog('error', messageOrError, errorOrContext);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
fatal(messageOrError, context) {
|
|
138
|
+
if (messageOrError instanceof Error) {
|
|
139
|
+
super.fatal(messageOrError, context);
|
|
140
|
+
this.sendLog('fatal', messageOrError.message, {
|
|
141
|
+
error: {
|
|
142
|
+
name: messageOrError.name,
|
|
143
|
+
message: messageOrError.message,
|
|
144
|
+
stack: messageOrError.stack,
|
|
145
|
+
},
|
|
146
|
+
...context,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
super.fatal(messageOrError, context);
|
|
151
|
+
this.sendLog('fatal', messageOrError, context);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Create a remote logger instance
|
|
157
|
+
*/
|
|
158
|
+
export function createRemoteLogger(config) {
|
|
159
|
+
return new RemoteLogger(config);
|
|
160
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
2
2
|
import { MonitoringClientConfig } from './monitoring-client.js';
|
|
3
3
|
import { LoggerConfig, LOGGER_TOKEN } from '@dex-monit/observability-logger';
|
|
4
|
+
import { Severity } from '@dex-monit/observability-contracts';
|
|
4
5
|
/**
|
|
5
6
|
* SDK Node module configuration
|
|
6
7
|
*/
|
|
@@ -11,6 +12,8 @@ export interface SdkNodeModuleConfig {
|
|
|
11
12
|
monitoring?: MonitoringClientConfig;
|
|
12
13
|
/** Whether to apply middleware globally */
|
|
13
14
|
global?: boolean;
|
|
15
|
+
/** Minimum log level to send remotely (default: 'info') */
|
|
16
|
+
remoteLogLevel?: Severity;
|
|
14
17
|
}
|
|
15
18
|
export { LOGGER_TOKEN };
|
|
16
19
|
/**
|
|
@@ -24,7 +27,7 @@ export declare const MONITORING_CLIENT_TOKEN = "OBSERVABILITY_MONITORING_CLIENT"
|
|
|
24
27
|
* - Request ID middleware for tracing
|
|
25
28
|
* - Error capture interceptor (captures ALL errors, even if other filters exist)
|
|
26
29
|
* - Global exception filter for error capture
|
|
27
|
-
* - Logger instance
|
|
30
|
+
* - Logger instance (with automatic remote log capture if monitoring is configured)
|
|
28
31
|
* - Monitoring client instance
|
|
29
32
|
*/
|
|
30
33
|
export declare class SdkNodeModule implements NestModule {
|
|
@@ -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,EACX,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,EACX,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAEL,sBAAsB,EAEvB,MAAM,wBAAwB,CAAC;AAEhC,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,2DAA2D;IAC3D,cAAc,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;;;;;;GASG;AACH,qBAEa,aAAc,YAAW,UAAU;IAC9C;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa;IA4D1D;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;CAI9C"}
|
|
@@ -5,7 +5,8 @@ import { RequestIdMiddleware } from './request-id.middleware.js';
|
|
|
5
5
|
import { GlobalExceptionFilter } from './global-exception.filter.js';
|
|
6
6
|
import { ErrorCaptureInterceptor } from './error-capture.interceptor.js';
|
|
7
7
|
import { MonitoringClient, createMonitoringClient, } from './monitoring-client.js';
|
|
8
|
-
import {
|
|
8
|
+
import { RemoteLogger, createRemoteLogger } from './remote-logger.js';
|
|
9
|
+
import { Logger, LOGGER_TOKEN, } from '@dex-monit/observability-logger';
|
|
9
10
|
// Re-export LOGGER_TOKEN for convenience
|
|
10
11
|
export { LOGGER_TOKEN };
|
|
11
12
|
/**
|
|
@@ -19,7 +20,7 @@ export const MONITORING_CLIENT_TOKEN = 'OBSERVABILITY_MONITORING_CLIENT';
|
|
|
19
20
|
* - Request ID middleware for tracing
|
|
20
21
|
* - Error capture interceptor (captures ALL errors, even if other filters exist)
|
|
21
22
|
* - Global exception filter for error capture
|
|
22
|
-
* - Logger instance
|
|
23
|
+
* - Logger instance (with automatic remote log capture if monitoring is configured)
|
|
23
24
|
* - Monitoring client instance
|
|
24
25
|
*/
|
|
25
26
|
let SdkNodeModule = (() => {
|
|
@@ -40,10 +41,17 @@ let SdkNodeModule = (() => {
|
|
|
40
41
|
* Register the module with configuration
|
|
41
42
|
*/
|
|
42
43
|
static forRoot(config) {
|
|
43
|
-
const logger = createLogger(config.logger);
|
|
44
44
|
const monitoringClient = config.monitoring
|
|
45
45
|
? createMonitoringClient(config.monitoring)
|
|
46
46
|
: undefined;
|
|
47
|
+
// Use RemoteLogger if monitoring is configured, otherwise use base Logger
|
|
48
|
+
const logger = monitoringClient
|
|
49
|
+
? createRemoteLogger({
|
|
50
|
+
...config.logger,
|
|
51
|
+
monitoringClient,
|
|
52
|
+
remoteLevel: config.remoteLogLevel || 'info',
|
|
53
|
+
})
|
|
54
|
+
: createRemoteLogger(config.logger);
|
|
47
55
|
return {
|
|
48
56
|
module: SdkNodeModule,
|
|
49
57
|
providers: [
|
|
@@ -55,6 +63,10 @@ let SdkNodeModule = (() => {
|
|
|
55
63
|
provide: Logger,
|
|
56
64
|
useValue: logger,
|
|
57
65
|
},
|
|
66
|
+
{
|
|
67
|
+
provide: RemoteLogger,
|
|
68
|
+
useValue: logger,
|
|
69
|
+
},
|
|
58
70
|
{
|
|
59
71
|
provide: MONITORING_CLIENT_TOKEN,
|
|
60
72
|
useValue: monitoringClient,
|
|
@@ -79,6 +91,7 @@ let SdkNodeModule = (() => {
|
|
|
79
91
|
exports: [
|
|
80
92
|
LOGGER_TOKEN,
|
|
81
93
|
Logger,
|
|
94
|
+
RemoteLogger,
|
|
82
95
|
MONITORING_CLIENT_TOKEN,
|
|
83
96
|
MonitoringClient,
|
|
84
97
|
],
|