Skip to content

ES|QL query log (#124094) #125120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions distribution/src/config/log4j2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,26 @@ logger.index_indexing_slowlog.name = index.indexing.slowlog.index
logger.index_indexing_slowlog.level = trace
logger.index_indexing_slowlog.appenderRef.index_indexing_slowlog_rolling.ref = index_indexing_slowlog_rolling
logger.index_indexing_slowlog.additivity = false


######## ES|QL query log JSON ####################
appender.esql_querylog_rolling.type = RollingFile
appender.esql_querylog_rolling.name = esql_querylog_rolling
appender.esql_querylog_rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs\
.cluster_name}_esql_querylog.json
appender.esql_querylog_rolling.layout.type = ECSJsonLayout
appender.esql_querylog_rolling.layout.dataset = elasticsearch.esql_querylog

appender.esql_querylog_rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs\
.cluster_name}_esql_querylog-%i.json.gz
appender.esql_querylog_rolling.policies.type = Policies
appender.esql_querylog_rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.esql_querylog_rolling.policies.size.size = 1GB
appender.esql_querylog_rolling.strategy.type = DefaultRolloverStrategy
appender.esql_querylog_rolling.strategy.max = 4
#################################################

logger.esql_querylog_rolling.name = esql.querylog
logger.esql_querylog_rolling.level = trace
logger.esql_querylog_rolling.appenderRef.esql_querylog_rolling.ref = esql_querylog_rolling
logger.esql_querylog_rolling.additivity = false
5 changes: 5 additions & 0 deletions docs/changelog/124094.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 124094
summary: ES|QL slow log
area: ES|QL
type: enhancement
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ public interface SlowLogFieldProvider {
* @param indexSettings settings for the index
*/
SlowLogFields create(IndexSettings indexSettings);

/**
* Create a field provider without index level settings
*/
SlowLogFields create();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ public interface SlowLogFields {
* @return map of field name to value
*/
Map<String, String> searchFields();

/**
* Slow log fields for query
* @return map of field name to value
*/
default Map<String, String> queryFields() {
return Map.of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public class IndicesServiceBuilder {
QueryRewriteInterceptor queryRewriteInterceptor = null;
SlowLogFieldProvider slowLogFieldProvider = new SlowLogFieldProvider() {
@Override
public SlowLogFields create(IndexSettings indexSettings) {
public SlowLogFields create() {
return new SlowLogFields() {
@Override
public Map<String, String> indexFields() {
Expand All @@ -96,6 +96,12 @@ public Map<String, String> searchFields() {
}
};
}

@Override
public SlowLogFields create(IndexSettings indexSettings) {
return create();
}

};

public IndicesServiceBuilder settings(Settings settings) {
Expand Down
77 changes: 59 additions & 18 deletions server/src/main/java/org/elasticsearch/node/NodeConstruction.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
import org.elasticsearch.index.IndexMode;
import org.elasticsearch.index.IndexSettingProvider;
import org.elasticsearch.index.IndexSettingProviders;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.IndexingPressure;
import org.elasticsearch.index.SlowLogFieldProvider;
import org.elasticsearch.index.SlowLogFields;
Expand Down Expand Up @@ -810,26 +811,65 @@ private void construct(
List<? extends SlowLogFieldProvider> slowLogFieldProviders = pluginsService.loadServiceProviders(SlowLogFieldProvider.class);
// NOTE: the response of index/search slow log fields below must be calculated dynamically on every call
// because the responses may change dynamically at runtime
SlowLogFieldProvider slowLogFieldProvider = indexSettings -> {
final List<SlowLogFields> fields = new ArrayList<>();
for (var provider : slowLogFieldProviders) {
fields.add(provider.create(indexSettings));
}
return new SlowLogFields() {
@Override
public Map<String, String> indexFields() {
return fields.stream()
.flatMap(f -> f.indexFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
SlowLogFieldProvider slowLogFieldProvider = new SlowLogFieldProvider() {
public SlowLogFields create() {
final List<SlowLogFields> fields = new ArrayList<>();
for (var provider : slowLogFieldProviders) {
fields.add(provider.create());
}
return new SlowLogFields() {
@Override
public Map<String, String> indexFields() {
return fields.stream()
.flatMap(f -> f.indexFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

@Override
public Map<String, String> searchFields() {
return fields.stream()
.flatMap(f -> f.searchFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

@Override
public Map<String, String> queryFields() {
return fields.stream()
.flatMap(f -> f.queryFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
};
}

@Override
public Map<String, String> searchFields() {
return fields.stream()
.flatMap(f -> f.searchFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
public SlowLogFields create(IndexSettings indexSettings) {
final List<SlowLogFields> fields = new ArrayList<>();
for (var provider : slowLogFieldProviders) {
fields.add(provider.create(indexSettings));
}
};
return new SlowLogFields() {
@Override
public Map<String, String> indexFields() {
return fields.stream()
.flatMap(f -> f.indexFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

@Override
public Map<String, String> searchFields() {
return fields.stream()
.flatMap(f -> f.searchFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

@Override
public Map<String, String> queryFields() {
return fields.stream()
.flatMap(f -> f.queryFields().entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
};
}

};

IndicesService indicesService = new IndicesServiceBuilder().settings(settings)
Expand Down Expand Up @@ -917,7 +957,8 @@ public Map<String, String> searchFields() {
systemIndices,
dataStreamGlobalRetentionSettings,
documentParsingProvider,
taskManager
taskManager,
slowLogFieldProvider
);

Collection<?> pluginComponents = pluginsService.flatMap(plugin -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.features.FeatureService;
import org.elasticsearch.index.SlowLogFieldProvider;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.indices.SystemIndices;
import org.elasticsearch.plugins.Plugin;
Expand Down Expand Up @@ -51,5 +52,6 @@ public record PluginServiceInstances(
SystemIndices systemIndices,
DataStreamGlobalRetentionSettings dataStreamGlobalRetentionSettings,
DocumentParsingProvider documentParsingProvider,
TaskManager taskManager
TaskManager taskManager,
SlowLogFieldProvider slowLogFieldProvider
) implements Plugin.PluginServices {}
6 changes: 6 additions & 0 deletions server/src/main/java/org/elasticsearch/plugins/Plugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.elasticsearch.features.FeatureService;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.index.IndexSettingProvider;
import org.elasticsearch.index.SlowLogFieldProvider;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.indices.SystemIndices;
import org.elasticsearch.plugins.internal.DocumentParsingProvider;
Expand Down Expand Up @@ -173,6 +174,11 @@ public interface PluginServices {
* to track task removal by registering a RemovedTaskListener.
*/
TaskManager taskManager();

/**
* Provider for additional SlowLog fields
*/
SlowLogFieldProvider slowLogFieldProvider();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ static void setFields(Map<String, String> fields) {
}

@Override
public SlowLogFields create(IndexSettings indexSettings) {
public SlowLogFields create() {
return new SlowLogFields() {
@Override
public Map<String, String> indexFields() {
Expand All @@ -223,6 +223,12 @@ public Map<String, String> searchFields() {
}
};
}

@Override
public SlowLogFields create(IndexSettings indexSettings) {
return create();
}

}

public static class TestAnotherSlowLogFieldProvider implements SlowLogFieldProvider {
Expand All @@ -234,7 +240,7 @@ static void setFields(Map<String, String> fields) {
}

@Override
public SlowLogFields create(IndexSettings indexSettings) {
public SlowLogFields create() {
return new SlowLogFields() {
@Override
public Map<String, String> indexFields() {
Expand All @@ -247,6 +253,11 @@ public Map<String, String> searchFields() {
}
};
}

@Override
public SlowLogFields create(IndexSettings indexSettings) {
return create();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public enum LogType {
SERVER_JSON("%s_server.json"),
AUDIT("%s_audit.json"),
SEARCH_SLOW("%s_index_search_slowlog.json"),
INDEXING_SLOW("%s_index_indexing_slowlog.json");
INDEXING_SLOW("%s_index_indexing_slowlog.json"),
ESQL_QUERY("%s_esql_querylog.json");

private final String filenameFormat;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.esql;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.filter.RegexFilter;
import org.apache.logging.log4j.message.Message;

public class MockAppender extends AbstractAppender {
public LogEvent lastEvent;

public MockAppender(final String name) throws IllegalAccessException {
super(name, RegexFilter.createFilter(".*(\n.*)*", new String[0], false, null, null), null, false);
}

@Override
public void append(LogEvent event) {
lastEvent = event.toImmutable();
}

public Message lastMessage() {
return lastEvent.getMessage();
}

public LogEvent lastEvent() {
return lastEvent;
}

public LogEvent getLastEventAndReset() {
LogEvent toReturn = lastEvent;
lastEvent = null;
return toReturn;
}
}
Loading