Skip to content

Commit 5f81efb

Browse files
authored
feat: Add silent log level for Cloud Code (#8803)
1 parent 7d84b24 commit 5f81efb

File tree

5 files changed

+104
-27
lines changed

5 files changed

+104
-27
lines changed

Diff for: spec/CloudCodeLogger.spec.js

+56
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ describe('Cloud Code Logger', () => {
1515
// useful to flip to false for fine tuning :).
1616
silent: true,
1717
logLevel: undefined,
18+
logLevels: {
19+
cloudFunctionError: 'error',
20+
cloudFunctionSuccess: 'info',
21+
triggerAfter: 'info',
22+
triggerBeforeError: 'error',
23+
triggerBeforeSuccess: 'info',
24+
},
1825
})
1926
.then(() => {
2027
return Parse.User.#('tester', 'abc')
@@ -334,4 +341,53 @@ describe('Cloud Code Logger', () => {
334341
expect(args[0]).toBe('Parse error: ');
335342
expect(args[1].message).toBe('Object not found.');
336343
});
344+
345+
it('should log cloud function execution using the silent log level', async () => {
346+
await reconfigureServer({
347+
logLevels: {
348+
cloudFunctionSuccess: 'silent',
349+
cloudFunctionError: 'silent',
350+
},
351+
});
352+
Parse.Cloud.define('aFunction', () => {
353+
return 'it worked!';
354+
});
355+
Parse.Cloud.define('bFunction', () => {
356+
throw new Error('Failed');
357+
});
358+
spy = spyOn(Config.get('test').loggerController.adapter, 'log').and.callThrough();
359+
360+
await Parse.Cloud.run('aFunction', { foo: 'bar' });
361+
expect(spy).toHaveBeenCalledTimes(0);
362+
363+
await expectAsync(Parse.Cloud.run('bFunction', { foo: 'bar' })).toBeRejected();
364+
// Not "Failed running cloud function message..."
365+
expect(spy).toHaveBeenCalledTimes(1);
366+
});
367+
368+
it('should log cloud function triggers using the silent log level', async () => {
369+
await reconfigureServer({
370+
logLevels: {
371+
triggerAfter: 'silent',
372+
triggerBeforeSuccess: 'silent',
373+
triggerBeforeError: 'silent',
374+
},
375+
});
376+
Parse.Cloud.beforeSave('TestClassError', () => {
377+
throw new Error('Failed');
378+
});
379+
Parse.Cloud.beforeSave('TestClass', () => {});
380+
Parse.Cloud.afterSave('TestClass', () => {});
381+
382+
spy = spyOn(Config.get('test').loggerController.adapter, 'log').and.callThrough();
383+
384+
const obj = new Parse.Object('TestClass');
385+
await obj.save();
386+
expect(spy).toHaveBeenCalledTimes(0);
387+
388+
const objError = new Parse.Object('TestClassError');
389+
await expectAsync(objError.save()).toBeRejected();
390+
// Not "beforeSave failed for TestClassError for user ..."
391+
expect(spy).toHaveBeenCalledTimes(1);
392+
});
337393
});

Diff for: spec/helper.js

+13-6
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ const defaultConfiguration = {
132132
allowClientClassCreation: true,
133133
};
134134

135+
if (silent) {
136+
defaultConfiguration.logLevels = {
137+
cloudFunctionSuccess: 'silent',
138+
cloudFunctionError: 'silent',
139+
triggerAfter: 'silent',
140+
triggerBeforeError: 'silent',
141+
triggerBeforeSuccess: 'silent',
142+
};
143+
}
144+
135145
if (process.env.PARSE_SERVER_TEST_CACHE === 'redis') {
136146
defaultConfiguration.cacheAdapter = new RedisCacheAdapter();
137147
}
@@ -434,8 +444,8 @@ try {
434444
// Fetch test exclusion list
435445
testExclusionList = require('./testExclusionList.json');
436446
console.log(`Using test exclusion list with ${testExclusionList.length} entries`);
437-
} catch(error) {
438-
if(error.code !== 'MODULE_NOT_FOUND') {
447+
} catch (error) {
448+
if (error.code !== 'MODULE_NOT_FOUND') {
439449
throw error;
440450
}
441451
}
@@ -445,10 +455,7 @@ global.it_id = (id, func) => {
445455
if (testExclusionList.includes(id)) {
446456
return xit;
447457
} else {
448-
if(func === undefined)
449-
return it;
450-
else
451-
return func;
458+
return func || it;
452459
}
453460
};
454461

Diff for: src/Controllers/LoggerController.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const LogOrder = {
1616
ASCENDING: 'asc',
1717
};
1818

19-
export const logLevels = ['error', 'warn', 'info', 'debug', 'verbose', 'silly'];
19+
export const logLevels = ['error', 'warn', 'info', 'debug', 'verbose', 'silly', 'silent'];
2020

2121
export class LoggerController extends AdaptableController {
2222
constructor(adapter, appId, options = { logLevel: 'info' }) {

Diff for: src/Routers/FunctionsRouter.js

+25-20
Original file line numberDiff line numberDiff line change
@@ -141,36 +141,41 @@ export class FunctionsRouter extends PromiseRouter {
141141

142142
return new Promise(function (resolve, reject) {
143143
const userString = req.auth && req.auth.user ? req.auth.user.id : undefined;
144-
const cleanInput = logger.truncateLogMessage(JSON.stringify(params));
145144
const { success, error } = FunctionsRouter.createResponseObject(
146145
result => {
147146
try {
148-
const cleanResult = logger.truncateLogMessage(JSON.stringify(result.response.result));
149-
logger[req.config.logLevels.cloudFunctionSuccess](
150-
`Ran cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Result: ${cleanResult}`,
151-
{
152-
functionName,
153-
params,
154-
user: userString,
155-
}
156-
);
147+
if (req.config.logLevels.cloudFunctionSuccess !== 'silent') {
148+
const cleanInput = logger.truncateLogMessage(JSON.stringify(params));
149+
const cleanResult = logger.truncateLogMessage(JSON.stringify(result.response.result));
150+
logger[req.config.logLevels.cloudFunctionSuccess](
151+
`Ran cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Result: ${cleanResult}`,
152+
{
153+
functionName,
154+
params,
155+
user: userString,
156+
}
157+
);
158+
}
157159
resolve(result);
158160
} catch (e) {
159161
reject(e);
160162
}
161163
},
162164
error => {
163165
try {
164-
logger[req.config.logLevels.cloudFunctionError](
165-
`Failed running cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Error: ` +
166-
JSON.stringify(error),
167-
{
168-
functionName,
169-
error,
170-
params,
171-
user: userString,
172-
}
173-
);
166+
if (req.config.logLevels.cloudFunctionError !== 'silent') {
167+
const cleanInput = logger.truncateLogMessage(JSON.stringify(params));
168+
logger[req.config.logLevels.cloudFunctionError](
169+
`Failed running cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Error: ` +
170+
JSON.stringify(error),
171+
{
172+
functionName,
173+
error,
174+
params,
175+
user: userString,
176+
}
177+
);
178+
}
174179
reject(error);
175180
} catch (e) {
176181
reject(e);

Diff for: src/triggers.js

+9
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,9 @@ function userIdForLog(auth) {
382382
}
383383

384384
function logTriggerAfterHook(triggerType, className, input, auth, logLevel) {
385+
if (logLevel === 'silent') {
386+
return;
387+
}
385388
const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
386389
logger[logLevel](
387390
`${triggerType} triggered for ${className} for user ${userIdForLog(
@@ -396,6 +399,9 @@ function logTriggerAfterHook(triggerType, className, input, auth, logLevel) {
396399
}
397400

398401
function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth, logLevel) {
402+
if (logLevel === 'silent') {
403+
return;
404+
}
399405
const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
400406
const cleanResult = logger.truncateLogMessage(JSON.stringify(result));
401407
logger[logLevel](
@@ -411,6 +417,9 @@ function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth
411417
}
412418

413419
function logTriggerErrorBeforeHook(triggerType, className, input, auth, error, logLevel) {
420+
if (logLevel === 'silent') {
421+
return;
422+
}
414423
const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
415424
logger[logLevel](
416425
`${triggerType} failed for ${className} for user ${userIdForLog(

0 commit comments

Comments
 (0)