This repository has been archived by the owner on May 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
00c6da8
commit 66353c2
Showing
4 changed files
with
101 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const logLevels = ['error', 'warn', 'info', 'debug']; | ||
|
||
/** | ||
* Asserts that the caller-supplied logger contains all required methods | ||
* and wraps it in an exception handler that falls back to the fallbackLogger | ||
* @param {LDLogger} logger | ||
* @param {LDLogger} fallbackLogger | ||
*/ | ||
function LoggerWrapper(logger, fallbackLogger) { | ||
validateLogger(logger); | ||
|
||
const wrappedLogger = {}; | ||
logLevels.forEach(level => { | ||
wrappedLogger[level] = wrapLoggerLevel(logger, fallbackLogger, level); | ||
}); | ||
|
||
return wrappedLogger; | ||
} | ||
|
||
function validateLogger(logger) { | ||
logLevels.forEach(level => { | ||
if (!logger[level] || typeof logger[level] !== 'function') { | ||
throw new Error('Provided logger instance must support logger.' + level + '(...) method'); | ||
} | ||
}); | ||
} | ||
|
||
function wrapLoggerLevel(logger, fallbackLogger, level) { | ||
return function wrappedLoggerMethod() { | ||
try { | ||
return logger[level].apply(logger, arguments); | ||
} catch (err) { | ||
fallbackLogger.error('Error calling provided logger instance method ' + level + ': ' + err); | ||
fallbackLogger[level].apply(fallbackLogger, arguments); | ||
} | ||
}; | ||
} | ||
|
||
module.exports = LoggerWrapper; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const LoggerWrapper = require('../logger_wrapper'); | ||
|
||
describe('LoggerWrapper', function () { | ||
|
||
function mockLogger() { | ||
return { | ||
error: jest.fn(), | ||
warn: jest.fn(), | ||
info: jest.fn(), | ||
debug: jest.fn(), | ||
}; | ||
} | ||
|
||
const levels = ['error', 'warn', 'info', 'debug']; | ||
|
||
it('throws an error if you pass in a logger that does not conform to the LDLogger schema', () => { | ||
const fallbackLogger = mockLogger(); | ||
|
||
// If the method does not exist | ||
levels.forEach(method => { | ||
const logger = mockLogger(); | ||
delete logger[method]; | ||
expect(() => LoggerWrapper(logger, fallbackLogger)).toThrow(/Provided logger instance must support .* method/); | ||
}); | ||
|
||
// If the method is not a function | ||
levels.forEach(method => { | ||
const logger = mockLogger(); | ||
logger[method] = 'invalid'; | ||
expect(() => LoggerWrapper(logger, fallbackLogger)).toThrow(/Provided logger instance must support .* method/); | ||
}); | ||
}); | ||
|
||
it('If a logger method throws an error, the error is caught and logged, then the fallback logger is called', () => { | ||
const err = Error('Something bad happened'); | ||
|
||
levels.forEach(level => { | ||
const logger = mockLogger(); | ||
logger[level] = jest.fn(() => { | ||
throw err | ||
}); | ||
const fallbackLogger = mockLogger(); | ||
const wrappedLogger = LoggerWrapper(logger, fallbackLogger); | ||
|
||
expect(() => wrappedLogger[level]('this is a logline', 'with multiple', 'arguments')).not.toThrow(); | ||
|
||
expect(fallbackLogger.error).toHaveBeenNthCalledWith(1, 'Error calling provided logger instance method ' + level + ': ' + err); | ||
|
||
const nthCall = level === 'error' ? 2 : 1; | ||
expect(fallbackLogger[level]).toHaveBeenNthCalledWith(nthCall, 'this is a logline', 'with multiple', 'arguments'); | ||
}); | ||
}); | ||
}); |