diff --git a/core/src/main/java/org/elasticsearch/common/settings/Setting.java b/core/src/main/java/org/elasticsearch/common/settings/Setting.java index d81204cfb21..241315144a9 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/Setting.java +++ b/core/src/main/java/org/elasticsearch/common/settings/Setting.java @@ -345,7 +345,7 @@ public class Setting extends ToXContentToBytes { /** Logs a deprecation warning if the setting is deprecated and used. */ protected void checkDeprecation(Settings settings) { // They're using the setting, so we need to tell them to stop - if (this.isDeprecated() && this.exists(settings)) { + if (this.isDeprecated() && this.exists(settings) && settings.addDeprecatedSetting(this)) { // It would be convenient to show its replacement key, but replacement is often not so simple final DeprecationLogger deprecationLogger = new DeprecationLogger(Loggers.getLogger(getClass())); deprecationLogger.deprecated("[{}] setting was deprecated in Elasticsearch and will be removed in a future release! " + diff --git a/core/src/main/java/org/elasticsearch/common/settings/Settings.java b/core/src/main/java/org/elasticsearch/common/settings/Settings.java index 182ea6ccb1d..8412f57fd89 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/Settings.java +++ b/core/src/main/java/org/elasticsearch/common/settings/Settings.java @@ -55,7 +55,6 @@ import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -63,6 +62,7 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Predicate; @@ -93,6 +93,22 @@ public final class Settings implements ToXContent { /** The first level of setting names. This is constructed lazily in {@link #names()}. */ private final SetOnce> firstLevelNames = new SetOnce<>(); + /** + * The set of deprecated settings tracked by this settings object. + */ + private final Set deprecatedSettings = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + /** + * Add the setting as a tracked deprecated setting. + * + * @param setting the deprecated setting to track + * @return true if the setting was not already tracked as a deprecated setting, otherwise false + */ + boolean addDeprecatedSetting(final Setting setting) { + assert setting.isDeprecated() && setting.exists(this) : setting.getKey(); + return deprecatedSettings.add(setting.getKey()); + } + /** * Setting names found in this Settings for both string and secure settings. * This is constructed lazily in {@link #keySet()}. diff --git a/core/src/test/java/org/elasticsearch/common/settings/SettingTests.java b/core/src/test/java/org/elasticsearch/common/settings/SettingTests.java index 0bb1abb37ad..1ac94b6caa3 100644 --- a/core/src/test/java/org/elasticsearch/common/settings/SettingTests.java +++ b/core/src/test/java/org/elasticsearch/common/settings/SettingTests.java @@ -154,6 +154,22 @@ public class SettingTests extends ESTestCase { assertNull(ab2.get()); } + public void testDeprecatedSetting() { + final Setting deprecatedSetting = Setting.boolSetting("deprecated.foo.bar", false, Property.Deprecated); + final Settings settings = Settings.builder().put("deprecated.foo.bar", true).build(); + final int iterations = randomIntBetween(0, 128); + for (int i = 0; i < iterations; i++) { + deprecatedSetting.get(settings); + } + if (iterations > 0) { + /* + * This tests that we log the deprecation warning exactly one time, otherwise we would have to assert the deprecation warning + * for each usage of the setting. + */ + assertSettingDeprecationsAndWarnings(new Setting[]{deprecatedSetting}); + } + } + public void testDefault() { TimeValue defaultValue = TimeValue.timeValueMillis(randomIntBetween(0, 1000000)); Setting setting = diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/DeprecationHttpIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/DeprecationHttpIT.java index 948f573a05c..bedb11ecc93 100644 --- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/DeprecationHttpIT.java +++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/DeprecationHttpIT.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase; import org.hamcrest.Matcher; import java.io.IOException; @@ -54,6 +55,7 @@ import static org.hamcrest.Matchers.hasSize; /** * Tests {@code DeprecationLogger} uses the {@code ThreadContext} to add response headers. */ +@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST) public class DeprecationHttpIT extends HttpSmokeTestCase { @Override @@ -125,14 +127,6 @@ public class DeprecationHttpIT extends HttpSmokeTestCase { doTestDeprecationWarningsAppearInHeaders(); } - public void testDeprecationHeadersDoNotGetStuck() throws Exception { - doTestDeprecationWarningsAppearInHeaders(); - doTestDeprecationWarningsAppearInHeaders(); - if (rarely()) { - doTestDeprecationWarningsAppearInHeaders(); - } - } - /** * Run a request that receives a predictably randomized number of deprecation warnings. *