Removes second log when responding with a regular error

This commit is contained in:
Florent Vilmart
2018-08-10 17:59:56 -04:00
parent b9673da07b
commit 8ba8a3393d
4 changed files with 47 additions and 31 deletions

View File

@@ -1,6 +1,7 @@
const LoggerController = require('../lib/Controllers/LoggerController').LoggerController; const LoggerController = require('../lib/Controllers/LoggerController').LoggerController;
const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter;
const fs = require('fs'); const fs = require('fs');
const Config = require('../lib/Config');
const loremFile = __dirname + '/support/lorem.txt'; const loremFile = __dirname + '/support/lorem.txt';
@@ -23,8 +24,9 @@ describe("Cloud Code Logger", () => {
// Note that helpers takes care of logout. // Note that helpers takes care of logout.
// see helpers.js:afterEach // see helpers.js:afterEach
it("should expose log to functions", done => { it("should expose log to functions", () => {
const logController = new LoggerController(new WinstonLoggerAdapter()); const config = Config.get('test');
const spy = spyOn(config.loggerController, 'log').and.callThrough();
Parse.Cloud.define("loggerTest", (req, res) => { Parse.Cloud.define("loggerTest", (req, res) => {
req.log.info('logTest', 'info log', { info: 'some log' }); req.log.info('logTest', 'info log', { info: 'some log' });
@@ -32,25 +34,23 @@ describe("Cloud Code Logger", () => {
res.success({}); res.success({});
}); });
Parse.Cloud.run('loggerTest').then(() => { return Parse.Cloud.run('loggerTest').then(() => {
return logController.getLogs({ from: Date.now() - 500, size: 1000 }); expect(spy).toHaveBeenCalledTimes(3);
}).then((res) => { const cloudFunctionMessage = spy.calls.all()[2];
expect(res.length).not.toBe(0); const errorMessage = spy.calls.all()[1];
const lastLogs = res.slice(0, 3); const infoMessage = spy.calls.all()[0];
const cloudFunctionMessage = lastLogs[0]; expect(cloudFunctionMessage.args[0]).toBe('info');
const errorMessage = lastLogs[1]; expect(cloudFunctionMessage.args[1][1].params).toEqual({});
const infoMessage = lastLogs[2]; expect(cloudFunctionMessage.args[1][0]).toMatch(/Ran cloud function loggerTest for user [^ ]* with:\n {2}Input: {}\n {2}Result: {}/);
expect(cloudFunctionMessage.level).toBe('info'); expect(cloudFunctionMessage.args[1][1].functionName).toEqual('loggerTest');
expect(cloudFunctionMessage.params).toEqual({}); expect(errorMessage.args[0]).toBe('error');
expect(cloudFunctionMessage.message).toMatch(/Ran cloud function loggerTest for user [^ ]* with:\n {2}Input: {}\n {2}Result: {}/); expect(errorMessage.args[1][2].error).toBe('there was an error');
expect(cloudFunctionMessage.functionName).toEqual('loggerTest'); expect(errorMessage.args[1][0]).toBe('logTest');
expect(errorMessage.level).toBe('error'); expect(errorMessage.args[1][1]).toBe('error log');
expect(errorMessage.error).toBe('there was an error'); expect(infoMessage.args[0]).toBe('info');
expect(errorMessage.message).toBe('logTest error log'); expect(infoMessage.args[1][2].info).toBe('some log');
expect(infoMessage.level).toBe('info'); expect(infoMessage.args[1][0]).toBe('logTest');
expect(infoMessage.info).toBe('some log'); expect(infoMessage.args[1][1]).toBe('info log');
expect(infoMessage.message).toBe('logTest info log');
done();
}); });
}); });
@@ -194,7 +194,8 @@ describe("Cloud Code Logger", () => {
Parse.Cloud.run('aFunction', { foo: 'bar' }) Parse.Cloud.run('aFunction', { foo: 'bar' })
.then(null, () => logController.getLogs({ from: Date.now() - 500, size: 1000 })) .then(null, () => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then(logs => { .then(logs => {
const log = logs[2]; expect(logs[0].message).toBe('it failed!');
const log = logs[1];
expect(log.level).toEqual('error'); expect(log.level).toEqual('error');
expect(log.message).toMatch( expect(log.message).toMatch(
/Failed running cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Error: {"code":141,"message":"it failed!"}/); /Failed running cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Error: {"code":141,"message":"it failed!"}/);
@@ -243,4 +244,18 @@ describe("Cloud Code Logger", () => {
}) })
.then(null, e => done.fail(e)); .then(null, e => done.fail(e));
}); });
it('should only log once for object not found', async () => {
const config = Config.get('test');
const spy = spyOn(config.loggerController, 'error').and.callThrough();
try {
const object = new Parse.Object('Object');
object.id = 'invalid'
await object.fetch();
} catch(e) { /**/ }
expect(spy).toHaveBeenCalled();
expect(spy.calls.count()).toBe(1);
const { args } = spy.calls.mostRecent();
expect(args[0]).toBe('Object not found.');
});
}); });

View File

@@ -87,8 +87,8 @@ describe('LogsRouter', () => {
}, (error, response, body) => { }, (error, response, body) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
// 4th entry is our actual GET request // 4th entry is our actual GET request
expect(body[3].url).toEqual('/1/login?username=test&password=********'); expect(body[2].url).toEqual('/1/login?username=test&password=********');
expect(body[3].message).toEqual('REQUEST for [GET] /1/login?username=test&password=********: {}'); expect(body[2].message).toEqual('REQUEST for [GET] /1/login?username=test&password=********: {}');
done(); done();
}); });
}); });
@@ -114,8 +114,8 @@ describe('LogsRouter', () => {
}, (error, response, body) => { }, (error, response, body) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
// 4th entry is our actual GET request // 4th entry is our actual GET request
expect(body[3].url).toEqual('/1/login?username=test&password=********'); expect(body[2].url).toEqual('/1/login?username=test&password=********');
expect(body[3].message).toEqual('REQUEST for [GET] /1/login?username=test&password=********: {}'); expect(body[2].message).toEqual('REQUEST for [GET] /1/login?username=test&password=********: {}');
done(); done();
}); });
}); });
@@ -144,8 +144,8 @@ describe('LogsRouter', () => {
}, (error, response, body) => { }, (error, response, body) => {
expect(response.statusCode).toEqual(200); expect(response.statusCode).toEqual(200);
// 4th entry is our actual GET request // 4th entry is our actual GET request
expect(body[3].url).toEqual('/1/login'); expect(body[2].url).toEqual('/1/login');
expect(body[3].message).toEqual('REQUEST for [POST] /1/login: {}'); expect(body[2].message).toEqual('REQUEST for [POST] /1/login: {}');
done(); done();
}); });
}); });

View File

@@ -181,7 +181,7 @@ function makeExpressHandler(appId, promiseHandler) {
}) })
} }
res.json(result.response); res.json(result.response);
}, (e) => { }, (error) => next(error)).catch((e) => {
log.error(`Error generating response. ${inspect(e)}`, {error: e}); log.error(`Error generating response. ${inspect(e)}`, {error: e});
next(e); next(e);
}); });

View File

@@ -1,9 +1,9 @@
import AppCache from './cache'; import AppCache from './cache';
import log from './logger';
import Parse from 'parse/node'; import Parse from 'parse/node';
import auth from './Auth'; import auth from './Auth';
import Config from './Config'; import Config from './Config';
import ClientSDK from './ClientSDK'; import ClientSDK from './ClientSDK';
import defaultLogger from './logger';
// Checks that the request is authorized for this app and checks user // Checks that the request is authorized for this app and checks user
// auth too. // auth too.
@@ -179,7 +179,7 @@ export function handleParseHeaders(req, res, next) {
} }
else { else {
// TODO: Determine the correct error scenario. // TODO: Determine the correct error scenario.
log.error('error getting auth for sessionToken', error); req.config.loggerController.error('error getting auth for sessionToken', error);
throw new Parse.Error(Parse.Error.UNKNOWN_ERROR, error); throw new Parse.Error(Parse.Error.UNKNOWN_ERROR, error);
} }
}); });
@@ -267,6 +267,7 @@ export function allowMethodOverride(req, res, next) {
} }
export function handleParseErrors(err, req, res, next) { export function handleParseErrors(err, req, res, next) {
const log = (req.config && req.config.loggerController) || defaultLogger;
if (err instanceof Parse.Error) { if (err instanceof Parse.Error) {
let httpStatus; let httpStatus;
// TODO: fill out this mapping // TODO: fill out this mapping