diff --git a/test/api/unit/libs/logger.js b/test/api/unit/libs/logger.js index 030997ca07..7683c8b076 100644 --- a/test/api/unit/libs/logger.js +++ b/test/api/unit/libs/logger.js @@ -1,14 +1,27 @@ -import winston from 'winston'; -import logger from '../../../../website/server/libs/logger'; +import logger, { _loggerConfig } from '../../../../website/server/libs/logger'; import { NotFound, } from '../../../../website/server/libs/errors'; -describe.only('logger', () => { - let logSpy; +describe('logger', () => { + let infoSpy; + let warnSpy; + let errorSpy; + + const originalLoggingEnabled = _loggerConfig.loggingEnabled; + + before(() => { // enable logging in tests + _loggerConfig.loggingEnabled = true; + }); + + after(() => { // reset value of _loggerConfig.loggingEnabled + _loggerConfig.loggingEnabled = originalLoggingEnabled; + }); beforeEach(() => { - logSpy = sandbox.stub(Object.getPrototypeOf(winston.createLogger()), 'log'); + infoSpy = sandbox.stub(_loggerConfig.logger, 'info'); + warnSpy = sandbox.stub(_loggerConfig.logger, 'warn'); + errorSpy = sandbox.stub(_loggerConfig.logger, 'error'); }); afterEach(() => { @@ -18,8 +31,8 @@ describe.only('logger', () => { describe('info', () => { it('calls winston\'s info log', () => { logger.info(1, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith('info', 1, 2, 3); + expect(infoSpy).to.be.calledOnce; + expect(infoSpy).to.be.calledWith(1, 2, 3); }); }); @@ -27,8 +40,8 @@ describe.only('logger', () => { context('non-error object', () => { it('passes through arguments if the first arg is not an error object', () => { logger.error(1, 2, 3, 4); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith('error', 1, 2, 3, 4); + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith(1, 2, 3, 4); }); }); @@ -39,9 +52,8 @@ describe.only('logger', () => { data: 1, }, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, { data: 1, fullError: errInstance }, 2, @@ -58,9 +70,8 @@ describe.only('logger', () => { fullError: anotherError, }, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, { data: 1, fullError: anotherError }, 2, @@ -73,9 +84,8 @@ describe.only('logger', () => { logger.error(errInstance, null, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, null, 2, @@ -88,9 +98,8 @@ describe.only('logger', () => { logger.error(errInstance, true, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, true, 2, @@ -103,9 +112,8 @@ describe.only('logger', () => { logger.error(errInstance, { httpCode: 400 }, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, { httpCode: 400, fullError: errInstance }, 2, @@ -121,9 +129,8 @@ describe.only('logger', () => { httpCode: 502, }, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, { httpCode: 502, isHandledError: true, fullError: errInstance }, 2, @@ -139,9 +146,8 @@ describe.only('logger', () => { httpCode: 403, }, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'warn', + expect(warnSpy).to.be.calledOnce; + expect(warnSpy).to.be.calledWith( errInstance.stack, { httpCode: 403, isHandledError: true, fullError: errInstance }, 2, @@ -156,9 +162,8 @@ describe.only('logger', () => { logger.error(errInstance, {}, 2, 3); - expect(logSpy).to.be.calledOnce; - expect(logSpy).to.be.calledWith( - 'error', + expect(errorSpy).to.be.calledOnce; + expect(errorSpy).to.be.calledWith( errInstance.stack, { fullError: { diff --git a/website/server/libs/logger.js b/website/server/libs/logger.js index ef443b11ed..79ef86eb53 100644 --- a/website/server/libs/logger.js +++ b/website/server/libs/logger.js @@ -14,6 +14,13 @@ const ENABLE_LOGS_IN_PROD = nconf.get('ENABLE_CONSOLE_LOGS_IN_PROD') === 'true'; const logger = winston.createLogger(); +const _config = { + logger, + loggingEnabled: true, // false if no transport has been configured +}; + +export { _config as _loggerConfig }; // exported for use during tests + if (IS_PROD) { if (ENABLE_LOGS_IN_PROD) { logger.add(new winston.transports.Console({ @@ -46,6 +53,12 @@ if (IS_PROD) { .add(new winston.transports.Console({ level: 'warn', // warn and errors (json part) format: winston.format.combine( + // Remove stacktrace from json, printed separately + winston.format(info => { + const message = info.message.split('\n')[0]; + info.message = message; + return info; + })(), winston.format.prettyPrint({ colorize: true, }), @@ -68,11 +81,15 @@ if (IS_PROD) { winston.format.printf(info => `${info.timestamp} - ${info.level} ${info.message}`), ), })); +} else { + _config.loggingEnabled = false; } // exports a public interface insteaf of accessing directly the logger module const loggerInterface = { info (...args) { + if (!_config.loggingEnabled) return; + logger.info(...args); }, @@ -81,6 +98,7 @@ const loggerInterface = { // and an object of additional data to log alongside the error // If the first argument isn't an Error, it'll call logger.error with all the arguments supplied error (...args) { + if (!_config.loggingEnabled) return; const [err, errorData = {}, ...otherArgs] = args; if (err instanceof Error) {