Skip to content

Commit

Permalink
Improved support for Error
Browse files Browse the repository at this point in the history
  • Loading branch information
arv committed Mar 7, 2023
1 parent 1f07070 commit 68910a2
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"version": "4.0.0",
"repository": "github:rocicorp/logger",
"license": "Apache-2.0",
"engines": {
"node": "^14.13.1 || >=16.0.0"
},
"scripts": {
"test": "mocha --ui=tdd out/*.test.js",
"pretest": "npm run build",
Expand Down
62 changes: 53 additions & 9 deletions src/logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,20 +243,64 @@ test('Console logger calls JSON stringify on complex arguments', () => {
const mockDebug = mockConsoleMethod('debug');
consoleLogSink.log('debug', 'a', false, 123, {b: 1}, [2, 3]);
assert(mockDebug.calledOnce);
assert(mockDebug.calledWith('a', false, 123, '{"b":1}', '[2,3]'));
assert.deepEqual(mockDebug.firstCall.args, [
'a',
false,
123,
'{"b":1}',
'[2,3]',
]);
assert.equal(jsonStringifySpy.callCount, 2);
assert.deepEqual(jsonStringifySpy.getCall(0).args, [{b: 1}]);
assert.deepEqual(jsonStringifySpy.getCall(1).args, [[2, 3]]);
assert.deepEqual(jsonStringifySpy.getCall(0).firstArg, {b: 1});
assert.deepEqual(jsonStringifySpy.getCall(1).firstArg, [2, 3]);

mockDebug.resetHistory();

consoleLogSink.log('debug', new Error('a', {cause: new TypeError('b')}));
assert(mockDebug.calledOnce);

testNormalizeError(mockDebug.firstCall.firstArg);
});

test('newNodeLogContext calls JSON stringify on complex arguments', () => {
test('nodeConsoleSink calls JSON stringify on complex arguments', () => {
const jsonStringifySpy = sinon.spy(JSON, 'stringify');
const mockDebug = mockConsoleMethod('debug');
const lc = newNodeLogContext('debug');
lc.debug?.('a', false, 123, {b: 1}, [2, 3]);
nodeConsoleLogSink.log('debug', 'a', false, 123, {b: 1}, [2, 3]);
assert(mockDebug.calledOnce);
assert(mockDebug.calledWith('DBG', 'a', false, 123, '{"b":1}', '[2,3]'));
assert.deepEqual(mockDebug.firstCall.args, [
'DBG',
'a',
false,
123,
'{"b":1}',
'[2,3]',
]);
assert.equal(jsonStringifySpy.callCount, 2);
assert.deepEqual(jsonStringifySpy.getCall(0).args, [{b: 1}]);
assert.deepEqual(jsonStringifySpy.getCall(1).args, [[2, 3]]);
assert.deepEqual(jsonStringifySpy.getCall(0).firstArg, {b: 1});
assert.deepEqual(jsonStringifySpy.getCall(1).firstArg, [2, 3]);

mockDebug.resetHistory();

nodeConsoleLogSink.log('debug', new Error('a', {cause: new TypeError('b')}));
assert(mockDebug.calledOnce);

testNormalizeError(mockDebug.firstCall.args[1]);
});

function testNormalizeError(stringifiedError: string) {
const obj = JSON.parse(stringifiedError);
assert(typeof obj.stack === 'string');
const {cause} = obj;
delete obj.stack;
delete obj.cause;
assert.deepEqual(obj, {
message: 'a',
name: 'Error',
});
assert(typeof cause.stack === 'string');
delete cause.stack;
assert.deepEqual(cause, {
message: 'b',
name: 'TypeError',
});
}
16 changes: 14 additions & 2 deletions src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class FormatLogger implements LogSink {
*/
export const nodeConsoleLogSink: LogSink = {
log(level: LogLevel, ...args: unknown[]): void {
console[level](logLevelPrefix[level], ...args);
console[level](logLevelPrefix[level], ...args.map(normalizeArgument));
},
};

Expand Down Expand Up @@ -180,5 +180,17 @@ function normalizeArgument(
}
break;
}
return JSON.stringify(v);
return JSON.stringify(v, errorReplacer);
}

function errorReplacer(_key: string | symbol, v: unknown) {
if (v instanceof Error) {
return {
name: v.name,
message: v.message,
stack: v.stack,
...('cause' in v ? {cause: v.cause} : null),
};
}
return v;
}

0 comments on commit 68910a2

Please sign in to comment.