@unito/integration-sdk 2.3.4 → 2.3.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/src/index.cjs +12 -12
- package/dist/src/resources/logger.js +12 -12
- package/dist/test/resources/logger.test.js +57 -0
- package/package.json +1 -1
- package/src/resources/logger.ts +14 -13
- package/test/resources/logger.test.ts +69 -0
package/dist/src/index.cjs
CHANGED
|
@@ -165,9 +165,10 @@ class Logger {
|
|
|
165
165
|
const coloredMessage = Logger.colorize(message, processedLogs, logLevel);
|
|
166
166
|
const metadata = {
|
|
167
167
|
date: new Date(processedLogs.date).toISOString(),
|
|
168
|
-
...processedMetadata,
|
|
168
|
+
...(processedMetadata.error && { error: processedMetadata.error }),
|
|
169
169
|
};
|
|
170
|
-
|
|
170
|
+
const metadataString = Object.keys(metadata).length > 1 ? ` ${JSON.stringify(metadata, null, 2)}` : ` ${JSON.stringify(metadata)}`;
|
|
171
|
+
console[logLevel](`${coloredMessage}${metadataString}`);
|
|
171
172
|
}
|
|
172
173
|
else {
|
|
173
174
|
console[logLevel](JSON.stringify(processedLogs));
|
|
@@ -219,9 +220,8 @@ class Logger {
|
|
|
219
220
|
*/
|
|
220
221
|
static colorize(message, metadata, logLevel) {
|
|
221
222
|
if (!process.stdout.isTTY) {
|
|
222
|
-
return message
|
|
223
|
+
return `${logLevel}: ${message}`;
|
|
223
224
|
}
|
|
224
|
-
const logOutput = `${logLevel}: ${message}`;
|
|
225
225
|
// Extract status code from logs
|
|
226
226
|
let statusCode;
|
|
227
227
|
if (metadata.http && typeof metadata.http === 'object' && !Array.isArray(metadata.http)) {
|
|
@@ -236,28 +236,28 @@ class Logger {
|
|
|
236
236
|
// Color based on status code first
|
|
237
237
|
if (statusCode) {
|
|
238
238
|
if (statusCode >= 400) {
|
|
239
|
-
return util.styleText('red',
|
|
239
|
+
return `${util.styleText('red', logLevel)}: ${util.styleText('red', message)}`;
|
|
240
240
|
}
|
|
241
241
|
else if (statusCode >= 300) {
|
|
242
|
-
return util.styleText('yellow',
|
|
242
|
+
return `${util.styleText('yellow', logLevel)}: ${util.styleText('yellow', message)}`;
|
|
243
243
|
}
|
|
244
244
|
else if (statusCode >= 200) {
|
|
245
|
-
return util.styleText('green',
|
|
245
|
+
return `${util.styleText('green', logLevel)}: ${util.styleText('green', message)}`;
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
// Fall back to log level if no status code found
|
|
249
249
|
switch (logLevel) {
|
|
250
250
|
case LogLevel.ERROR:
|
|
251
|
-
return util.styleText('red',
|
|
251
|
+
return `${util.styleText('red', logLevel)}: ${util.styleText('red', message)}`;
|
|
252
252
|
case LogLevel.WARN:
|
|
253
|
-
return util.styleText('yellow',
|
|
253
|
+
return `${util.styleText('yellow', logLevel)}: ${util.styleText('yellow', message)}`;
|
|
254
254
|
case LogLevel.INFO:
|
|
255
255
|
case LogLevel.LOG:
|
|
256
|
-
return util.styleText('green',
|
|
256
|
+
return `${util.styleText('green', logLevel)}: ${util.styleText('green', message)}`;
|
|
257
257
|
case LogLevel.DEBUG:
|
|
258
|
-
return util.styleText('cyan',
|
|
258
|
+
return `${util.styleText('cyan', logLevel)}: ${util.styleText('cyan', message)}`;
|
|
259
259
|
default:
|
|
260
|
-
return
|
|
260
|
+
return `${logLevel}: ${message}`;
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
}
|
|
@@ -137,9 +137,10 @@ export default class Logger {
|
|
|
137
137
|
const coloredMessage = Logger.colorize(message, processedLogs, logLevel);
|
|
138
138
|
const metadata = {
|
|
139
139
|
date: new Date(processedLogs.date).toISOString(),
|
|
140
|
-
...processedMetadata,
|
|
140
|
+
...(processedMetadata.error && { error: processedMetadata.error }),
|
|
141
141
|
};
|
|
142
|
-
|
|
142
|
+
const metadataString = Object.keys(metadata).length > 1 ? ` ${JSON.stringify(metadata, null, 2)}` : ` ${JSON.stringify(metadata)}`;
|
|
143
|
+
console[logLevel](`${coloredMessage}${metadataString}`);
|
|
143
144
|
}
|
|
144
145
|
else {
|
|
145
146
|
console[logLevel](JSON.stringify(processedLogs));
|
|
@@ -191,9 +192,8 @@ export default class Logger {
|
|
|
191
192
|
*/
|
|
192
193
|
static colorize(message, metadata, logLevel) {
|
|
193
194
|
if (!process.stdout.isTTY) {
|
|
194
|
-
return message
|
|
195
|
+
return `${logLevel}: ${message}`;
|
|
195
196
|
}
|
|
196
|
-
const logOutput = `${logLevel}: ${message}`;
|
|
197
197
|
// Extract status code from logs
|
|
198
198
|
let statusCode;
|
|
199
199
|
if (metadata.http && typeof metadata.http === 'object' && !Array.isArray(metadata.http)) {
|
|
@@ -208,28 +208,28 @@ export default class Logger {
|
|
|
208
208
|
// Color based on status code first
|
|
209
209
|
if (statusCode) {
|
|
210
210
|
if (statusCode >= 400) {
|
|
211
|
-
return styleText('red',
|
|
211
|
+
return `${styleText('red', logLevel)}: ${styleText('red', message)}`;
|
|
212
212
|
}
|
|
213
213
|
else if (statusCode >= 300) {
|
|
214
|
-
return styleText('yellow',
|
|
214
|
+
return `${styleText('yellow', logLevel)}: ${styleText('yellow', message)}`;
|
|
215
215
|
}
|
|
216
216
|
else if (statusCode >= 200) {
|
|
217
|
-
return styleText('green',
|
|
217
|
+
return `${styleText('green', logLevel)}: ${styleText('green', message)}`;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
// Fall back to log level if no status code found
|
|
221
221
|
switch (logLevel) {
|
|
222
222
|
case LogLevel.ERROR:
|
|
223
|
-
return styleText('red',
|
|
223
|
+
return `${styleText('red', logLevel)}: ${styleText('red', message)}`;
|
|
224
224
|
case LogLevel.WARN:
|
|
225
|
-
return styleText('yellow',
|
|
225
|
+
return `${styleText('yellow', logLevel)}: ${styleText('yellow', message)}`;
|
|
226
226
|
case LogLevel.INFO:
|
|
227
227
|
case LogLevel.LOG:
|
|
228
|
-
return styleText('green',
|
|
228
|
+
return `${styleText('green', logLevel)}: ${styleText('green', message)}`;
|
|
229
229
|
case LogLevel.DEBUG:
|
|
230
|
-
return styleText('cyan',
|
|
230
|
+
return `${styleText('cyan', logLevel)}: ${styleText('cyan', message)}`;
|
|
231
231
|
default:
|
|
232
|
-
return
|
|
232
|
+
return `${logLevel}: ${message}`;
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
}
|
|
@@ -250,4 +250,61 @@ describe('Logger', () => {
|
|
|
250
250
|
});
|
|
251
251
|
}
|
|
252
252
|
});
|
|
253
|
+
it('only logs date for metadata of successful requests in development', testContext => {
|
|
254
|
+
const originalEnv = process.env.NODE_ENV;
|
|
255
|
+
try {
|
|
256
|
+
process.env.NODE_ENV = 'development';
|
|
257
|
+
const infoSpy = testContext.mock.method(global.console, 'info', () => { });
|
|
258
|
+
const metadata = {
|
|
259
|
+
correlation_id: '123456789',
|
|
260
|
+
http: { method: 'GET', status_code: 200 },
|
|
261
|
+
user_id: 'user123',
|
|
262
|
+
request_id: 'req456',
|
|
263
|
+
};
|
|
264
|
+
const logger = new Logger(metadata);
|
|
265
|
+
logger.info('Test message without error');
|
|
266
|
+
assert.strictEqual(infoSpy.mock.calls.length, 1);
|
|
267
|
+
const loggedOutput = infoSpy.mock.calls[0]?.arguments[0];
|
|
268
|
+
assert.ok(loggedOutput.includes('Test message without error'));
|
|
269
|
+
// Should only contain date in metadata JSON
|
|
270
|
+
const metadataMatch = loggedOutput.match(/({.*})/);
|
|
271
|
+
assert.ok(metadataMatch);
|
|
272
|
+
const parsedMetadata = JSON.parse(metadataMatch[1]);
|
|
273
|
+
assert.ok(parsedMetadata.date);
|
|
274
|
+
assert.strictEqual(Object.keys(parsedMetadata).length, 1); // What matters: Only the date
|
|
275
|
+
}
|
|
276
|
+
finally {
|
|
277
|
+
process.env.NODE_ENV = originalEnv;
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
it('logs date & error stack for metadata of failed requests in development', testContext => {
|
|
281
|
+
const originalEnv = process.env.NODE_ENV;
|
|
282
|
+
try {
|
|
283
|
+
process.env.NODE_ENV = 'development';
|
|
284
|
+
const metadata = {
|
|
285
|
+
correlation_id: '123456789',
|
|
286
|
+
http: { method: 'GET', status_code: 200 },
|
|
287
|
+
user_id: 'user123',
|
|
288
|
+
request_id: 'req456',
|
|
289
|
+
};
|
|
290
|
+
const logger = new Logger(metadata);
|
|
291
|
+
// Test with error metadata
|
|
292
|
+
const errorSpy = testContext.mock.method(global.console, 'error', () => { });
|
|
293
|
+
logger.error('Test message with error', { error: { code: 500, message: 'Internal Server Error' } });
|
|
294
|
+
assert.strictEqual(errorSpy.mock.calls.length, 1);
|
|
295
|
+
const errorLoggedOutput = errorSpy.mock.calls[0]?.arguments[0];
|
|
296
|
+
assert.ok(errorLoggedOutput.includes('Test message with error'));
|
|
297
|
+
// Should contain both date and error in metadata JSON
|
|
298
|
+
const errorMetadataMatch = errorLoggedOutput.match(/({.*})/s);
|
|
299
|
+
assert.ok(errorMetadataMatch);
|
|
300
|
+
const parsedErrorMetadata = JSON.parse(errorMetadataMatch[1]);
|
|
301
|
+
assert.ok(parsedErrorMetadata.date);
|
|
302
|
+
assert.ok(parsedErrorMetadata.error);
|
|
303
|
+
assert.deepEqual(parsedErrorMetadata.error, { code: 500, message: 'Internal Server Error' });
|
|
304
|
+
assert.strictEqual(Object.keys(parsedErrorMetadata).length, 2); // What matters: Date and error only
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
process.env.NODE_ENV = originalEnv;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
253
310
|
});
|
package/package.json
CHANGED
package/src/resources/logger.ts
CHANGED
|
@@ -168,10 +168,13 @@ export default class Logger {
|
|
|
168
168
|
|
|
169
169
|
const metadata = {
|
|
170
170
|
date: new Date(processedLogs.date).toISOString(),
|
|
171
|
-
...processedMetadata,
|
|
171
|
+
...(processedMetadata.error && { error: processedMetadata.error }),
|
|
172
172
|
};
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
const metadataString =
|
|
175
|
+
Object.keys(metadata).length > 1 ? ` ${JSON.stringify(metadata, null, 2)}` : ` ${JSON.stringify(metadata)}`;
|
|
176
|
+
|
|
177
|
+
console[logLevel](`${coloredMessage}${metadataString}`);
|
|
175
178
|
} else {
|
|
176
179
|
console[logLevel](JSON.stringify(processedLogs));
|
|
177
180
|
}
|
|
@@ -228,11 +231,9 @@ export default class Logger {
|
|
|
228
231
|
*/
|
|
229
232
|
private static colorize(message: string, metadata: Value, logLevel: LogLevel): string {
|
|
230
233
|
if (!process.stdout.isTTY) {
|
|
231
|
-
return message
|
|
234
|
+
return `${logLevel}: ${message}`;
|
|
232
235
|
}
|
|
233
236
|
|
|
234
|
-
const logOutput = `${logLevel}: ${message}`;
|
|
235
|
-
|
|
236
237
|
// Extract status code from logs
|
|
237
238
|
let statusCode: number | undefined;
|
|
238
239
|
if (metadata.http && typeof metadata.http === 'object' && !Array.isArray(metadata.http)) {
|
|
@@ -248,27 +249,27 @@ export default class Logger {
|
|
|
248
249
|
// Color based on status code first
|
|
249
250
|
if (statusCode) {
|
|
250
251
|
if (statusCode >= 400) {
|
|
251
|
-
return styleText('red',
|
|
252
|
+
return `${styleText('red', logLevel)}: ${styleText('red', message)}`;
|
|
252
253
|
} else if (statusCode >= 300) {
|
|
253
|
-
return styleText('yellow',
|
|
254
|
+
return `${styleText('yellow', logLevel)}: ${styleText('yellow', message)}`;
|
|
254
255
|
} else if (statusCode >= 200) {
|
|
255
|
-
return styleText('green',
|
|
256
|
+
return `${styleText('green', logLevel)}: ${styleText('green', message)}`;
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
// Fall back to log level if no status code found
|
|
260
261
|
switch (logLevel) {
|
|
261
262
|
case LogLevel.ERROR:
|
|
262
|
-
return styleText('red',
|
|
263
|
+
return `${styleText('red', logLevel)}: ${styleText('red', message)}`;
|
|
263
264
|
case LogLevel.WARN:
|
|
264
|
-
return styleText('yellow',
|
|
265
|
+
return `${styleText('yellow', logLevel)}: ${styleText('yellow', message)}`;
|
|
265
266
|
case LogLevel.INFO:
|
|
266
267
|
case LogLevel.LOG:
|
|
267
|
-
return styleText('green',
|
|
268
|
+
return `${styleText('green', logLevel)}: ${styleText('green', message)}`;
|
|
268
269
|
case LogLevel.DEBUG:
|
|
269
|
-
return styleText('cyan',
|
|
270
|
+
return `${styleText('cyan', logLevel)}: ${styleText('cyan', message)}`;
|
|
270
271
|
default:
|
|
271
|
-
return
|
|
272
|
+
return `${logLevel}: ${message}`;
|
|
272
273
|
}
|
|
273
274
|
}
|
|
274
275
|
}
|
|
@@ -291,4 +291,73 @@ describe('Logger', () => {
|
|
|
291
291
|
});
|
|
292
292
|
}
|
|
293
293
|
});
|
|
294
|
+
|
|
295
|
+
it('only logs date for metadata of successful requests in development', testContext => {
|
|
296
|
+
const originalEnv = process.env.NODE_ENV;
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
process.env.NODE_ENV = 'development';
|
|
300
|
+
|
|
301
|
+
const infoSpy = testContext.mock.method(global.console, 'info', () => {});
|
|
302
|
+
const metadata = {
|
|
303
|
+
correlation_id: '123456789',
|
|
304
|
+
http: { method: 'GET', status_code: 200 },
|
|
305
|
+
user_id: 'user123',
|
|
306
|
+
request_id: 'req456',
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const logger = new Logger(metadata);
|
|
310
|
+
|
|
311
|
+
logger.info('Test message without error');
|
|
312
|
+
assert.strictEqual(infoSpy.mock.calls.length, 1);
|
|
313
|
+
|
|
314
|
+
const loggedOutput = infoSpy.mock.calls[0]?.arguments[0];
|
|
315
|
+
assert.ok(loggedOutput.includes('Test message without error'));
|
|
316
|
+
|
|
317
|
+
// Should only contain date in metadata JSON
|
|
318
|
+
const metadataMatch = loggedOutput.match(/({.*})/);
|
|
319
|
+
assert.ok(metadataMatch);
|
|
320
|
+
const parsedMetadata = JSON.parse(metadataMatch[1]);
|
|
321
|
+
assert.ok(parsedMetadata.date);
|
|
322
|
+
assert.strictEqual(Object.keys(parsedMetadata).length, 1); // What matters: Only the date
|
|
323
|
+
} finally {
|
|
324
|
+
process.env.NODE_ENV = originalEnv;
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('logs date & error stack for metadata of failed requests in development', testContext => {
|
|
329
|
+
const originalEnv = process.env.NODE_ENV;
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
process.env.NODE_ENV = 'development';
|
|
333
|
+
|
|
334
|
+
const metadata = {
|
|
335
|
+
correlation_id: '123456789',
|
|
336
|
+
http: { method: 'GET', status_code: 200 },
|
|
337
|
+
user_id: 'user123',
|
|
338
|
+
request_id: 'req456',
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const logger = new Logger(metadata);
|
|
342
|
+
|
|
343
|
+
// Test with error metadata
|
|
344
|
+
const errorSpy = testContext.mock.method(global.console, 'error', () => {});
|
|
345
|
+
logger.error('Test message with error', { error: { code: 500, message: 'Internal Server Error' } });
|
|
346
|
+
assert.strictEqual(errorSpy.mock.calls.length, 1);
|
|
347
|
+
|
|
348
|
+
const errorLoggedOutput = errorSpy.mock.calls[0]?.arguments[0];
|
|
349
|
+
assert.ok(errorLoggedOutput.includes('Test message with error'));
|
|
350
|
+
|
|
351
|
+
// Should contain both date and error in metadata JSON
|
|
352
|
+
const errorMetadataMatch = errorLoggedOutput.match(/({.*})/s);
|
|
353
|
+
assert.ok(errorMetadataMatch);
|
|
354
|
+
const parsedErrorMetadata = JSON.parse(errorMetadataMatch[1]);
|
|
355
|
+
assert.ok(parsedErrorMetadata.date);
|
|
356
|
+
assert.ok(parsedErrorMetadata.error);
|
|
357
|
+
assert.deepEqual(parsedErrorMetadata.error, { code: 500, message: 'Internal Server Error' });
|
|
358
|
+
assert.strictEqual(Object.keys(parsedErrorMetadata).length, 2); // What matters: Date and error only
|
|
359
|
+
} finally {
|
|
360
|
+
process.env.NODE_ENV = originalEnv;
|
|
361
|
+
}
|
|
362
|
+
});
|
|
294
363
|
});
|