Skip to content

Commit da3dbed

Browse files
authored
SlowLoggers using single logger backport(#56708) (#57228)
Slow loggers should use single shared logger as otherwise when index is deleted the log4j logger will remain reachable (log4j is caching) and will create a memory leak. closes #56171
1 parent f371e66 commit da3dbed

File tree

8 files changed

+477
-61
lines changed

8 files changed

+477
-61
lines changed

server/src/main/java/org/elasticsearch/index/IndexingSlowLog.java

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,7 @@
3939
import java.util.concurrent.TimeUnit;
4040

4141
public final class IndexingSlowLog implements IndexingOperationListener {
42-
private final Index index;
43-
private boolean reformat;
44-
private long indexWarnThreshold;
45-
private long indexInfoThreshold;
46-
private long indexDebugThreshold;
47-
private long indexTraceThreshold;
48-
/**
49-
* How much of the source to log in the slowlog - 0 means log none and
50-
* anything greater than 0 means log at least that many <em>characters</em>
51-
* of the source.
52-
*/
53-
private int maxSourceCharsToLog;
54-
55-
private final Logger indexLogger;
56-
57-
private static final String INDEX_INDEXING_SLOWLOG_PREFIX = "index.indexing.slowlog";
42+
public static final String INDEX_INDEXING_SLOWLOG_PREFIX = "index.indexing.slowlog";
5843
public static final Setting<TimeValue> INDEX_INDEXING_SLOWLOG_THRESHOLD_INDEX_WARN_SETTING =
5944
Setting.timeSetting(INDEX_INDEXING_SLOWLOG_PREFIX +".threshold.index.warn", TimeValue.timeValueNanos(-1),
6045
TimeValue.timeValueMillis(-1), Property.Dynamic, Property.IndexScope);
@@ -72,6 +57,22 @@ public final class IndexingSlowLog implements IndexingOperationListener {
7257
public static final Setting<SlowLogLevel> INDEX_INDEXING_SLOWLOG_LEVEL_SETTING =
7358
new Setting<>(INDEX_INDEXING_SLOWLOG_PREFIX +".level", SlowLogLevel.TRACE.name(), SlowLogLevel::parse, Property.Dynamic,
7459
Property.IndexScope);
60+
61+
private final Logger indexLogger;
62+
private final Index index;
63+
64+
private boolean reformat;
65+
private long indexWarnThreshold;
66+
private long indexInfoThreshold;
67+
private long indexDebugThreshold;
68+
private long indexTraceThreshold;
69+
/*
70+
* How much of the source to log in the slowlog - 0 means log none and anything greater than 0 means log at least that many
71+
* <em>characters</em> of the source.
72+
*/
73+
private int maxSourceCharsToLog;
74+
private SlowLogLevel level;
75+
7576
/**
7677
* Reads how much of the source to log. The user can specify any value they
7778
* like and numbers are interpreted the maximum number of characters to log
@@ -88,7 +89,8 @@ public final class IndexingSlowLog implements IndexingOperationListener {
8889
}, Property.Dynamic, Property.IndexScope);
8990

9091
IndexingSlowLog(IndexSettings indexSettings) {
91-
this.indexLogger = LogManager.getLogger(INDEX_INDEXING_SLOWLOG_PREFIX + ".index." + indexSettings.getUUID());
92+
this.indexLogger = LogManager.getLogger(INDEX_INDEXING_SLOWLOG_PREFIX + ".index");
93+
Loggers.setLevel(this.indexLogger, SlowLogLevel.TRACE.name());
9294
this.index = indexSettings.getIndex();
9395

9496
indexSettings.getScopedSettings().addSettingsUpdateConsumer(INDEX_INDEXING_SLOWLOG_REFORMAT_SETTING, this::setReformat);
@@ -117,7 +119,7 @@ private void setMaxSourceCharsToLog(int maxSourceCharsToLog) {
117119
}
118120

119121
private void setLevel(SlowLogLevel level) {
120-
Loggers.setLevel(this.indexLogger, level.name());
122+
this.level = level;
121123
}
122124

123125
private void setWarnThreshold(TimeValue warnThreshold) {
@@ -145,13 +147,14 @@ public void postIndex(ShardId shardId, Engine.Index indexOperation, Engine.Index
145147
if (result.getResultType() == Engine.Result.Type.SUCCESS) {
146148
final ParsedDocument doc = indexOperation.parsedDoc();
147149
final long tookInNanos = result.getTook();
148-
if (indexWarnThreshold >= 0 && tookInNanos > indexWarnThreshold) {
150+
// when logger level is more specific than WARN AND event is within threshold it should be logged
151+
if (indexWarnThreshold >= 0 && tookInNanos > indexWarnThreshold && level.isLevelEnabledFor(SlowLogLevel.WARN)) {
149152
indexLogger.warn("{}", new SlowLogParsedDocumentPrinter(index, doc, tookInNanos, reformat, maxSourceCharsToLog));
150-
} else if (indexInfoThreshold >= 0 && tookInNanos > indexInfoThreshold) {
153+
} else if (indexInfoThreshold >= 0 && tookInNanos > indexInfoThreshold && level.isLevelEnabledFor(SlowLogLevel.INFO)) {
151154
indexLogger.info("{}", new SlowLogParsedDocumentPrinter(index, doc, tookInNanos, reformat, maxSourceCharsToLog));
152-
} else if (indexDebugThreshold >= 0 && tookInNanos > indexDebugThreshold) {
155+
} else if (indexDebugThreshold >= 0 && tookInNanos > indexDebugThreshold && level.isLevelEnabledFor(SlowLogLevel.DEBUG)) {
153156
indexLogger.debug("{}", new SlowLogParsedDocumentPrinter(index, doc, tookInNanos, reformat, maxSourceCharsToLog));
154-
} else if (indexTraceThreshold >= 0 && tookInNanos > indexTraceThreshold) {
157+
} else if (indexTraceThreshold >= 0 && tookInNanos > indexTraceThreshold && level.isLevelEnabledFor(SlowLogLevel.TRACE)) {
155158
indexLogger.trace("{}", new SlowLogParsedDocumentPrinter(index, doc, tookInNanos, reformat, maxSourceCharsToLog));
156159
}
157160
}
@@ -230,7 +233,7 @@ int getMaxSourceCharsToLog() {
230233
}
231234

232235
SlowLogLevel getLevel() {
233-
return SlowLogLevel.parse(indexLogger.getLevel().name());
236+
return level;
234237
}
235238

236239
}

server/src/main/java/org/elasticsearch/index/SearchSlowLog.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public final class SearchSlowLog implements SearchOperationListener {
4848
private final Logger queryLogger;
4949
private final Logger fetchLogger;
5050

51-
private static final String INDEX_SEARCH_SLOWLOG_PREFIX = "index.search.slowlog";
51+
static final String INDEX_SEARCH_SLOWLOG_PREFIX = "index.search.slowlog";
5252
public static final Setting<TimeValue> INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_WARN_SETTING =
5353
Setting.timeSetting(INDEX_SEARCH_SLOWLOG_PREFIX + ".threshold.query.warn", TimeValue.timeValueNanos(-1),
5454
TimeValue.timeValueMillis(-1), Property.Dynamic, Property.IndexScope);
@@ -78,11 +78,13 @@ public final class SearchSlowLog implements SearchOperationListener {
7878
Property.IndexScope);
7979

8080
private static final ToXContent.Params FORMAT_PARAMS = new ToXContent.MapParams(Collections.singletonMap("pretty", "false"));
81+
private SlowLogLevel level;
8182

8283
public SearchSlowLog(IndexSettings indexSettings) {
83-
84-
this.queryLogger = LogManager.getLogger(INDEX_SEARCH_SLOWLOG_PREFIX + ".query." + indexSettings.getUUID());
85-
this.fetchLogger = LogManager.getLogger(INDEX_SEARCH_SLOWLOG_PREFIX + ".fetch." + indexSettings.getUUID());
84+
this.queryLogger = LogManager.getLogger(INDEX_SEARCH_SLOWLOG_PREFIX + ".query");
85+
this.fetchLogger = LogManager.getLogger(INDEX_SEARCH_SLOWLOG_PREFIX + ".fetch");
86+
Loggers.setLevel(this.fetchLogger, SlowLogLevel.TRACE.name());
87+
Loggers.setLevel(this.queryLogger, SlowLogLevel.TRACE.name());
8688

8789
indexSettings.getScopedSettings().addSettingsUpdateConsumer(INDEX_SEARCH_SLOWLOG_THRESHOLD_QUERY_WARN_SETTING,
8890
this::setQueryWarnThreshold);
@@ -115,31 +117,31 @@ public SearchSlowLog(IndexSettings indexSettings) {
115117
}
116118

117119
private void setLevel(SlowLogLevel level) {
118-
Loggers.setLevel(queryLogger, level.name());
119-
Loggers.setLevel(fetchLogger, level.name());
120+
this.level = level;
120121
}
122+
121123
@Override
122124
public void onQueryPhase(SearchContext context, long tookInNanos) {
123-
if (queryWarnThreshold >= 0 && tookInNanos > queryWarnThreshold) {
125+
if (queryWarnThreshold >= 0 && tookInNanos > queryWarnThreshold && level.isLevelEnabledFor(SlowLogLevel.WARN)) {
124126
queryLogger.warn("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
125-
} else if (queryInfoThreshold >= 0 && tookInNanos > queryInfoThreshold) {
127+
} else if (queryInfoThreshold >= 0 && tookInNanos > queryInfoThreshold && level.isLevelEnabledFor(SlowLogLevel.INFO)) {
126128
queryLogger.info("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
127-
} else if (queryDebugThreshold >= 0 && tookInNanos > queryDebugThreshold) {
129+
} else if (queryDebugThreshold >= 0 && tookInNanos > queryDebugThreshold && level.isLevelEnabledFor(SlowLogLevel.DEBUG)) {
128130
queryLogger.debug("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
129-
} else if (queryTraceThreshold >= 0 && tookInNanos > queryTraceThreshold) {
131+
} else if (queryTraceThreshold >= 0 && tookInNanos > queryTraceThreshold && level.isLevelEnabledFor(SlowLogLevel.TRACE)) {
130132
queryLogger.trace("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
131133
}
132134
}
133135

134136
@Override
135137
public void onFetchPhase(SearchContext context, long tookInNanos) {
136-
if (fetchWarnThreshold >= 0 && tookInNanos > fetchWarnThreshold) {
138+
if (fetchWarnThreshold >= 0 && tookInNanos > fetchWarnThreshold && level.isLevelEnabledFor(SlowLogLevel.WARN)) {
137139
fetchLogger.warn("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
138-
} else if (fetchInfoThreshold >= 0 && tookInNanos > fetchInfoThreshold) {
140+
} else if (fetchInfoThreshold >= 0 && tookInNanos > fetchInfoThreshold && level.isLevelEnabledFor(SlowLogLevel.INFO)) {
139141
fetchLogger.info("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
140-
} else if (fetchDebugThreshold >= 0 && tookInNanos > fetchDebugThreshold) {
142+
} else if (fetchDebugThreshold >= 0 && tookInNanos > fetchDebugThreshold && level.isLevelEnabledFor(SlowLogLevel.DEBUG)) {
141143
fetchLogger.debug("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
142-
} else if (fetchTraceThreshold >= 0 && tookInNanos > fetchTraceThreshold) {
144+
} else if (fetchTraceThreshold >= 0 && tookInNanos > fetchTraceThreshold && level.isLevelEnabledFor(SlowLogLevel.TRACE)) {
143145
fetchLogger.trace("{}", new SlowLogSearchContextPrinter(context, tookInNanos));
144146
}
145147
}
@@ -256,7 +258,6 @@ long getFetchTraceThreshold() {
256258
}
257259

258260
SlowLogLevel getLevel() {
259-
assert queryLogger.getLevel().equals(fetchLogger.getLevel());
260-
return SlowLogLevel.parse(queryLogger.getLevel().name());
261+
return level;
261262
}
262263
}

server/src/main/java/org/elasticsearch/index/SlowLogLevel.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,23 @@
2121
import java.util.Locale;
2222

2323
public enum SlowLogLevel {
24-
WARN, TRACE, INFO, DEBUG;
24+
WARN(3), // most specific - little logging
25+
INFO(2),
26+
DEBUG(1),
27+
TRACE(0); // least specific - lots of logging
28+
29+
private final int specificity;
30+
31+
SlowLogLevel(int specificity) {
32+
this.specificity = specificity;
33+
}
34+
2535
public static SlowLogLevel parse(String level) {
2636
return valueOf(level.toUpperCase(Locale.ROOT));
2737
}
38+
39+
boolean isLevelEnabledFor(SlowLogLevel levelToBeUsed) {
40+
// example: this.info(2) tries to log with levelToBeUsed.warn(3) - should allow
41+
return this.specificity <= levelToBeUsed.specificity;
42+
}
2843
}

server/src/test/java/org/elasticsearch/common/logging/LoggersTests.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
import org.apache.logging.log4j.Level;
2323
import org.apache.logging.log4j.LogManager;
2424
import org.apache.logging.log4j.Logger;
25-
import org.apache.logging.log4j.core.LogEvent;
26-
import org.apache.logging.log4j.core.appender.AbstractAppender;
27-
import org.apache.logging.log4j.core.filter.RegexFilter;
2825
import org.apache.logging.log4j.message.ParameterizedMessage;
2926
import org.elasticsearch.test.ESTestCase;
3027

@@ -38,23 +35,6 @@
3835

3936
public class LoggersTests extends ESTestCase {
4037

41-
static class MockAppender extends AbstractAppender {
42-
private LogEvent lastEvent;
43-
44-
MockAppender(final String name) throws IllegalAccessException {
45-
super(name, RegexFilter.createFilter(".*(\n.*)*", new String[0], false, null, null), null);
46-
}
47-
48-
@Override
49-
public void append(LogEvent event) {
50-
lastEvent = event.toImmutable();
51-
}
52-
53-
ParameterizedMessage lastParameterizedMessage() {
54-
return (ParameterizedMessage) lastEvent.getMessage();
55-
}
56-
}
57-
5838
public void testParameterizedMessageLambda() throws Exception {
5939
final MockAppender appender = new MockAppender("trace_appender");
6040
appender.start();
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.common.logging;
21+
22+
import org.apache.logging.log4j.core.LogEvent;
23+
import org.apache.logging.log4j.core.appender.AbstractAppender;
24+
import org.apache.logging.log4j.core.filter.RegexFilter;
25+
import org.apache.logging.log4j.message.ParameterizedMessage;
26+
27+
public class MockAppender extends AbstractAppender {
28+
public LogEvent lastEvent;
29+
30+
public MockAppender(final String name) throws IllegalAccessException {
31+
super(name, RegexFilter.createFilter(".*(\n.*)*", new String[0], false, null, null), null);
32+
}
33+
34+
@Override
35+
public void append(LogEvent event) {
36+
lastEvent = event.toImmutable();
37+
}
38+
39+
ParameterizedMessage lastParameterizedMessage() {
40+
return (ParameterizedMessage) lastEvent.getMessage();
41+
}
42+
43+
public LogEvent getLastEventAndReset() {
44+
LogEvent toReturn = lastEvent;
45+
lastEvent = null;
46+
return toReturn;
47+
}
48+
}

0 commit comments

Comments
 (0)