Skip to content

Commit 1f0e85b

Browse files
authored
Exposing the ability to log deprecated settings at non-critical level(#79107) (#79492)
A recent change for the deprecation logs provided the capability to emit deprecation's at critical vs. warning levels, #77482. However deprecated settings always log at critical level without the ability to express that the setting deprecation is only a warning. This commit exposes the ability to set the deprecation level when deprecating a setting. Relates #78781
1 parent f58a31b commit 1f0e85b

File tree

30 files changed

+323
-127
lines changed

30 files changed

+323
-127
lines changed

client/rest/src/main/java/org/elasticsearch/client/Response.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,14 @@ public HttpEntity getEntity() {
136136

137137
/**
138138
* Tests if a string matches the RFC 7234 specification for warning headers.
139-
* This assumes that the warn code is always 299 and the warn agent is always
140-
* Elasticsearch.
139+
* This assumes that the warn code is always 299 or 300 and the warn agent is
140+
* always Elasticsearch.
141141
*
142142
* @param s the value of a warning header formatted according to RFC 7234
143143
* @return {@code true} if the input string matches the specification
144144
*/
145145
private static boolean matchWarningHeaderPatternByPrefix(final String s) {
146-
return s.startsWith("299 Elasticsearch-");
146+
return s.startsWith("299 Elasticsearch-") || s.startsWith("300 Elasticsearch-");
147147
}
148148

149149
/**

libs/x-content/src/test/java/org/elasticsearch/xcontent/ObjectParserTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
package org.elasticsearch.xcontent;
99

10+
import org.elasticsearch.common.logging.DeprecationLogger;
1011
import org.elasticsearch.common.xcontent.XContentParserUtils;
1112
import org.elasticsearch.common.Strings;
1213
import org.elasticsearch.core.CheckedFunction;
@@ -213,7 +214,8 @@ class TestStruct {
213214
objectParser.declareField((i, v, c) -> v.test = i.text(), new ParseField("test", "old_test"), ObjectParser.ValueType.STRING);
214215
objectParser.parse(parser, s, null);
215216
assertEquals("foo", s.test);
216-
assertWarnings(false, "[foo][1:15] Deprecated field [old_test] used, expected [test] instead");
217+
assertWarnings(false, new DeprecationWarning(DeprecationLogger.CRITICAL, "[foo][1:15] Deprecated field [old_test] used, " +
218+
"expected [test] instead"));
217219
}
218220

219221
public void testFailOnValueType() throws IOException {

modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/GeoIpProcessor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.cluster.ClusterState;
2424
import org.elasticsearch.cluster.service.ClusterService;
2525
import org.elasticsearch.common.CheckedSupplier;
26+
import org.elasticsearch.common.logging.DeprecationLogger;
2627
import org.elasticsearch.common.logging.HeaderWarning;
2728
import org.elasticsearch.common.network.InetAddresses;
2829
import org.elasticsearch.common.network.NetworkAddress;
@@ -447,8 +448,8 @@ public GeoIpProcessor create(
447448

448449
boolean valid = metadata.isValid(currentState.metadata().settings());
449450
if (valid && metadata.isCloseToExpiration()) {
450-
HeaderWarning.addWarning("database [{}] was not updated for over 25 days, geoip processor will stop working if there " +
451-
"is no update for 30 days", databaseFile);
451+
HeaderWarning.addWarning(DeprecationLogger.CRITICAL, "database [{}] was not updated for over 25 days, geoip processor" +
452+
" will stop working if there is no update for 30 days", databaseFile);
452453
}
453454

454455
return valid;

plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/AwsEc2ServiceImplTests.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
import com.amazonaws.auth.AWSCredentialsProvider;
1515
import com.amazonaws.auth.BasicSessionCredentials;
1616
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
17+
18+
import org.elasticsearch.common.logging.DeprecationLogger;
1719
import org.elasticsearch.common.settings.MockSecureSettings;
20+
import org.elasticsearch.common.settings.Setting;
1821
import org.elasticsearch.common.settings.Settings;
1922
import org.elasticsearch.common.settings.SettingsException;
2023
import org.elasticsearch.test.ESTestCase;
@@ -59,8 +62,9 @@ public void testDeprecationOfLoneAccessKey() {
5962
Ec2ClientSettings.getClientSettings(Settings.builder().setSecureSettings(secureSettings).build())).getCredentials();
6063
assertThat(credentials.getAWSAccessKeyId(), is("aws_key"));
6164
assertThat(credentials.getAWSSecretKey(), is(""));
62-
assertSettingDeprecationsAndWarnings(new String[]{},
63-
"Setting [discovery.ec2.access_key] is set but [discovery.ec2.secret_key] is not, which will be unsupported in future");
65+
assertSettingDeprecationsAndWarnings(new Setting<?>[]{},
66+
new DeprecationWarning(DeprecationLogger.CRITICAL, "Setting [discovery.ec2.access_key] is set but " +
67+
"[discovery.ec2.secret_key] is not, which will be unsupported in future"));
6468
}
6569

6670
public void testDeprecationOfLoneSecretKey() {
@@ -70,8 +74,9 @@ public void testDeprecationOfLoneSecretKey() {
7074
Ec2ClientSettings.getClientSettings(Settings.builder().setSecureSettings(secureSettings).build())).getCredentials();
7175
assertThat(credentials.getAWSAccessKeyId(), is(""));
7276
assertThat(credentials.getAWSSecretKey(), is("aws_secret"));
73-
assertSettingDeprecationsAndWarnings(new String[]{},
74-
"Setting [discovery.ec2.secret_key] is set but [discovery.ec2.access_key] is not, which will be unsupported in future");
77+
assertSettingDeprecationsAndWarnings(new Setting<?>[]{},
78+
new DeprecationWarning(DeprecationLogger.CRITICAL, "Setting [discovery.ec2.secret_key] is set but " +
79+
"[discovery.ec2.access_key] is not, which will be unsupported in future"));
7580
}
7681

7782
public void testRejectionOfLoneSessionToken() {

qa/logging-config/src/test/java/org/elasticsearch/common/logging/JsonLoggerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void testDeprecationWarnMessage() throws IOException {
9595
);
9696
}
9797

98-
assertWarnings("deprecated warn message1");
98+
assertWarnings(true, new DeprecationWarning(Level.WARN, "deprecated warn message1")) ;
9999
}
100100

101101
public void testDeprecatedMessageWithoutXOpaqueId() throws IOException {

server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.elasticsearch.common.collect.ImmutableOpenMap;
3636
import org.elasticsearch.common.io.stream.StreamInput;
3737
import org.elasticsearch.common.io.stream.StreamOutput;
38+
import org.elasticsearch.common.logging.DeprecationLogger;
3839
import org.elasticsearch.common.logging.HeaderWarning;
3940
import org.elasticsearch.common.regex.Regex;
4041
import org.elasticsearch.common.settings.Setting;
@@ -1785,7 +1786,7 @@ static void validateDataStreams(SortedMap<String, IndexAbstraction> indicesLooku
17851786
// log as debug, this method is executed each time a new cluster state is created and
17861787
// could result in many logs:
17871788
logger.debug(warning);
1788-
HeaderWarning.addWarning(warning);
1789+
HeaderWarning.addWarning(DeprecationLogger.CRITICAL, warning);
17891790
}
17901791
}
17911792
}

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.cluster.ClusterState;
2525
import org.elasticsearch.cluster.ClusterStateUpdateTask;
2626
import org.elasticsearch.cluster.service.ClusterService;
27+
import org.elasticsearch.common.logging.DeprecationLogger;
2728
import org.elasticsearch.core.Nullable;
2829
import org.elasticsearch.common.Priority;
2930
import org.elasticsearch.common.Strings;
@@ -490,7 +491,7 @@ public ClusterState addIndexTemplateV2(final ClusterState currentState, final bo
490491
.collect(Collectors.joining(",")),
491492
name);
492493
logger.warn(warning);
493-
HeaderWarning.addWarning(warning);
494+
HeaderWarning.addWarning(DeprecationLogger.CRITICAL, warning);
494495
}
495496

496497
ComposableIndexTemplate finalIndexTemplate = template;
@@ -816,7 +817,7 @@ static ClusterState innerPutTemplate(final ClusterState currentState, PutRequest
816817
.collect(Collectors.joining(",")),
817818
request.name);
818819
logger.warn(warning);
819-
HeaderWarning.addWarning(warning);
820+
HeaderWarning.addWarning(DeprecationLogger.CRITICAL, warning);
820821
}
821822

822823
templateBuilder.order(request.order);

server/src/main/java/org/elasticsearch/common/logging/HeaderWarning.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.elasticsearch.common.logging;
1010

11+
import org.apache.logging.log4j.Level;
1112
import org.elasticsearch.Build;
1213
import org.elasticsearch.Version;
1314
import org.elasticsearch.common.util.concurrent.ThreadContext;
@@ -32,10 +33,11 @@
3233
public class HeaderWarning {
3334
/**
3435
* Regular expression to test if a string matches the RFC7234 specification for warning headers. This pattern assumes that the warn code
35-
* is always 299. Further, this pattern assumes that the warn agent represents a version of Elasticsearch including the build hash.
36+
* is always 299 or 300. Further, this pattern assumes that the warn agent represents a version of Elasticsearch including the build
37+
* hash.
3638
*/
3739
public static final Pattern WARNING_HEADER_PATTERN = Pattern.compile(
38-
"299 " + // warn code
40+
"(?:299|300) " + // log level code
3941
"Elasticsearch-" + // warn agent
4042
"\\d+\\.\\d+\\.\\d+(?:-(?:alpha|beta|rc)\\d+)?(?:-SNAPSHOT)?-" + // warn agent
4143
"(?:[a-f0-9]{7}(?:[a-f0-9]{33})?|unknown) " + // warn agent
@@ -53,15 +55,16 @@ public class HeaderWarning {
5355

5456
/*
5557
* RFC7234 specifies the warning format as warn-code <space> warn-agent <space> "warn-text" [<space> "warn-date"]. Here, warn-code is a
56-
* three-digit number with various standard warn codes specified. The warn code 299 is apt for our purposes as it represents a
57-
* miscellaneous persistent warning (can be presented to a human, or logged, and must not be removed by a cache). The warn-agent is an
58-
* arbitrary token; here we use the Elasticsearch version and build hash. The warn text must be quoted. The warn-date is an optional
59-
* quoted field that can be in a variety of specified date formats; here we use RFC 1123 format.
58+
* three-digit number with various standard warn codes specified, and is left off of this static prefix so that it can be added based
59+
* on the log level received. The warn code will be either 299 or 300 at runtime, which are apt for our purposes as
60+
* they represent miscellaneous persistent warnings (can be presented to a human, or logged, and must not be removed by a cache).
61+
* The warn-agent is an arbitrary token; here we use the Elasticsearch version and build hash. The warn text must be quoted. The
62+
* warn-date is an optional quoted field that can be in a variety of specified date formats; here we use RFC 1123 format.
6063
*/
6164
private static final String WARNING_PREFIX =
6265
String.format(
6366
Locale.ROOT,
64-
"299 Elasticsearch-%s%s-%s",
67+
" Elasticsearch-%s%s-%s",
6568
Version.CURRENT.toString(),
6669
Build.CURRENT.isSnapshot() ? "-SNAPSHOT" : "",
6770
Build.CURRENT.hash());
@@ -189,14 +192,15 @@ private static boolean assertWarningValue(final String s, final String warningVa
189192
* Format a warning string in the proper warning format by prepending a warn code, warn agent, wrapping the warning string in quotes,
190193
* and appending the RFC 7231 date.
191194
*
195+
* @param level the level of the warning - Level.WARN or DeprecationLogger.CRITICAL
192196
* @param s the warning string to format
193197
* @return a warning value formatted according to RFC 7234
194198
*/
195-
public static String formatWarning(final String s) {
199+
public static String formatWarning(final Level level, final String s) {
196200
// Assume that the common scenario won't have a string to escape and encode.
197-
int length = WARNING_PREFIX.length() + s.length() + 3;
201+
int length = WARNING_PREFIX.length() + s.length() + 6;
198202
final StringBuilder sb = new StringBuilder(length);
199-
sb.append(WARNING_PREFIX).append(" \"").append(escapeAndEncode(s)).append("\"");
203+
sb.append(level.intLevel() + WARNING_PREFIX).append(" \"").append(escapeAndEncode(s)).append("\"");
200204
return sb.toString();
201205
}
202206

@@ -310,16 +314,21 @@ public static String getXOpaqueId() {
310314
.orElse("");
311315
}
312316

313-
public static void addWarning(String message, Object... params) {
314-
addWarning(THREAD_CONTEXT, message, params);
317+
public static void addWarning(Level level, String message, Object... params) {
318+
addWarning(THREAD_CONTEXT, level, message, params);
315319
}
316320

317321
// package scope for testing
318322
static void addWarning(Set<ThreadContext> threadContexts, String message, Object... params) {
323+
addWarning(threadContexts, DeprecationLogger.CRITICAL, message, params);
324+
}
325+
326+
// package scope for testing
327+
static void addWarning(Set<ThreadContext> threadContexts, Level level, String message, Object... params) {
319328
final Iterator<ThreadContext> iterator = threadContexts.iterator();
320329
if (iterator.hasNext()) {
321330
final String formattedMessage = LoggerMessageFormat.format(message, params);
322-
final String warningHeaderValue = formatWarning(formattedMessage);
331+
final String warningHeaderValue = formatWarning(level, formattedMessage);
323332
assert WARNING_HEADER_PATTERN.matcher(warningHeaderValue).matches();
324333
assert extractWarningValueFromWarningHeader(warningHeaderValue, false)
325334
.equals(escapeAndEncode(formattedMessage));

server/src/main/java/org/elasticsearch/common/logging/HeaderWarningAppender.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ public void append(LogEvent event) {
3535
String messagePattern = esLogMessage.getMessagePattern();
3636
Object[] arguments = esLogMessage.getArguments();
3737

38-
HeaderWarning.addWarning(messagePattern, arguments);
38+
HeaderWarning.addWarning(event.getLevel(), messagePattern, arguments);
3939
} else {
4040
final String formattedMessage = event.getMessage().getFormattedMessage();
41-
HeaderWarning.addWarning(formattedMessage);
41+
HeaderWarning.addWarning(event.getLevel(), formattedMessage);
4242
}
4343
}
4444

server/src/main/java/org/elasticsearch/common/settings/Setting.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,15 @@ public enum Property {
100100
Final,
101101

102102
/**
103-
* mark this setting as deprecated
103+
* mark this setting as deprecated (critical level)
104104
*/
105105
Deprecated,
106106

107+
/**
108+
* mark this setting as deprecated (warning level)
109+
*/
110+
DeprecatedWarning,
111+
107112
/**
108113
* Node scope
109114
*/
@@ -170,6 +175,9 @@ private Setting(Key key, @Nullable Setting<T> fallbackSetting, Function<Settings
170175
if (propertiesAsSet.contains(Property.Dynamic) && propertiesAsSet.contains(Property.OperatorDynamic)) {
171176
throw new IllegalArgumentException("setting [" + key + "] cannot be both dynamic and operator dynamic");
172177
}
178+
if (propertiesAsSet.contains(Property.Deprecated) && propertiesAsSet.contains(Property.DeprecatedWarning)) {
179+
throw new IllegalArgumentException("setting [" + key + "] cannot be deprecated at both critical and warning levels");
180+
}
173181
checkPropertyRequiresIndexScope(propertiesAsSet, Property.NotCopyableOnResize);
174182
checkPropertyRequiresIndexScope(propertiesAsSet, Property.InternalIndex);
175183
checkPropertyRequiresIndexScope(propertiesAsSet, Property.PrivateIndex);
@@ -382,7 +390,11 @@ public boolean hasIndexScope() {
382390
* Returns <code>true</code> if this setting is deprecated, otherwise <code>false</code>
383391
*/
384392
public boolean isDeprecated() {
385-
return properties.contains(Property.Deprecated);
393+
return properties.contains(Property.Deprecated) || properties.contains(Property.DeprecatedWarning);
394+
}
395+
396+
private boolean isDeprecatedWarningOnly() {
397+
return properties.contains(Property.DeprecatedWarning);
386398
}
387399

388400
/**
@@ -561,13 +573,16 @@ void checkDeprecation(Settings settings) {
561573
if (this.isDeprecated() && this.exists(settings)) {
562574
// It would be convenient to show its replacement key, but replacement is often not so simple
563575
final String key = getKey();
564-
565576
DeprecationCategory category = this.isSecure(settings) ? DeprecationCategory.SECURITY : DeprecationCategory.SETTINGS;
566577
List<String> skipTheseDeprecations = settings.getAsList("deprecation.skip_deprecated_settings");
567578
if (Regex.simpleMatch(skipTheseDeprecations, key) == false) {
568-
Settings.DeprecationLoggerHolder.deprecationLogger
569-
.critical(category, key, "[{}] setting was deprecated in Elasticsearch and will be removed in a future release! "
570-
+ "See the breaking changes documentation for the next major version.", key);
579+
String message = "[{}] setting was deprecated in Elasticsearch and will be removed in a future release! "
580+
+ "See the breaking changes documentation for the next major version.";
581+
if (this.isDeprecatedWarningOnly()) {
582+
Settings.DeprecationLoggerHolder.deprecationLogger.warn(category, key, message, key);
583+
} else {
584+
Settings.DeprecationLoggerHolder.deprecationLogger.critical(category, key, message, key);
585+
}
571586
}
572587
}
573588
}

0 commit comments

Comments
 (0)