@dex-monit/observability-sdk-node 1.0.4 → 1.0.6

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.
@@ -0,0 +1,14 @@
1
+ import { MonitoringClient } from './monitoring-client.js';
2
+ /**
3
+ * Start capturing console output and sending to monitoring
4
+ */
5
+ export declare function startConsoleCapture(monitoringClient: MonitoringClient): void;
6
+ /**
7
+ * Stop capturing console output
8
+ */
9
+ export declare function stopConsoleCapture(): void;
10
+ /**
11
+ * Check if console capture is active
12
+ */
13
+ export declare function isConsoleCaptureActive(): boolean;
14
+ //# sourceMappingURL=console-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-capture.d.ts","sourceRoot":"","sources":["../../src/lib/console-capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAwB1D;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAyC5E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAazC;AAqBD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD"}
@@ -0,0 +1,87 @@
1
+ const CONSOLE_TO_SEVERITY = {
2
+ debug: 'debug',
3
+ log: 'info',
4
+ info: 'info',
5
+ warn: 'warning',
6
+ error: 'error',
7
+ };
8
+ let originalMethods = null;
9
+ let isCapturing = false;
10
+ /**
11
+ * Start capturing console output and sending to monitoring
12
+ */
13
+ export function startConsoleCapture(monitoringClient) {
14
+ if (isCapturing) {
15
+ return;
16
+ }
17
+ // Store original methods
18
+ originalMethods = {
19
+ log: console.log.bind(console),
20
+ info: console.info.bind(console),
21
+ warn: console.warn.bind(console),
22
+ error: console.error.bind(console),
23
+ debug: console.debug.bind(console),
24
+ };
25
+ const methods = ['log', 'info', 'warn', 'error', 'debug'];
26
+ for (const method of methods) {
27
+ const original = originalMethods[method];
28
+ const severity = CONSOLE_TO_SEVERITY[method];
29
+ console[method] = (...args) => {
30
+ // Call original console method first
31
+ original(...args);
32
+ // Skip if it's our own SDK log to avoid infinite loops
33
+ const message = formatConsoleArgs(args);
34
+ if (message.startsWith('[DEX SDK]') || message.startsWith('[MonitoringClient]') || message.startsWith('[RemoteLogger]')) {
35
+ return;
36
+ }
37
+ // Send to monitoring (fire and forget)
38
+ monitoringClient.captureLog(severity, message, {
39
+ source: 'console',
40
+ method,
41
+ }).catch(() => {
42
+ // Silently ignore - don't use console.error here to avoid loops
43
+ });
44
+ };
45
+ }
46
+ isCapturing = true;
47
+ }
48
+ /**
49
+ * Stop capturing console output
50
+ */
51
+ export function stopConsoleCapture() {
52
+ if (!isCapturing || !originalMethods) {
53
+ return;
54
+ }
55
+ console.log = originalMethods.log;
56
+ console.info = originalMethods.info;
57
+ console.warn = originalMethods.warn;
58
+ console.error = originalMethods.error;
59
+ console.debug = originalMethods.debug;
60
+ originalMethods = null;
61
+ isCapturing = false;
62
+ }
63
+ /**
64
+ * Format console arguments into a single message string
65
+ */
66
+ function formatConsoleArgs(args) {
67
+ return args.map(arg => {
68
+ if (typeof arg === 'string') {
69
+ return arg;
70
+ }
71
+ if (arg instanceof Error) {
72
+ return `${arg.name}: ${arg.message}\n${arg.stack || ''}`;
73
+ }
74
+ try {
75
+ return JSON.stringify(arg, null, 2);
76
+ }
77
+ catch {
78
+ return String(arg);
79
+ }
80
+ }).join(' ');
81
+ }
82
+ /**
83
+ * Check if console capture is active
84
+ */
85
+ export function isConsoleCaptureActive() {
86
+ return isCapturing;
87
+ }
@@ -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,EAAc,MAAM,oCAAoC,CAAC;AAEpG,OAAO,EAAsB,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,uDAAuD;IACvD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,GAAG,IAAI,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,WAAW;IACX,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,sBAAsB;IACtB,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAClC,mBAAmB;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;CAC7B;AAyCD;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAmC;gBAErC,MAAM,EAAE,sBAAsB;IAe1C;;OAEG;IACG,gBAAgB,CACpB,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgEzB;;OAEG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,QAAiB,EACxB,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAM,GAC1C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAwDzB;;OAEG;YACW,SAAS;IA6BvB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,UAAU,IAAI,MAAM;CAGrB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,gBAAgB,CAElB"}
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
+ }
@@ -3,4 +3,5 @@ export * from './request-id.middleware.js';
3
3
  export * from './global-exception.filter.js';
4
4
  export * from './error-capture.interceptor.js';
5
5
  export * from './monitoring-client.js';
6
+ export * from './console-capture.js';
6
7
  //# sourceMappingURL=sdk-node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-node.d.ts","sourceRoot":"","sources":["../../src/lib/sdk-node.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"sdk-node.d.ts","sourceRoot":"","sources":["../../src/lib/sdk-node.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
@@ -4,3 +4,4 @@ export * from './request-id.middleware.js';
4
4
  export * from './global-exception.filter.js';
5
5
  export * from './error-capture.interceptor.js';
6
6
  export * from './monitoring-client.js';
7
+ export * from './console-capture.js';
@@ -1,6 +1,7 @@
1
- import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
1
+ import { DynamicModule, MiddlewareConsumer, NestModule, OnModuleDestroy } 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,10 @@ 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: 'debug' = capture all) */
16
+ remoteLogLevel?: Severity;
17
+ /** Whether to capture console.log/warn/error (default: true) */
18
+ captureConsole?: boolean;
14
19
  }
15
20
  export { LOGGER_TOKEN };
16
21
  /**
@@ -24,10 +29,12 @@ export declare const MONITORING_CLIENT_TOKEN = "OBSERVABILITY_MONITORING_CLIENT"
24
29
  * - Request ID middleware for tracing
25
30
  * - Error capture interceptor (captures ALL errors, even if other filters exist)
26
31
  * - Global exception filter for error capture
27
- * - Logger instance
32
+ * - Logger instance (with automatic remote log capture if monitoring is configured)
33
+ * - Console capture (intercepts console.log/warn/error)
28
34
  * - Monitoring client instance
29
35
  */
30
- export declare class SdkNodeModule implements NestModule {
36
+ export declare class SdkNodeModule implements NestModule, OnModuleDestroy {
37
+ private static remoteLogger;
31
38
  /**
32
39
  * Register the module with configuration
33
40
  */
@@ -36,5 +43,9 @@ export declare class SdkNodeModule implements NestModule {
36
43
  * Configure middleware
37
44
  */
38
45
  configure(consumer: MiddlewareConsumer): void;
46
+ /**
47
+ * Cleanup on module destroy
48
+ */
49
+ onModuleDestroy(): Promise<void>;
39
50
  }
40
51
  //# sourceMappingURL=sdk-node.module.d.ts.map
@@ -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;AAChC,OAAO,EAGL,YAAY,EACZ,YAAY,EACb,MAAM,iCAAiC,CAAC;AAEzC;;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;CAClB;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;IA+C1D;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;CAI9C"}
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;AAGhC,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;CAC1B;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,uBAAuB,oCAAoC,CAAC;AAEzE;;;;;;;;;;GAUG;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;IAkE1D;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAK7C;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CASvC"}
@@ -5,7 +5,9 @@ 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 { Logger, createLogger, LOGGER_TOKEN, } from '@dex-monit/observability-logger';
8
+ import { RemoteLogger, createRemoteLogger } from './remote-logger.js';
9
+ import { startConsoleCapture, stopConsoleCapture } from './console-capture.js';
10
+ import { Logger, LOGGER_TOKEN, } from '@dex-monit/observability-logger';
9
11
  // Re-export LOGGER_TOKEN for convenience
10
12
  export { LOGGER_TOKEN };
11
13
  /**
@@ -19,7 +21,8 @@ export const MONITORING_CLIENT_TOKEN = 'OBSERVABILITY_MONITORING_CLIENT';
19
21
  * - Request ID middleware for tracing
20
22
  * - Error capture interceptor (captures ALL errors, even if other filters exist)
21
23
  * - Global exception filter for error capture
22
- * - Logger instance
24
+ * - Logger instance (with automatic remote log capture if monitoring is configured)
25
+ * - Console capture (intercepts console.log/warn/error)
23
26
  * - Monitoring client instance
24
27
  */
25
28
  let SdkNodeModule = (() => {
@@ -34,16 +37,27 @@ let SdkNodeModule = (() => {
34
37
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
35
38
  SdkNodeModule = _classThis = _classDescriptor.value;
36
39
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
37
- __runInitializers(_classThis, _classExtraInitializers);
38
40
  }
41
+ static remoteLogger = null;
39
42
  /**
40
43
  * Register the module with configuration
41
44
  */
42
45
  static forRoot(config) {
43
- const logger = createLogger(config.logger);
44
46
  const monitoringClient = config.monitoring
45
47
  ? createMonitoringClient(config.monitoring)
46
48
  : undefined;
49
+ // Use RemoteLogger if monitoring is configured
50
+ const logger = createRemoteLogger({
51
+ ...config.logger,
52
+ monitoringClient,
53
+ remoteLevel: config.remoteLogLevel || 'debug', // Default: capture ALL logs
54
+ });
55
+ // Store reference for cleanup
56
+ SdkNodeModule.remoteLogger = logger;
57
+ // Start console capture if enabled (default: true)
58
+ if (monitoringClient && (config.captureConsole ?? true)) {
59
+ startConsoleCapture(monitoringClient);
60
+ }
47
61
  return {
48
62
  module: SdkNodeModule,
49
63
  providers: [
@@ -55,6 +69,10 @@ let SdkNodeModule = (() => {
55
69
  provide: Logger,
56
70
  useValue: logger,
57
71
  },
72
+ {
73
+ provide: RemoteLogger,
74
+ useValue: logger,
75
+ },
58
76
  {
59
77
  provide: MONITORING_CLIENT_TOKEN,
60
78
  useValue: monitoringClient,
@@ -79,6 +97,7 @@ let SdkNodeModule = (() => {
79
97
  exports: [
80
98
  LOGGER_TOKEN,
81
99
  Logger,
100
+ RemoteLogger,
82
101
  MONITORING_CLIENT_TOKEN,
83
102
  MonitoringClient,
84
103
  ],
@@ -91,6 +110,20 @@ let SdkNodeModule = (() => {
91
110
  // Apply RequestIdMiddleware to all routes
92
111
  consumer.apply(RequestIdMiddleware).forRoutes('*');
93
112
  }
113
+ /**
114
+ * Cleanup on module destroy
115
+ */
116
+ async onModuleDestroy() {
117
+ // Stop console capture
118
+ stopConsoleCapture();
119
+ // Flush remaining logs
120
+ if (SdkNodeModule.remoteLogger) {
121
+ await SdkNodeModule.remoteLogger.close();
122
+ }
123
+ }
124
+ static {
125
+ __runInitializers(_classThis, _classExtraInitializers);
126
+ }
94
127
  };
95
128
  return SdkNodeModule = _classThis;
96
129
  })();