@ngn-net/nestjs-telescope 0.2.8 → 0.2.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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ngn-net/nestjs-telescope",
3
- "version": "0.2.8",
4
- "builtAt": "2026-06-08T12:41:45.083Z"
3
+ "version": "0.2.10",
4
+ "builtAt": "2026-06-08T12:50:24.624Z"
5
5
  }
@@ -22,6 +22,10 @@ let ExceptionWatcher = class ExceptionWatcher {
22
22
  this.telescope = telescope;
23
23
  }
24
24
  intercept(context, next) {
25
+ // Skip non-HTTP execution contexts (e.g. RPC/RabbitMQ or WebSockets)
26
+ if (context.getType() !== 'http') {
27
+ return next.handle();
28
+ }
25
29
  const request = context.switchToHttp().getRequest();
26
30
  return next.handle().pipe((0, operators_1.catchError)((err) => {
27
31
  this.telescope.record({
@@ -38,7 +42,7 @@ let ExceptionWatcher = class ExceptionWatcher {
38
42
  ip: request?.ip,
39
43
  },
40
44
  },
41
- });
45
+ }).catch(() => { });
42
46
  return (0, rxjs_1.throwError)(() => err);
43
47
  }));
44
48
  }
@@ -27,6 +27,10 @@ let HttpRequestWatcher = class HttpRequestWatcher {
27
27
  this.options = options;
28
28
  }
29
29
  intercept(context, next) {
30
+ // Skip non-HTTP execution contexts (e.g. RPC/RabbitMQ or WebSockets)
31
+ if (context.getType() !== 'http') {
32
+ return next.handle();
33
+ }
30
34
  const request = context.switchToHttp().getRequest();
31
35
  const response = context.switchToHttp().getResponse();
32
36
  const url = request.originalUrl || request.url || '/';
@@ -43,20 +47,40 @@ let HttpRequestWatcher = class HttpRequestWatcher {
43
47
  query: request.query,
44
48
  ip: request.ip,
45
49
  };
46
- return next.handle().pipe((0, operators_1.tap)((responseBody) => {
47
- const duration = Date.now() - start;
48
- const statusCode = response.statusCode || 200;
49
- this.telescope.record({
50
- type: entry_type_enum_1.EntryType.REQUEST,
51
- content: {
52
- request: requestData,
53
- response: {
54
- statusCode,
55
- body: responseBody,
50
+ return next.handle().pipe((0, operators_1.tap)({
51
+ next: (responseBody) => {
52
+ const duration = Date.now() - start;
53
+ const statusCode = response.statusCode || 200;
54
+ this.telescope.record({
55
+ type: entry_type_enum_1.EntryType.REQUEST,
56
+ content: {
57
+ request: requestData,
58
+ response: {
59
+ statusCode,
60
+ body: responseBody,
61
+ },
62
+ duration,
63
+ },
64
+ }).catch(() => { });
65
+ },
66
+ error: (error) => {
67
+ const duration = Date.now() - start;
68
+ const statusCode = error.status || error.statusCode || 500;
69
+ this.telescope.record({
70
+ type: entry_type_enum_1.EntryType.REQUEST,
71
+ content: {
72
+ request: requestData,
73
+ response: {
74
+ statusCode,
75
+ body: {
76
+ message: error.message || String(error),
77
+ error: error.name || 'Error',
78
+ },
79
+ },
80
+ duration,
56
81
  },
57
- duration,
58
- },
59
- });
82
+ }).catch(() => { });
83
+ },
60
84
  }));
61
85
  }
62
86
  };
@@ -14,6 +14,44 @@ exports.LogWatcher = void 0;
14
14
  const common_1 = require("@nestjs/common");
15
15
  const telescope_service_1 = require("../telescope.service");
16
16
  const entry_type_enum_1 = require("../enums/entry-type.enum");
17
+ class TelescopeLoggerWrapper {
18
+ original;
19
+ recordLog;
20
+ constructor(original, recordLog) {
21
+ this.original = original;
22
+ this.recordLog = recordLog;
23
+ }
24
+ log(message, ...optionalParams) {
25
+ this.recordLog('log', message, ...optionalParams);
26
+ this.original.log(message, ...optionalParams);
27
+ }
28
+ error(message, ...optionalParams) {
29
+ this.recordLog('error', message, ...optionalParams);
30
+ this.original.error(message, ...optionalParams);
31
+ }
32
+ warn(message, ...optionalParams) {
33
+ this.recordLog('warn', message, ...optionalParams);
34
+ this.original.warn(message, ...optionalParams);
35
+ }
36
+ debug(message, ...optionalParams) {
37
+ this.recordLog('debug', message, ...optionalParams);
38
+ if (this.original.debug) {
39
+ this.original.debug(message, ...optionalParams);
40
+ }
41
+ }
42
+ verbose(message, ...optionalParams) {
43
+ this.recordLog('verbose', message, ...optionalParams);
44
+ if (this.original.verbose) {
45
+ this.original.verbose(message, ...optionalParams);
46
+ }
47
+ }
48
+ fatal(message, ...optionalParams) {
49
+ this.recordLog('fatal', message, ...optionalParams);
50
+ if (this.original.fatal) {
51
+ this.original.fatal(message, ...optionalParams);
52
+ }
53
+ }
54
+ }
17
55
  let LogWatcher = class LogWatcher {
18
56
  telescope;
19
57
  isRecording = false; // Guard against infinite recursion
@@ -27,38 +65,76 @@ let LogWatcher = class LogWatcher {
27
65
  const originalDebug = console.debug.bind(console);
28
66
  const self = this;
29
67
  const formatArgs = (args) => args.map((a) => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ');
30
- const recordLog = (level, args) => {
31
- // Guard: if we're already recording, skip to prevent infinite recursion
32
- // (recording a log → save to DB → TypeORM logs → recording again → ...)
68
+ const recordConsoleLog = (level, args) => {
33
69
  if (self.isRecording)
34
70
  return;
71
+ const message = formatArgs(args);
72
+ // Skip telescope queries, logs, or dashboard routes to prevent recursion
73
+ if (message.includes('telescope_entries') || message.includes('TelescopeModule')) {
74
+ return;
75
+ }
35
76
  self.isRecording = true;
36
77
  try {
37
78
  self.telescope.record({
38
79
  type: entry_type_enum_1.EntryType.LOG,
39
- content: { level, message: formatArgs(args) },
40
- });
80
+ content: { level, message },
81
+ }).catch(() => { });
41
82
  }
42
83
  finally {
43
84
  self.isRecording = false;
44
85
  }
45
86
  };
87
+ // 1. Intercept raw console logs
46
88
  console.log = function (...args) {
47
- recordLog('log', args);
89
+ recordConsoleLog('log', args);
48
90
  return originalLog(...args);
49
91
  };
50
92
  console.error = function (...args) {
51
- recordLog('error', args);
93
+ recordConsoleLog('error', args);
52
94
  return originalError(...args);
53
95
  };
54
96
  console.warn = function (...args) {
55
- recordLog('warn', args);
97
+ recordConsoleLog('warn', args);
56
98
  return originalWarn(...args);
57
99
  };
58
100
  console.debug = function (...args) {
59
- recordLog('debug', args);
101
+ recordConsoleLog('debug', args);
60
102
  return originalDebug(...args);
61
103
  };
104
+ // 2. Intercept NestJS Logger Service logs
105
+ try {
106
+ const activeLogger = common_1.Logger.logger;
107
+ if (activeLogger && !(activeLogger instanceof TelescopeLoggerWrapper)) {
108
+ const wrapper = new TelescopeLoggerWrapper(activeLogger, (level, message, ...optionalParams) => {
109
+ if (self.isRecording)
110
+ return;
111
+ let formattedMessage = typeof message === 'object' ? JSON.stringify(message) : String(message);
112
+ if (optionalParams.length > 0) {
113
+ // Get context (usually the last parameter, e.g. [PurchaseService])
114
+ const context = optionalParams[optionalParams.length - 1];
115
+ const contextStr = typeof context === 'string' ? `[${context}] ` : '';
116
+ formattedMessage = contextStr + formattedMessage;
117
+ }
118
+ if (formattedMessage.includes('telescope_entries') || formattedMessage.includes('TelescopeModule')) {
119
+ return;
120
+ }
121
+ self.isRecording = true;
122
+ try {
123
+ self.telescope.record({
124
+ type: entry_type_enum_1.EntryType.LOG,
125
+ content: { level, message: formattedMessage },
126
+ }).catch(() => { });
127
+ }
128
+ finally {
129
+ self.isRecording = false;
130
+ }
131
+ });
132
+ common_1.Logger.overrideLogger(wrapper);
133
+ }
134
+ }
135
+ catch {
136
+ // Ignore errors if overrideLogger doesn't exist or fails
137
+ }
62
138
  }
63
139
  };
64
140
  exports.LogWatcher = LogWatcher;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngn-net/nestjs-telescope",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },