diff --git a/spec/Deprecator.spec.js b/spec/Deprecator.spec.js
index 993d18682f..16373385ff 100644
--- a/spec/Deprecator.spec.js
+++ b/spec/Deprecator.spec.js
@@ -35,6 +35,26 @@ describe('Deprecator', () => {
expect(logSpy).not.toHaveBeenCalled();
});
+ it('does not log deprecation for new default if logLevels.deprecation is silent', async () => {
+ deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];
+
+ spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
+ const logger = require('../lib/logger').logger;
+ const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
+ await reconfigureServer({ logLevels: { deprecation: 'silent' } });
+ expect(logSpy).not.toHaveBeenCalled();
+ });
+
+ it('does not log deprecation for new default if logLevels.deprecation_exampleKey is silent', async () => {
+ deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];
+
+ spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
+ const logger = require('../lib/logger').logger;
+ const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
+ await reconfigureServer({ logLevels: { deprecation_exampleKey: 'silent' } });
+ expect(logSpy).not.toHaveBeenCalled();
+ });
+
it('logs runtime deprecation', async () => {
const logger = require('../lib/logger').logger;
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
diff --git a/src/Deprecator/Deprecator.js b/src/Deprecator/Deprecator.js
index 626f397a36..58c2e704b8 100644
--- a/src/Deprecator/Deprecator.js
+++ b/src/Deprecator/Deprecator.js
@@ -23,8 +23,11 @@ class Deprecator {
const changeNewKey = deprecation.changeNewKey;
// If default will change, only throw a warning if option is not set
- if (changeNewDefault != null && Utils.getNestedProperty(options, optionKey) == null) {
- Deprecator._logOption({ optionKey, changeNewDefault, solution });
+ if (
+ changeNewDefault != null &&
+ Utils.getNestedProperty(options, optionKey) == null
+ ) {
+ Deprecator._logOption({ optionKey, changeNewDefault, solution, options });
}
// If key will be removed or renamed, only throw a warning if option is set;
@@ -32,7 +35,7 @@ class Deprecator {
const resolvedValue = deprecation.resolvedValue;
const optionValue = Utils.getNestedProperty(options, optionKey);
if (changeNewKey != null && optionValue != null && optionValue !== resolvedValue) {
- Deprecator._logOption({ optionKey, changeNewKey, solution });
+ Deprecator._logOption({ optionKey, changeNewKey, solution, options });
}
}
}
@@ -103,8 +106,9 @@ class Deprecator {
* message must not include the warning that the parameter is deprecated, that is
* automatically added to the message. It should only contain the instruction on how
* to resolve this warning.
+ * @param {Object} [options] The Parse Server options, used to determine log levels.
*/
- static _logOption({ optionKey, envKey, changeNewKey, changeNewDefault, solution }) {
+ static _logOption({ optionKey, envKey, changeNewKey, changeNewDefault, solution, options }) {
const type = optionKey ? 'option' : 'environment key';
const key = optionKey ? optionKey : envKey;
const keyAction =
@@ -114,6 +118,19 @@ class Deprecator {
? `renamed to '${changeNewKey}'`
: `removed`;
+ // Determine the log level
+ const logLevels = (options && options.logLevels) || {};
+ let level = 'warn';
+ if (key && logLevels[`deprecation_${key}`]) {
+ level = logLevels[`deprecation_${key}`];
+ } else if (logLevels['deprecation']) {
+ level = logLevels['deprecation'];
+ }
+
+ if (level === 'silent') {
+ return;
+ }
+
// Compose message
let output = `DeprecationWarning: The Parse Server ${type} '${key}' `;
output += changeNewKey != null ? `is deprecated and will be ${keyAction} in a future version.` : '';
@@ -121,7 +138,12 @@ class Deprecator {
? `default will change to '${changeNewDefault}' in a future version.`
: '';
output += solution ? ` ${solution}` : '';
- logger.warn(output);
+
+ if (typeof logger[level] === 'function') {
+ logger[level](output);
+ } else {
+ logger.warn(output);
+ }
}
}
diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js
index 64c54561eb..986310e770 100644
--- a/src/Options/Definitions.js
+++ b/src/Options/Definitions.js
@@ -1599,4 +1599,9 @@ module.exports.LogLevels = {
help: 'Log level used by the Cloud Code Triggers `beforeSave`, `beforeDelete`, `beforeFind`, `beforeLogin` on success. Default is `info`. See [LogLevel](LogLevel.html) for available values.',
default: 'info',
},
+ deprecation: {
+ env: 'PARSE_SERVER_LOG_LEVELS_DEPRECATION',
+ help: 'Log level used for deprecation warnings. Default is `warn`. Set to `silent` to suppress all deprecations. You can also specify per-deprecation log levels by appending the option key, e.g., `deprecation_fileUpload`. See [LogLevel](LogLevel.html) for available values.',
+ default: 'warn',
+ },
};
diff --git a/src/Options/docs.js b/src/Options/docs.js
index 564a9b1718..bc6f9fc69e 100644
--- a/src/Options/docs.js
+++ b/src/Options/docs.js
@@ -13,6 +13,7 @@
/**
* @interface ParseServerOptions
* @property {AccountLockoutOptions} accountLockout The account lockout policy for failed login attempts.
Note: Setting a user's ACL to an empty object `{}` via master key is a separate mechanism that only prevents new logins; it does not invalidate existing session tokens. To immediately revoke a user's access, destroy their sessions via master key in addition to setting the ACL.
+ * @property {Boolean} acknowledgeFutureDefaults Set to `true` to acknowledge and suppress warnings about Parse Server options whose default values will change in a future version.
* @property {Boolean} allowAggregationForReadOnlyMasterKey Whether the `readOnlyMasterKey` is allowed to run aggregation pipelines via the aggregate endpoint. An aggregation pipeline can contain write-capable stages (for example MongoDB `$out` and `$merge`), so allowing aggregation effectively gives the read-only master key a way to perform writes, contrary to its read-only intent. If `true` (default), the read-only master key can run aggregation pipelines. If `false`, the read-only master key cannot run aggregation pipelines at all. Note that the `readOnlyMasterKey` is a secret key for internal server-side use only and must never be distributed; this option is an additional safeguard, not a substitute for keeping the key confidential. Defaults to `true`.
* @property {Boolean} allowClientClassCreation Enable (or disable) client class creation, defaults to false
* @property {Boolean} allowCustomObjectId Enable (or disable) custom objectId
diff --git a/src/Options/index.js b/src/Options/index.js
index 42f0ffb3b8..baad39efc4 100644
--- a/src/Options/index.js
+++ b/src/Options/index.js
@@ -954,4 +954,8 @@ export interface LogLevels {
:DEFAULT: info
*/
signupUsernameTaken: ?string;
+ /* Log level used for deprecation warnings. Default is `warn`. Set to `silent` to suppress all deprecations. You can also specify per-deprecation log levels by appending the option key, e.g., `deprecation_fileUpload`. See [LogLevel](LogLevel.html) for available values.
+ :DEFAULT: warn
+ */
+ deprecation: ?string;
}