diff --git a/server/src/main/java/org/elasticsearch/TransportVersions.java b/server/src/main/java/org/elasticsearch/TransportVersions.java index fcddbbdae8efa..03445ac836163 100644 --- a/server/src/main/java/org/elasticsearch/TransportVersions.java +++ b/server/src/main/java/org/elasticsearch/TransportVersions.java @@ -207,6 +207,7 @@ static TransportVersion def(int id) { public static final TransportVersion RESCORE_VECTOR_ALLOW_ZERO = def(9_039_0_00); public static final TransportVersion PROJECT_ID_IN_SNAPSHOT = def(9_040_0_00); public static final TransportVersion INDEX_STATS_AND_METADATA_INCLUDE_PEAK_WRITE_LOAD = def(9_041_0_00); + public static final TransportVersion ESQL_PLANNER_PROFILE = def(9_042_0_00); /* * STOP! READ THIS FIRST! No, really, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java index 5e36eee7364c7..2d621a4d56cd4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java @@ -27,8 +27,10 @@ import org.elasticsearch.xcontent.ToXContent; import org.elasticsearch.xpack.core.esql.action.EsqlResponse; import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -346,18 +348,48 @@ public EsqlResponse responseInternal() { public static class Profile implements Writeable, ChunkedToXContentObject { private final List drivers; + private final List plannerProfile; - public Profile(List drivers) { + public static final Profile EMPTY = new Profile(List.of(), List.of()); + + public Profile() { + this.drivers = new ArrayList<>(); + this.plannerProfile = new ArrayList<>(); + } + + public Profile(List drivers, List plannerProfile) { this.drivers = drivers; + this.plannerProfile = plannerProfile; } public Profile(StreamInput in) throws IOException { this.drivers = in.readCollectionAsImmutableList(DriverProfile::readFrom); + if (in.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + this.plannerProfile = in.readCollectionAsImmutableList(PlannerProfile::readFrom); + } else { + this.plannerProfile = List.of(); + } + } + + public void merge(Profile other) { + this.drivers.addAll(other.drivers); + this.plannerProfile.addAll(other.plannerProfile); + } + + public List getDriverProfiles() { + return drivers; + } + + public List getPlannerProfiles() { + return plannerProfile; } @Override public void writeTo(StreamOutput out) throws IOException { out.writeCollection(drivers); + if (out.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + out.writeCollection(plannerProfile); + } } @Override @@ -369,12 +401,12 @@ public boolean equals(Object o) { return false; } Profile profile = (Profile) o; - return Objects.equals(drivers, profile.drivers); + return Objects.equals(drivers, profile.drivers) && Objects.equals(plannerProfile, profile.plannerProfile); } @Override public int hashCode() { - return Objects.hash(drivers); + return Objects.hash(drivers, plannerProfile); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 384d556165ecd..fbaf3e56070d0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -95,6 +95,7 @@ import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject; import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation; import org.elasticsearch.xpack.esql.plan.logical.local.LocalSupplier; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.rule.ParameterizedRule; import org.elasticsearch.xpack.esql.rule.ParameterizedRuleExecutor; import org.elasticsearch.xpack.esql.rule.Rule; @@ -189,8 +190,8 @@ public class Analyzer extends ParameterizedRuleExecutor { - public LocalLogicalPlanOptimizer(LocalLogicalOptimizerContext localLogicalOptimizerContext) { - super(localLogicalOptimizerContext); + public LocalLogicalPlanOptimizer(LocalLogicalOptimizerContext localLogicalOptimizerContext, PlannerProfile profile) { + super(localLogicalOptimizerContext, profile); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java index a865f784137ad..4b7e4739880b9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizer.java @@ -19,6 +19,7 @@ import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.SpatialDocValuesExtraction; import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.SpatialShapeBoundsExtraction; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.rule.ParameterizedRuleExecutor; import org.elasticsearch.xpack.esql.rule.Rule; @@ -36,8 +37,8 @@ public class LocalPhysicalPlanOptimizer extends ParameterizedRuleExecutor runDurations; + private int runsWithChanges; + + public RuleProfile() { + this.runDurations = new ArrayList<>(); + this.runsWithChanges = 0; + } + + public RuleProfile(List durationNanos, int runsWithChanges) { + this.runDurations = durationNanos; + this.runsWithChanges = runsWithChanges; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeCollection(runDurations, StreamOutput::writeLong); + out.writeInt(runsWithChanges); + } + + public RuleProfile readFrom(StreamInput in) throws IOException { + List runDurations = in.readCollectionAsImmutableList(StreamInput::readLong); + int runsWithChanges = in.readInt(); + return new RuleProfile(runDurations, runsWithChanges); + } + + public void addRun(long runDuration, boolean hasChanges) { + runDurations.add(runDuration); + if (hasChanges) { + runsWithChanges++; + } + } + + @Override + public Iterator toXContentChunked(ToXContent.Params params) { + // NOCOMMIT + return null; + } + + // NOCOMMIT equals and hashcode, once the fields are stable + } + + public static final PlannerProfile EMPTY = new PlannerProfile(false, ""); + + private final boolean isLocalPlanning; + private final String nodeName; + + private Map> ruleProfiles; + + public PlannerProfile(boolean isLocalPlanning, String nodeName) { + this.isLocalPlanning = isLocalPlanning; + this.nodeName = nodeName; + ruleProfiles = new HashMap<>(); + } + + public static PlannerProfile readFrom(StreamInput in) throws IOException { + // NOCOMMIT - need to read back the profiles + return new PlannerProfile(in.readBoolean(), in.readString()); + } + + public void recordRuleProfile(String batchName, String ruleName, long runDuration, boolean hasChanges) { + ruleProfiles.computeIfAbsent(batchName, k -> new HashMap<>()) + .computeIfAbsent(ruleName, k -> new RuleProfile()) + .addRun(runDuration, hasChanges); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeBoolean(isLocalPlanning); + out.writeString(nodeName); + // NOCOMMIT - need to write out the profile map + } + + @Override + public Iterator toXContentChunked(ToXContent.Params params) { + // NOCOMMIT + throw new UnsupportedOperationException(); + } + // NOCOMMIT equals and hashcode, once the fields are stable +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java index d58ce1105dc38..315fb9cb02e79 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java @@ -138,14 +138,27 @@ public static PhysicalPlan localPlan( List searchContexts, Configuration configuration, FoldContext foldCtx, - PhysicalPlan plan + PhysicalPlan plan, + PlannerProfile profile ) { - return localPlan(configuration, foldCtx, plan, SearchContextStats.from(searchContexts)); + return localPlan(configuration, foldCtx, plan, SearchContextStats.from(searchContexts), profile); } - public static PhysicalPlan localPlan(Configuration configuration, FoldContext foldCtx, PhysicalPlan plan, SearchStats searchStats) { - final var logicalOptimizer = new LocalLogicalPlanOptimizer(new LocalLogicalOptimizerContext(configuration, foldCtx, searchStats)); - var physicalOptimizer = new LocalPhysicalPlanOptimizer(new LocalPhysicalOptimizerContext(configuration, foldCtx, searchStats)); + public static PhysicalPlan localPlan( + Configuration configuration, + FoldContext foldCtx, + PhysicalPlan plan, + SearchStats searchStats, + PlannerProfile profile + ) { + final var logicalOptimizer = new LocalLogicalPlanOptimizer( + new LocalLogicalOptimizerContext(configuration, foldCtx, searchStats), + profile + ); + var physicalOptimizer = new LocalPhysicalPlanOptimizer( + new LocalPhysicalOptimizerContext(configuration, foldCtx, searchStats), + profile + ); return localPlan(plan, logicalOptimizer, physicalOptimizer); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java index 5ad81177a6a44..504175404c660 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java @@ -11,7 +11,6 @@ import org.elasticsearch.action.ActionListenerResponseHandler; import org.elasticsearch.action.OriginalIndices; import org.elasticsearch.action.support.ChannelActionListener; -import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.compute.operator.exchange.ExchangeService; import org.elasticsearch.compute.operator.exchange.ExchangeSourceHandler; import org.elasticsearch.core.Releasable; @@ -27,6 +26,7 @@ import org.elasticsearch.transport.TransportRequestOptions; import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.esql.session.Configuration; @@ -75,7 +75,7 @@ void startComputeOnRemoteCluster( RemoteCluster cluster, Runnable cancelQueryOnFailure, EsqlExecutionInfo executionInfo, - ActionListener> listener + ActionListener listener ) { var queryPragmas = configuration.pragmas(); listener = ActionListener.runBefore(listener, exchangeSource.addEmptySink()::close); @@ -87,10 +87,10 @@ void startComputeOnRemoteCluster( final boolean receivedResults = finalResponse.get() != null || pagesFetched.get(); if (receivedResults == false && EsqlCCSUtils.shouldIgnoreRuntimeError(executionInfo, clusterAlias, e)) { EsqlCCSUtils.markClusterWithFinalStateAndNoShards(executionInfo, clusterAlias, EsqlExecutionInfo.Cluster.Status.SKIPPED, e); - l.onResponse(List.of()); + l.onResponse(EsqlQueryResponse.Profile.EMPTY); } else if (configuration.allowPartialResults()) { EsqlCCSUtils.markClusterWithFinalStateAndNoShards(executionInfo, clusterAlias, EsqlExecutionInfo.Cluster.Status.PARTIAL, e); - l.onResponse(List.of()); + l.onResponse(EsqlQueryResponse.Profile.EMPTY); } else { l.onFailure(e); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeListener.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeListener.java index c8b8e84fd2478..a5c3aa01cd603 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeListener.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeListener.java @@ -14,6 +14,8 @@ import org.elasticsearch.compute.operator.ResponseHeadersCollector; import org.elasticsearch.core.Releasable; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import java.util.ArrayList; import java.util.Collections; @@ -29,17 +31,21 @@ final class ComputeListener implements Releasable { private final EsqlRefCountingListener refs; private final List collectedProfiles; + private final List collectedPlannerProfiles; private final ResponseHeadersCollector responseHeaders; private final Runnable runOnFailure; - ComputeListener(ThreadPool threadPool, Runnable runOnFailure, ActionListener> delegate) { + ComputeListener(ThreadPool threadPool, Runnable runOnFailure, ActionListener delegate) { this.runOnFailure = runOnFailure; this.responseHeaders = new ResponseHeadersCollector(threadPool.getThreadContext()); this.collectedProfiles = Collections.synchronizedList(new ArrayList<>()); + this.collectedPlannerProfiles = Collections.synchronizedList(new ArrayList<>()); // listener that executes after all the sub-listeners refs (created via acquireCompute) have completed this.refs = new EsqlRefCountingListener(delegate.delegateFailure((l, ignored) -> { responseHeaders.finish(); - delegate.onResponse(collectedProfiles.stream().toList()); + delegate.onResponse( + new EsqlQueryResponse.Profile(collectedProfiles.stream().toList(), collectedPlannerProfiles.stream().toList()) + ); })); } @@ -60,12 +66,18 @@ ActionListener acquireAvoid() { /** * Acquires a new listener that collects compute result. This listener will also collect warnings emitted during compute */ - ActionListener> acquireCompute() { + ActionListener acquireCompute() { final ActionListener delegate = acquireAvoid(); return ActionListener.wrap(profiles -> { responseHeaders.collect(); - if (profiles != null && profiles.isEmpty() == false) { - collectedProfiles.addAll(profiles); + if (profiles != null) { + // TODO: move profile merging onto profile object + if (profiles.getDriverProfiles().isEmpty() == false) { + collectedProfiles.addAll(profiles.getDriverProfiles()); + } + if (profiles.getPlannerProfiles().isEmpty() == false) { + collectedPlannerProfiles.addAll(profiles.getPlannerProfiles()); + } } delegate.onResponse(null); }, e -> { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeResponse.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeResponse.java index 289186ae38e6e..a2b36f4033e78 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeResponse.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeResponse.java @@ -14,6 +14,7 @@ import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.core.TimeValue; import org.elasticsearch.transport.TransportResponse; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import java.io.IOException; import java.util.List; @@ -22,7 +23,7 @@ * The compute result of {@link DataNodeRequest} or {@link ClusterComputeRequest} */ final class ComputeResponse extends TransportResponse { - private final List profiles; + private final EsqlQueryResponse.Profile profiles; // for use with ClusterComputeRequests (cross-cluster searches) private final TimeValue took; // overall took time for a specific cluster in a cross-cluster search @@ -32,12 +33,12 @@ final class ComputeResponse extends TransportResponse { public final int failedShards; public final List failures; - ComputeResponse(List profiles) { + ComputeResponse(EsqlQueryResponse.Profile profiles) { this(profiles, null, null, null, null, null, List.of()); } ComputeResponse( - List profiles, + EsqlQueryResponse.Profile profiles, TimeValue took, Integer totalShards, Integer successfulShards, @@ -57,7 +58,11 @@ final class ComputeResponse extends TransportResponse { ComputeResponse(StreamInput in) throws IOException { if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_12_0)) { if (in.readBoolean()) { - profiles = in.readCollectionAsImmutableList(DriverProfile::readFrom); + if (in.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + profiles = new EsqlQueryResponse.Profile(in); + } else { + profiles = new EsqlQueryResponse.Profile(in.readCollectionAsImmutableList(DriverProfile::readFrom), List.of()); + } } else { profiles = null; } @@ -92,7 +97,11 @@ public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(false); } else { out.writeBoolean(true); - out.writeCollection(profiles); + if (out.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + profiles.writeTo(out); + } else { + out.writeCollection(profiles.getDriverProfiles()); + } } } if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_16_0)) { @@ -108,7 +117,7 @@ public void writeTo(StreamOutput out) throws IOException { } } - public List getProfiles() { + public EsqlQueryResponse.Profile getProfiles() { return profiles; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java index 293be0eb3c2b0..3fb75ae0ae2f5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java @@ -17,7 +17,6 @@ import org.elasticsearch.compute.data.BlockFactory; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.Driver; -import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.compute.operator.DriverTaskRunner; import org.elasticsearch.compute.operator.exchange.ExchangeService; import org.elasticsearch.compute.operator.exchange.ExchangeSourceHandler; @@ -28,6 +27,7 @@ import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.logging.LogManager; import org.elasticsearch.logging.Logger; +import org.elasticsearch.node.Node; import org.elasticsearch.search.SearchService; import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.lookup.SourceProvider; @@ -42,6 +42,7 @@ import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo; import org.elasticsearch.xpack.esql.action.EsqlQueryAction; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.enrich.EnrichLookupService; @@ -52,6 +53,7 @@ import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.esql.planner.EsPhysicalOperationProviders; import org.elasticsearch.xpack.esql.planner.LocalExecutionPlanner; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.planner.PlannerUtils; import org.elasticsearch.xpack.esql.session.Configuration; import org.elasticsearch.xpack.esql.session.Result; @@ -318,7 +320,7 @@ public void execute( EsqlExecutionInfo.Cluster.Status.PARTIAL ).setFailures(List.of(new ShardSearchFailure(e))).build() ); - dataNodesListener.onResponse(List.of()); + dataNodesListener.onResponse(EsqlQueryResponse.Profile.EMPTY); } else { dataNodesListener.onFailure(e); } @@ -378,7 +380,7 @@ private static void updateExecutionInfoAfterCoordinatorOnlyQuery(EsqlExecutionIn } } - void runCompute(CancellableTask task, ComputeContext context, PhysicalPlan plan, ActionListener> listener) { + void runCompute(CancellableTask task, ComputeContext context, PhysicalPlan plan, ActionListener listener) { listener = ActionListener.runBefore(listener, () -> Releasables.close(context.searchContexts())); List contexts = new ArrayList<>(context.searchContexts().size()); for (int i = 0; i < context.searchContexts().size(); i++) { @@ -397,6 +399,7 @@ public SourceProvider createSourceProvider() { ); } final List drivers; + final PlannerProfile localPlannerProfile = new PlannerProfile(true, Node.NODE_NAME_SETTING.get(clusterService.getSettings())); try { LocalExecutionPlanner planner = new LocalExecutionPlanner( context.sessionId(), @@ -416,7 +419,13 @@ public SourceProvider createSourceProvider() { LOGGER.debug("Received physical plan:\n{}", plan); - plan = PlannerUtils.localPlan(context.searchExecutionContexts(), context.configuration(), context.foldCtx(), plan); + plan = PlannerUtils.localPlan( + context.searchExecutionContexts(), + context.configuration(), + context.foldCtx(), + plan, + localPlannerProfile + ); // the planner will also set the driver parallelism in LocalExecutionPlanner.LocalExecutionPlan (used down below) // it's doing this in the planning of EsQueryExec (the source of the data) // see also EsPhysicalOperationProviders.sourcePhysicalOperation @@ -435,9 +444,9 @@ public SourceProvider createSourceProvider() { } ActionListener listenerCollectingStatus = listener.map(ignored -> { if (context.configuration().profile()) { - return drivers.stream().map(Driver::profile).toList(); + return new EsqlQueryResponse.Profile(drivers.stream().map(Driver::profile).toList(), List.of(localPlannerProfile)); } else { - return List.of(); + return EsqlQueryResponse.Profile.EMPTY; } }); listenerCollectingStatus = ActionListener.releaseAfter(listenerCollectingStatus, () -> Releasables.close(drivers)); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java index bea9c7b7a5db9..8dc5e67bee46c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeHandler.java @@ -16,7 +16,6 @@ import org.elasticsearch.action.support.ChannelActionListener; import org.elasticsearch.action.support.RefCountingRunnable; import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.compute.operator.exchange.ExchangeService; import org.elasticsearch.compute.operator.exchange.ExchangeSink; import org.elasticsearch.compute.operator.exchange.ExchangeSinkHandler; @@ -39,6 +38,7 @@ import org.elasticsearch.transport.TransportRequestHandler; import org.elasticsearch.transport.TransportRequestOptions; import org.elasticsearch.transport.TransportService; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.plan.physical.ExchangeSinkExec; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; @@ -251,11 +251,11 @@ private void runBatch(int startBatchIndex) { final int endBatchIndex = Math.min(startBatchIndex + maxConcurrentShards, request.shardIds().size()); final AtomicInteger pagesProduced = new AtomicInteger(); List shardIds = request.shardIds().subList(startBatchIndex, endBatchIndex); - ActionListener> batchListener = new ActionListener<>() { - final ActionListener> ref = computeListener.acquireCompute(); + ActionListener batchListener = new ActionListener<>() { + final ActionListener ref = computeListener.acquireCompute(); @Override - public void onResponse(List result) { + public void onResponse(EsqlQueryResponse.Profile result) { try { onBatchCompleted(endBatchIndex); } finally { @@ -269,7 +269,7 @@ public void onFailure(Exception e) { for (ShardId shardId : shardIds) { addShardLevelFailure(shardId, e); } - onResponse(List.of()); + onResponse(EsqlQueryResponse.Profile.EMPTY); } else { // TODO: add these to fatal failures so we can continue processing other shards. try { @@ -283,7 +283,7 @@ public void onFailure(Exception e) { acquireSearchContexts(clusterAlias, shardIds, configuration, request.aliasFilters(), ActionListener.wrap(searchContexts -> { assert ThreadPool.assertCurrentThreadPool(ThreadPool.Names.SEARCH, ESQL_WORKER_THREAD_POOL_NAME); if (searchContexts.isEmpty()) { - batchListener.onResponse(List.of()); + batchListener.onResponse(EsqlQueryResponse.Profile.EMPTY); return; } var computeContext = new ComputeContext( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeResponse.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeResponse.java index 1313db9e70449..c0e6e4d1eb361 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeResponse.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeComputeResponse.java @@ -7,11 +7,13 @@ package org.elasticsearch.xpack.esql.plugin; +import org.elasticsearch.TransportVersions; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.transport.TransportResponse; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import java.io.IOException; import java.util.List; @@ -22,20 +24,31 @@ * The compute result of {@link DataNodeRequest} */ final class DataNodeComputeResponse extends TransportResponse { - private final List profiles; + private final EsqlQueryResponse.Profile profiles; private final Map shardLevelFailures; - DataNodeComputeResponse(List profiles, Map shardLevelFailures) { + DataNodeComputeResponse(EsqlQueryResponse.Profile profiles, Map shardLevelFailures) { this.profiles = profiles; this.shardLevelFailures = shardLevelFailures; } DataNodeComputeResponse(StreamInput in) throws IOException { if (DataNodeComputeHandler.supportShardLevelRetryFailure(in.getTransportVersion())) { - this.profiles = in.readCollectionAsImmutableList(DriverProfile::readFrom); + if (in.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + this.profiles = new EsqlQueryResponse.Profile(in); + } else { + this.profiles = new EsqlQueryResponse.Profile(in.readCollectionAsImmutableList(DriverProfile::readFrom), List.of()); + } this.shardLevelFailures = in.readMap(ShardId::new, StreamInput::readException); } else { - this.profiles = Objects.requireNonNullElse(new ComputeResponse(in).getProfiles(), List.of()); + if (in.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + this.profiles = new EsqlQueryResponse.Profile(in); + } else { + this.profiles = new EsqlQueryResponse.Profile( + Objects.requireNonNullElse(new ComputeResponse(in).getProfiles().getDriverProfiles(), List.of()), + List.of() + ); + } this.shardLevelFailures = Map.of(); } } @@ -43,7 +56,11 @@ final class DataNodeComputeResponse extends TransportResponse { @Override public void writeTo(StreamOutput out) throws IOException { if (DataNodeComputeHandler.supportShardLevelRetryFailure(out.getTransportVersion())) { - out.writeCollection(profiles, (o, v) -> v.writeTo(o)); + if (out.getTransportVersion().onOrAfter(TransportVersions.ESQL_PLANNER_PROFILE)) { + profiles.writeTo(out); + } else { + out.writeCollection(profiles.getDriverProfiles(), (o, v) -> v.writeTo(o)); + } out.writeMap(shardLevelFailures, (o, v) -> v.writeTo(o), StreamOutput::writeException); } else { if (shardLevelFailures.isEmpty() == false) { @@ -53,7 +70,7 @@ public void writeTo(StreamOutput out) throws IOException { } } - List profiles() { + EsqlQueryResponse.Profile profiles() { return profiles; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSender.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSender.java index 7abc0ba40af76..0726fcc620276 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSender.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSender.java @@ -21,7 +21,6 @@ import org.elasticsearch.cluster.node.DiscoveryNodeRole; import org.elasticsearch.common.breaker.CircuitBreakingException; import org.elasticsearch.common.util.concurrent.ConcurrentCollections; -import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.compute.operator.FailureCollector; import org.elasticsearch.core.TimeValue; import org.elasticsearch.index.Index; @@ -35,6 +34,7 @@ import org.elasticsearch.transport.TransportException; import org.elasticsearch.transport.TransportRequestOptions; import org.elasticsearch.transport.TransportService; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.action.EsqlSearchShardsAction; import java.util.ArrayList; @@ -236,9 +236,9 @@ private List selectFailures() { } private void sendOneNodeRequest(TargetShards targetShards, ComputeListener computeListener, NodeRequest request) { - final ActionListener> listener = computeListener.acquireCompute(); + final ActionListener listener = computeListener.acquireCompute(); sendRequest(request.node, request.shardIds, request.aliasFilters, new NodeListener() { - void onAfter(List profiles) { + void onAfter(EsqlQueryResponse.Profile profiles) { nodePermits.get(request.node).release(); if (concurrentRequests != null) { concurrentRequests.release(); @@ -269,7 +269,7 @@ public void onFailure(Exception e, boolean receivedData) { trackShardLevelFailure(shardId, receivedData, e); pendingShardIds.add(shardId); } - onAfter(List.of()); + onAfter(EsqlQueryResponse.Profile.EMPTY); } @Override @@ -278,7 +278,7 @@ public void onSkip() { if (rootTask.isCancelled()) { onFailure(new TaskCancelledException("null"), true); } else { - onResponse(new DataNodeComputeResponse(List.of(), Map.of())); + onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of())); } } }); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java index 56773005edd5c..fa0468c072a7b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/EsqlPlugin.java @@ -40,6 +40,7 @@ import org.elasticsearch.core.TimeValue; import org.elasticsearch.features.NodeFeature; import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.node.Node; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.rest.RestController; @@ -170,7 +171,8 @@ public Collection createComponents(PluginServices services) { new IndexResolver(services.client()), services.telemetryProvider().getMeterRegistry(), getLicenseState(), - new EsqlQueryLog(services.clusterService().getClusterSettings(), services.slowLogFieldProvider()) + new EsqlQueryLog(services.clusterService().getClusterSettings(), services.slowLogFieldProvider()), + Node.NODE_NAME_SETTING.get(settings) ), new ExchangeService( services.clusterService().getSettings(), diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java index 72ca465f647b7..1e48db703b2ab 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java @@ -327,7 +327,7 @@ private EsqlQueryResponse toResponse(Task task, EsqlQueryRequest request, Config } return new ColumnInfoImpl(c.name(), c.dataType().outputType(), originalTypes); }).toList(); - EsqlQueryResponse.Profile profile = configuration.profile() ? new EsqlQueryResponse.Profile(result.profiles()) : null; + EsqlQueryResponse.Profile profile = configuration.profile() ? result.profile() : null; threadPool.getThreadContext().addResponseHeader(AsyncExecutionId.ASYNC_EXECUTION_IS_RUNNING_HEADER, "?0"); if (task instanceof EsqlQueryTask asyncTask && request.keepOnCompletion()) { String asyncExecutionId = asyncTask.getExecutionId().getEncoded(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/ParameterizedRuleExecutor.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/ParameterizedRuleExecutor.java index fedef03799093..ee4f5a67af020 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/ParameterizedRuleExecutor.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/ParameterizedRuleExecutor.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.esql.rule; import org.elasticsearch.xpack.esql.core.tree.Node; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import java.util.function.Function; @@ -15,7 +16,8 @@ public abstract class ParameterizedRuleExecutor, private final Context context; - protected ParameterizedRuleExecutor(Context context) { + protected ParameterizedRuleExecutor(Context context, PlannerProfile profile) { + super(profile); this.context = context; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/RuleExecutor.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/RuleExecutor.java index 7df5a029d724e..bf69f108d3a5b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/RuleExecutor.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/rule/RuleExecutor.java @@ -11,6 +11,7 @@ import org.elasticsearch.core.TimeValue; import org.elasticsearch.xpack.esql.core.tree.Node; import org.elasticsearch.xpack.esql.core.tree.NodeUtils; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -21,6 +22,7 @@ public abstract class RuleExecutor> { private final Logger log = LogManager.getLogger(getClass()); + private final PlannerProfile profile; public static class Limiter { public static final Limiter DEFAULT = new Limiter(100); @@ -165,6 +167,7 @@ protected final ExecutionInfo executeWithInfo(TreeType plan) { batchRuns++; for (Rule rule : batch.rules) { + long ruleStart = System.nanoTime(); if (log.isTraceEnabled()) { log.trace("About to apply rule {}", rule); } @@ -182,6 +185,7 @@ protected final ExecutionInfo executeWithInfo(TreeType plan) { log.trace("Rule {} applied w/o changes", rule); } } + profile.recordRuleProfile(batch.name(), rule.name(), ruleStart - System.nanoTime(), hasChanged); } batchDuration = System.currentTimeMillis() - batchStart; } while (hasChanged && batch.limit.reached(batchRuns) == false); @@ -211,6 +215,10 @@ protected final ExecutionInfo executeWithInfo(TreeType plan) { return new ExecutionInfo(plan, currentPlan, transformations); } + protected RuleExecutor(PlannerProfile profile) { + this.profile = profile; + } + protected Function transform(Rule rule) { return rule::apply; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlCCSUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlCCSUtils.java index 3a2db609d6c8a..ff275383ec716 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlCCSUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlCCSUtils.java @@ -26,6 +26,7 @@ import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo; import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo.Cluster; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.analysis.Analyzer; import org.elasticsearch.xpack.esql.analysis.TableInfo; import org.elasticsearch.xpack.esql.index.IndexResolution; @@ -75,7 +76,9 @@ abstract static class CssPartialErrorsActionListener implements ActionListener 0) { // code-path to execute subplans - executeSubPlan(new ArrayList<>(), physicalPlan, iterator, executionInfo, runner, listener); + executeSubPlan(new EsqlQueryResponse.Profile(), physicalPlan, iterator, executionInfo, runner, listener); } else { // execute main plan runner.run(physicalPlan, listener); @@ -249,7 +254,7 @@ private void executeSubPlans( } private void executeSubPlan( - List profileAccumulator, + EsqlQueryResponse.Profile profileAccumulator, PhysicalPlan plan, Iterator subPlanIterator, EsqlExecutionInfo executionInfo, @@ -257,10 +262,12 @@ private void executeSubPlan( ActionListener listener ) { PlanTuple tuple = subPlanIterator.next(); + List plannerProfiles = new ArrayList<>(); + plannerProfiles.add(plannerProfile); runner.run(tuple.physical, listener.delegateFailureAndWrap((next, result) -> { try { - profileAccumulator.addAll(result.profiles()); + profileAccumulator.merge(result.profile()); LocalRelation resultWrapper = resultToPlan(tuple.logical, result); // replace the original logical plan with the backing result @@ -295,8 +302,9 @@ private void executeSubPlan( }); if (subPlanIterator.hasNext() == false) { + // In the production path, this is runner.run calls ComputeService.execute runner.run(newPlan, next.delegateFailureAndWrap((finalListener, finalResult) -> { - profileAccumulator.addAll(finalResult.profiles()); + profileAccumulator.merge(finalResult.profile()); finalListener.onResponse(new Result(finalResult.schema(), finalResult.pages(), profileAccumulator, executionInfo)); })); } else { @@ -337,7 +345,8 @@ public void analyzedPlan( Function analyzeAction = (l) -> { Analyzer analyzer = new Analyzer( new AnalyzerContext(configuration, functionRegistry, l.indices, l.lookupIndices, l.enrichResolution), - verifier + verifier, + plannerProfile ); LogicalPlan plan = analyzer.analyze(parsed); plan.setAnalyzed(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Result.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Result.java index 4f90893c759b8..c809a42a2feea 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Result.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Result.java @@ -9,9 +9,9 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.Page; -import org.elasticsearch.compute.operator.DriverProfile; import org.elasticsearch.core.Nullable; import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.core.expression.Attribute; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; @@ -19,14 +19,21 @@ /** * Results from running a chunk of ESQL. - * @param schema "Schema" of the {@link Attribute}s that are produced by the {@link LogicalPlan} - * that was run. Each {@link Page} contains a {@link Block} of values for each - * attribute in this list. - * @param pages Actual values produced by running the ESQL. - * @param profiles {@link DriverProfile}s from all drivers that ran to produce the output. These - * are quite cheap to build, so we build them for all ESQL runs, regardless of if - * users have asked for them. But we only include them in the results if users ask - * for them. - * @param executionInfo Metadata about the execution of this query. Used for cross cluster queries. + * + * @param schema "Schema" of the {@link Attribute}s that are produced by the {@link LogicalPlan} + * that was run. Each {@link Page} contains a {@link Block} of values for each + * attribute in this list. + * @param pages Actual values produced by running the ESQL. + * @param profile {@link org.elasticsearch.xpack.esql.action.EsqlQueryResponse.Profile}s + * from all drivers that ran to produce the output. These + * are quite cheap to build, so we build them for all ESQL runs, regardless of if + * users have asked for them. But we only include them in the results if users ask + * for them. + * @param executionInfo Metadata about the execution of this query. Used for cross cluster queries. */ -public record Result(List schema, List pages, List profiles, @Nullable EsqlExecutionInfo executionInfo) {} +public record Result( + List schema, + List pages, + EsqlQueryResponse.Profile profile, + @Nullable EsqlExecutionInfo executionInfo +) {} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 90d171bd9796a..89b9454a194a1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -51,6 +51,7 @@ import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo; import org.elasticsearch.xpack.esql.action.EsqlQueryRequest; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.elasticsearch.xpack.esql.analysis.Analyzer; import org.elasticsearch.xpack.esql.analysis.AnalyzerContext; import org.elasticsearch.xpack.esql.analysis.EnrichResolution; @@ -70,7 +71,6 @@ import org.elasticsearch.xpack.esql.optimizer.LocalLogicalPlanOptimizer; import org.elasticsearch.xpack.esql.optimizer.LocalPhysicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.LogicalOptimizerContext; -import org.elasticsearch.xpack.esql.optimizer.LogicalPlanOptimizer; import org.elasticsearch.xpack.esql.optimizer.TestLocalPhysicalPlanOptimizer; import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.logical.Enrich; @@ -83,6 +83,7 @@ import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.esql.planner.LocalExecutionPlanner; import org.elasticsearch.xpack.esql.planner.LocalExecutionPlanner.LocalExecutionPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.planner.PlannerUtils; import org.elasticsearch.xpack.esql.planner.TestPhysicalOperationProviders; import org.elasticsearch.xpack.esql.planner.mapper.Mapper; @@ -478,7 +479,11 @@ private static EnrichPolicy loadEnrichPolicyMapping(String policyFileName) { private LogicalPlan analyzedPlan(LogicalPlan parsed, CsvTestsDataLoader.MultiIndexTestDataset datasets) { var indexResolution = loadIndexResolution(datasets); var enrichPolicies = loadEnrichPolicies(); - var analyzer = new Analyzer(new AnalyzerContext(configuration, functionRegistry, indexResolution, enrichPolicies), TEST_VERIFIER); + var analyzer = new Analyzer( + new AnalyzerContext(configuration, functionRegistry, indexResolution, enrichPolicies), + TEST_VERIFIER, + new PlannerProfile(false, "") + ); LogicalPlan plan = analyzer.analyze(parsed); plan.setAnalyzed(); LOGGER.debug("Analyzed plan:\n{}", plan); @@ -543,12 +548,13 @@ private ActualResults executePlan(BigArrays bigArrays) throws Exception { FoldContext foldCtx = FoldContext.small(); EsqlSession session = new EsqlSession( getTestName(), + "nodeName", configuration, null, null, null, functionRegistry, - new LogicalPlanOptimizer(new LogicalOptimizerContext(configuration, foldCtx)), + new LogicalOptimizerContext(configuration, foldCtx), mapper, TEST_VERIFIER, new PlanTelemetry(functionRegistry), @@ -682,7 +688,10 @@ void executeSubPlan( drivers.addAll(coordinatorNodeExecutionPlan.createDrivers(getTestName())); if (dataNodePlan != null) { var searchStats = new DisabledSearchStats(); - var logicalTestOptimizer = new LocalLogicalPlanOptimizer(new LocalLogicalOptimizerContext(configuration, foldCtx, searchStats)); + var logicalTestOptimizer = new LocalLogicalPlanOptimizer( + new LocalLogicalOptimizerContext(configuration, foldCtx, searchStats), + new PlannerProfile(true, "") + ); var physicalTestOptimizer = new TestLocalPhysicalPlanOptimizer( new LocalPhysicalOptimizerContext(configuration, foldCtx, searchStats) ); @@ -710,6 +719,9 @@ protected void start(Driver driver, ActionListener driverListener) { } }; listener = ActionListener.releaseAfter(listener, () -> Releasables.close(drivers)); - runner.runToCompletion(drivers, listener.map(ignore -> new Result(physicalPlan.output(), collectedPages, List.of(), null))); + runner.runToCompletion( + drivers, + listener.map(ignore -> new Result(physicalPlan.output(), collectedPages, EsqlQueryResponse.Profile.EMPTY, null)) + ); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseProfileTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseProfileTests.java index a0357c2393971..6e9bf76a3d9b9 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseProfileTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseProfileTests.java @@ -26,12 +26,15 @@ protected Writeable.Reader instanceReader() { @Override protected EsqlQueryResponse.Profile createTestInstance() { - return new EsqlQueryResponse.Profile(randomDriverProfiles()); + return randomDriverProfiles(); } @Override protected EsqlQueryResponse.Profile mutateInstance(EsqlQueryResponse.Profile instance) { - return new EsqlQueryResponse.Profile(randomValueOtherThan(instance.drivers(), this::randomDriverProfiles)); + return new EsqlQueryResponse.Profile( + randomValueOtherThan(instance.drivers(), () -> randomDriverProfiles().getDriverProfiles()), + List.of() + ); } @Override @@ -39,8 +42,10 @@ protected NamedWriteableRegistry getNamedWriteableRegistry() { return new NamedWriteableRegistry(List.of(AbstractPageMappingOperator.Status.ENTRY)); } - private List randomDriverProfiles() { - return randomList(10, this::randomDriverProfile); + // TODO: this method is duplicated in ComputeListenerTests + private EsqlQueryResponse.Profile randomDriverProfiles() { + // NOCOMMIT - test planner profiles too + return new EsqlQueryResponse.Profile(randomList(10, this::randomDriverProfile), List.of()); } private DriverProfile randomDriverProfile() { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java index 5dc913af74165..9b10f2859c8ac 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java @@ -757,7 +757,9 @@ public void testProfileXContent() { List.of(new OperatorStatus("asdf", new AbstractPageMappingOperator.Status(10021, 10, 111, 222))), DriverSleeps.empty() ) - ) + ), + // NOCOMMIT - test planner profiles here + List.of() ), false, false, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java index d4e786a9d9bb0..2ca606260a93f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTestUtils.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.esql.parser.QueryParams; import org.elasticsearch.xpack.esql.plan.logical.Enrich; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.session.Configuration; import java.util.ArrayList; @@ -59,7 +60,8 @@ public static Analyzer analyzer(IndexResolution indexResolution, Verifier verifi defaultLookupResolution(), defaultEnrichResolution() ), - verifier + verifier, + new PlannerProfile(false, "") ); } @@ -72,14 +74,16 @@ public static Analyzer analyzer(IndexResolution indexResolution, Map resolved = new ArrayList<>(); @@ -1778,7 +1779,7 @@ public void testEnrichFieldsIncludeMatchField() { ) ); AnalyzerContext context = new AnalyzerContext(configuration(query), new EsqlFunctionRegistry(), testIndex, enrichResolution); - Analyzer analyzer = new Analyzer(context, TEST_VERIFIER); + Analyzer analyzer = new Analyzer(context, TEST_VERIFIER, new PlannerProfile(false, "")); LogicalPlan plan = analyze(query, analyzer); var limit = as(plan, Limit.class); assertThat(Expressions.names(limit.output()), contains("language_name", "language_code")); @@ -2175,7 +2176,8 @@ public void testLookupJoinUnknownIndex() { Map.of("foobar", missingLookupIndex), defaultEnrichResolution() ), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); String query = "FROM test | LOOKUP JOIN foobar ON last_name"; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java index e458fb009d5c3..ffacf3ba1987f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.xpack.esql.parser.ParsingException; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.logical.Row; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import java.io.IOException; @@ -46,7 +47,8 @@ public class ParsingTests extends ESTestCase { private final IndexResolution defaultIndex = loadIndexResolution("mapping-basic.json"); private final Analyzer defaultAnalyzer = new Analyzer( new AnalyzerContext(TEST_CFG, new EsqlFunctionRegistry(), defaultIndex, emptyPolicyResolution()), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); public void testCaseFunctionInvalidInputs() { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/CheckLicenseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/CheckLicenseTests.java index cf2de30e44456..59a060dd14ff1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/CheckLicenseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/CheckLicenseTests.java @@ -29,6 +29,7 @@ import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.logical.Limit; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.telemetry.Metrics; import java.util.List; @@ -91,7 +92,8 @@ public EsqlFunctionRegistry snapshotRegistry() { private static Analyzer analyzer(EsqlFunctionRegistry registry, License.OperationMode operationMode) { return new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, registry, analyzerDefaultMapping(), defaultEnrichResolution()), - new Verifier(new Metrics(new EsqlFunctionRegistry()), getLicenseState(operationMode)) + new Verifier(new Metrics(new EsqlFunctionRegistry()), getLicenseState(operationMode)), + new PlannerProfile(false, "") ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizerTests.java index 98f3d1d2d8d8e..0eef9a99395d0 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalLogicalPlanOptimizerTests.java @@ -50,6 +50,7 @@ import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject; import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation; import org.elasticsearch.xpack.esql.plan.logical.local.LocalSupplier; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.stats.SearchStats; import org.hamcrest.Matchers; import org.junit.BeforeClass; @@ -95,11 +96,12 @@ public static void init() { mapping = loadMapping("mapping-basic.json"); EsIndex test = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD)); IndexResolution getIndexResult = IndexResolution.valid(test); - logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()); + logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext(), new PlannerProfile(false, "")); analyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResult, EsqlTestUtils.emptyPolicyResolution()), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); } @@ -399,17 +401,18 @@ public void testSparseDocument() throws Exception { EsIndex index = new EsIndex("large", large, Map.of("large", IndexMode.STANDARD)); IndexResolution getIndexResult = IndexResolution.valid(index); - var logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()); + var logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext(), new PlannerProfile(false, "")); var analyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResult, EsqlTestUtils.emptyPolicyResolution()), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); var analyzed = analyzer.analyze(parser.createStatement(query)); var optimized = logicalOptimizer.optimize(analyzed); var localContext = new LocalLogicalOptimizerContext(EsqlTestUtils.TEST_CFG, FoldContext.small(), searchStats); - var plan = new LocalLogicalPlanOptimizer(localContext).localOptimize(optimized); + var plan = new LocalLogicalPlanOptimizer(localContext, new PlannerProfile(true, "")).localOptimize(optimized); var project = as(plan, Project.class); assertThat(project.projections(), hasSize(10)); @@ -560,7 +563,7 @@ private LogicalPlan plan(String query) { private LogicalPlan localPlan(LogicalPlan plan, SearchStats searchStats) { var localContext = new LocalLogicalOptimizerContext(EsqlTestUtils.TEST_CFG, FoldContext.small(), searchStats); // System.out.println(plan); - var localPlan = new LocalLogicalPlanOptimizer(localContext).localOptimize(plan); + var localPlan = new LocalLogicalPlanOptimizer(localContext, new PlannerProfile(true, "")).localOptimize(plan); // System.out.println(localPlan); return localPlan; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java index 465fbd5cd5e29..feeb9711e881f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java @@ -70,6 +70,7 @@ import org.elasticsearch.xpack.esql.plan.physical.ProjectExec; import org.elasticsearch.xpack.esql.plan.physical.TopNExec; import org.elasticsearch.xpack.esql.planner.FilterTests; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.plugin.QueryPragmas; import org.elasticsearch.xpack.esql.querydsl.query.SingleValueQuery; import org.elasticsearch.xpack.esql.rule.Rule; @@ -185,7 +186,8 @@ private Analyzer makeAnalyzer(String mappingFileName, EnrichResolution enrichRes return new Analyzer( new AnalyzerContext(config, new EsqlFunctionRegistry(), getIndexResult, enrichResolution), - new Verifier(new Metrics(new EsqlFunctionRegistry()), new XPackLicenseState(() -> 0L)) + new Verifier(new Metrics(new EsqlFunctionRegistry()), new XPackLicenseState(() -> 0L)), + new PlannerProfile(false, "") ); } @@ -421,7 +423,7 @@ public void testMultiCountAllWithFilter() { @SuppressWarnings("unchecked") public void testSingleCountWithStatsFilter() { // an optimizer that filters out the ExtractAggregateCommonFilter rule - var logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()) { + var logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext(), new PlannerProfile(false, "")) { @Override protected List> batches() { var oldBatches = super.batches(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index dc6ad0513852d..0262b0ff77f6c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -129,6 +129,7 @@ import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject; import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation; import org.elasticsearch.xpack.esql.plan.logical.local.LocalSupplier; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.junit.BeforeClass; import java.util.ArrayList; @@ -218,7 +219,7 @@ public static class SubstitutionOnlyOptimizer extends LogicalPlanOptimizer { public static SubstitutionOnlyOptimizer INSTANCE = new SubstitutionOnlyOptimizer(unboundLogicalOptimizerContext()); SubstitutionOnlyOptimizer(LogicalOptimizerContext optimizerContext) { - super(optimizerContext); + super(optimizerContext, new PlannerProfile(false, "")); } @Override @@ -231,7 +232,7 @@ protected List> batches() { public static void init() { parser = new EsqlParser(); logicalOptimizerCtx = unboundLogicalOptimizerContext(); - logicalOptimizer = new LogicalPlanOptimizer(logicalOptimizerCtx); + logicalOptimizer = new LogicalPlanOptimizer(logicalOptimizerCtx, new PlannerProfile(false, "")); enrichResolution = new EnrichResolution(); AnalyzerTestUtils.loadEnrichPolicyResolution(enrichResolution, "languages_idx", "id", "languages_idx", "mapping-languages.json"); @@ -247,7 +248,8 @@ public static void init() { defaultLookupResolution(), enrichResolution ), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); // Some tests use data from the airports index, so we load it here, and use it in the plan_airports() function. @@ -256,7 +258,8 @@ public static void init() { IndexResolution getIndexResultAirports = IndexResolution.valid(airports); analyzerAirports = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResultAirports, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); // Some tests need additional types, so we load that index here and use it in the plan_types() function. @@ -265,7 +268,8 @@ public static void init() { IndexResolution getIndexResultTypes = IndexResolution.valid(types); analyzerTypes = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResultTypes, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); // Some tests use mappings from mapping-extra.json to be able to test more types so we load it here @@ -274,14 +278,16 @@ public static void init() { IndexResolution getIndexResultExtra = IndexResolution.valid(extra); analyzerExtra = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResultExtra, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); metricMapping = loadMapping("k8s-mappings.json"); var metricsIndex = IndexResolution.valid(new EsIndex("k8s", metricMapping, Map.of("k8s", IndexMode.TIME_SERIES))); metricsAnalyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), metricsIndex, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); var multiIndexMapping = loadMapping("mapping-basic.json"); @@ -296,7 +302,8 @@ public static void init() { ); multiIndexAnalyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), multiIndex, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); } @@ -5266,7 +5273,8 @@ public void testEmptyMappingIndex() { IndexResolution getIndexResultAirports = IndexResolution.valid(empty); var analyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResultAirports, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); var plan = logicalOptimizer.optimize(analyzer.analyze(parser.createStatement("from empty_test"))); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java index 2af859bfabc31..4ed97f6c53afe 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java @@ -130,6 +130,7 @@ import org.elasticsearch.xpack.esql.plan.physical.UnaryExec; import org.elasticsearch.xpack.esql.planner.EsPhysicalOperationProviders; import org.elasticsearch.xpack.esql.planner.LocalExecutionPlanner; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.planner.PlannerUtils; import org.elasticsearch.xpack.esql.planner.mapper.Mapper; import org.elasticsearch.xpack.esql.plugin.QueryPragmas; @@ -252,8 +253,8 @@ public PhysicalPlanOptimizerTests(String name, Configuration config) { @Before public void init() { parser = new EsqlParser(); - logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()); - physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(config)); + logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext(), new PlannerProfile(false, "")); + physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(config), new PlannerProfile(false, "")); EsqlFunctionRegistry functionRegistry = new EsqlFunctionRegistry(); mapper = new Mapper(); var enrichResolution = setupEnrichResolution(); @@ -357,7 +358,8 @@ TestDataSource makeTestDataSource( IndexResolution getIndexResult = IndexResolution.valid(index); Analyzer analyzer = new Analyzer( new AnalyzerContext(config, functionRegistry, getIndexResult, lookupResolution, enrichResolution), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); return new TestDataSource(mapping, index, analyzer, stats); } @@ -7659,7 +7661,7 @@ private LocalExecutionPlanner.LocalExecutionPlan physicalOperationsFromPhysicalP // The TopN needs an estimated row size for the planner to work var plans = PlannerUtils.breakPlanBetweenCoordinatorAndDataNode(EstimatesRowSize.estimateRowSize(0, plan), config); plan = useDataNodePlan ? plans.v2() : plans.v1(); - plan = PlannerUtils.localPlan(List.of(), config, FoldContext.small(), plan); + plan = PlannerUtils.localPlan(List.of(), config, FoldContext.small(), plan, new PlannerProfile(true, "")); ExchangeSinkHandler exchangeSinkHandler = new ExchangeSinkHandler(null, 10, () -> 10); LocalExecutionPlanner planner = new LocalExecutionPlanner( "test", @@ -7928,7 +7930,7 @@ private PhysicalPlan optimizedPlan(PhysicalPlan plan, SearchStats searchStats) { // individually hence why here the plan is kept as is var l = p.transformUp(FragmentExec.class, fragment -> { - var localPlan = PlannerUtils.localPlan(config, FoldContext.small(), fragment, searchStats); + var localPlan = PlannerUtils.localPlan(config, FoldContext.small(), fragment, searchStats, new PlannerProfile(true, "")); return EstimatesRowSize.estimateRowSize(fragment.estimatedRowSize(), localPlan); }); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestLocalPhysicalPlanOptimizer.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestLocalPhysicalPlanOptimizer.java index 0d1e85171bac3..4fc8b3d6c05ff 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestLocalPhysicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestLocalPhysicalPlanOptimizer.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.esql.optimizer; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import java.util.List; @@ -20,7 +21,7 @@ public TestLocalPhysicalPlanOptimizer(LocalPhysicalOptimizerContext context) { } public TestLocalPhysicalPlanOptimizer(LocalPhysicalOptimizerContext context, boolean esRules) { - super(context); + super(context, new PlannerProfile(true, "")); this.esRules = esRules; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java index e26779e075b68..df3cacd4806f4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPhysicalPlanOptimizer.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.esql.optimizer; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.rule.RuleExecutor; public class TestPhysicalPlanOptimizer extends PhysicalPlanOptimizer { @@ -15,7 +16,7 @@ public class TestPhysicalPlanOptimizer extends PhysicalPlanOptimizer { private static final Iterable> rules = initializeRules(false); public TestPhysicalPlanOptimizer(PhysicalOptimizerContext context) { - super(context); + super(context, new PlannerProfile(false, "")); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPlannerOptimizer.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPlannerOptimizer.java index e6a7d110f8c09..c566102a5a198 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPlannerOptimizer.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/TestPlannerOptimizer.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.physical.EstimatesRowSize; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.planner.PlannerUtils; import org.elasticsearch.xpack.esql.planner.mapper.Mapper; import org.elasticsearch.xpack.esql.session.Configuration; @@ -27,7 +28,11 @@ public class TestPlannerOptimizer { private final Configuration config; public TestPlannerOptimizer(Configuration config, Analyzer analyzer) { - this(config, analyzer, new LogicalPlanOptimizer(new LogicalOptimizerContext(config, FoldContext.small()))); + this( + config, + analyzer, + new LogicalPlanOptimizer(new LogicalOptimizerContext(config, FoldContext.small()), new PlannerProfile(false, "")) + ); } public TestPlannerOptimizer(Configuration config, Analyzer analyzer, LogicalPlanOptimizer logicalOptimizer) { @@ -36,7 +41,7 @@ public TestPlannerOptimizer(Configuration config, Analyzer analyzer, LogicalPlan this.logicalOptimizer = logicalOptimizer; parser = new EsqlParser(); - physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(config)); + physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(config), new PlannerProfile(false, "")); mapper = new Mapper(); } @@ -63,7 +68,8 @@ private PhysicalPlan optimizedPlan(PhysicalPlan plan, SearchStats searchStats) { // individually hence why here the plan is kept as is var logicalTestOptimizer = new LocalLogicalPlanOptimizer( - new LocalLogicalOptimizerContext(config, FoldContext.small(), searchStats) + new LocalLogicalOptimizerContext(config, FoldContext.small(), searchStats), + new PlannerProfile(true, "") ); var physicalTestOptimizer = new TestLocalPhysicalPlanOptimizer( new LocalPhysicalOptimizerContext(config, FoldContext.small(), searchStats), diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java index 8f2063146cabd..59af39c633c4e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PropagateInlineEvalsTests.java @@ -31,6 +31,7 @@ import org.elasticsearch.xpack.esql.plan.logical.join.InlineJoin; import org.elasticsearch.xpack.esql.plan.logical.join.StubRelation; import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.junit.BeforeClass; import java.util.List; @@ -65,7 +66,8 @@ public static void init() { defaultLookupResolution(), new EnrichResolution() ), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/FilterTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/FilterTests.java index 4c1b009e847ed..00203d9a40661 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/FilterTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/FilterTests.java @@ -79,13 +79,17 @@ public static void init() { Map mapping = loadMapping("mapping-basic.json"); EsIndex test = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD)); IndexResolution getIndexResult = IndexResolution.valid(test); - logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()); - physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(EsqlTestUtils.TEST_CFG)); + logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext(), new PlannerProfile(false, "")); + physicalPlanOptimizer = new PhysicalPlanOptimizer( + new PhysicalOptimizerContext(EsqlTestUtils.TEST_CFG), + new PlannerProfile(false, "") + ); mapper = new Mapper(); analyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResult, EsqlTestUtils.emptyPolicyResolution()), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/PlanConcurrencyCalculatorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/PlanConcurrencyCalculatorTests.java index da36b42d1241b..e26f58de070b2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/PlanConcurrencyCalculatorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/PlanConcurrencyCalculatorTests.java @@ -239,10 +239,11 @@ private void assertConcurrency(String query, Integer concurrencyPragmaValue, Int Analyzer analyzer = analyzer(analyzerDefaultMapping(), TEST_VERIFIER, configuration); LogicalPlan logicalPlan = AnalyzerTestUtils.analyze(query, analyzer); - logicalPlan = new LogicalPlanOptimizer(new LogicalOptimizerContext(configuration, FoldContext.small())).optimize(logicalPlan); + logicalPlan = new LogicalPlanOptimizer(new LogicalOptimizerContext(configuration, FoldContext.small()), PlannerProfile.EMPTY) + .optimize(logicalPlan); PhysicalPlan physicalPlan = new Mapper().map(logicalPlan); - physicalPlan = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(configuration)).optimize(physicalPlan); + physicalPlan = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(configuration), PlannerProfile.EMPTY).optimize(physicalPlan); PhysicalPlan dataNodePlan = PlannerUtils.breakPlanBetweenCoordinatorAndDataNode(physicalPlan, configuration).v2(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java index 64f073310d3e6..f1be3b5e2e5b9 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java @@ -47,7 +47,8 @@ private static Analyzer makeAnalyzer(String mappingFileName) { return new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResult, new EnrichResolution()), - new Verifier(new Metrics(new EsqlFunctionRegistry()), new XPackLicenseState(() -> 0L)) + new Verifier(new Metrics(new EsqlFunctionRegistry()), new XPackLicenseState(() -> 0L)), + new PlannerProfile(false, "") ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java index e58824290c49e..0b53d837cdad2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import java.io.IOException; import java.util.ArrayList; @@ -189,10 +190,11 @@ static LogicalPlan parse(String query) { Map mapping = loadMapping("mapping-basic.json"); EsIndex test = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD)); IndexResolution getIndexResult = IndexResolution.valid(test); - var logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext()); + var logicalOptimizer = new LogicalPlanOptimizer(unboundLogicalOptimizerContext(), new PlannerProfile(false, "")); var analyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResult, emptyPolicyResolution()), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); return logicalOptimizer.optimize(analyzer.analyze(new EsqlParser().createStatement(query))); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ComputeListenerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ComputeListenerTests.java index 5ec78fd8efbee..091f649c2f613 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ComputeListenerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ComputeListenerTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.junit.After; import org.junit.Before; @@ -56,7 +57,7 @@ public void shutdownTransportService() { terminate(threadPool); } - private List randomProfiles() { + private EsqlQueryResponse.Profile randomProfiles() { int numProfiles = randomIntBetween(0, 2); List profiles = new ArrayList<>(numProfiles); for (int i = 0; i < numProfiles; i++) { @@ -75,20 +76,22 @@ private List randomProfiles() { ) ); } - return profiles; + // NOCOMMIT - add random planner profiles? + return new EsqlQueryResponse.Profile(profiles, List.of()); } public void testEmpty() { - PlainActionFuture> results = new PlainActionFuture<>(); + PlainActionFuture results = new PlainActionFuture<>(); try (var ignored = new ComputeListener(threadPool, () -> {}, results)) { assertFalse(results.isDone()); } assertTrue(results.isDone()); - assertThat(results.actionGet(10, TimeUnit.SECONDS), empty()); + assertThat(results.actionGet(10, TimeUnit.SECONDS).getDriverProfiles(), empty()); + assertThat(results.actionGet(10, TimeUnit.SECONDS).getPlannerProfiles(), empty()); } public void testCollectComputeResults() { - PlainActionFuture> future = new PlainActionFuture<>(); + PlainActionFuture future = new PlainActionFuture<>(); List allProfiles = new ArrayList<>(); AtomicInteger onFailure = new AtomicInteger(); try (var computeListener = new ComputeListener(threadPool, onFailure::incrementAndGet, future)) { @@ -103,8 +106,8 @@ public void testCollectComputeResults() { ); } else { var profiles = randomProfiles(); - allProfiles.addAll(profiles); - ActionListener> subListener = computeListener.acquireCompute(); + allProfiles.addAll(profiles.getDriverProfiles()); + ActionListener subListener = computeListener.acquireCompute(); threadPool.schedule( ActionRunnable.wrap(subListener, l -> l.onResponse(profiles)), TimeValue.timeValueNanos(between(0, 100)), @@ -113,9 +116,10 @@ public void testCollectComputeResults() { } } } - List profiles = future.actionGet(10, TimeUnit.SECONDS); + EsqlQueryResponse.Profile profiles = future.actionGet(10, TimeUnit.SECONDS); assertThat( - profiles.stream().collect(Collectors.toMap(p -> p, p -> 1, Integer::sum)), + // TODO: Test planner profiles here? + profiles.getDriverProfiles().stream().collect(Collectors.toMap(p -> p, p -> 1, Integer::sum)), equalTo(allProfiles.stream().collect(Collectors.toMap(p -> p, p -> 1, Integer::sum))) ); assertThat(onFailure.get(), equalTo(0)); @@ -129,11 +133,11 @@ public void testCancelOnFailure() { ); int successTasks = between(1, 50); int failedTasks = between(1, 100); - PlainActionFuture> rootListener = new PlainActionFuture<>(); + PlainActionFuture rootListener = new PlainActionFuture<>(); final AtomicInteger onFailure = new AtomicInteger(); try (var computeListener = new ComputeListener(threadPool, onFailure::incrementAndGet, rootListener)) { for (int i = 0; i < successTasks; i++) { - ActionListener> subListener = computeListener.acquireCompute(); + ActionListener subListener = computeListener.acquireCompute(); threadPool.schedule( ActionRunnable.wrap(subListener, l -> l.onResponse(randomProfiles())), TimeValue.timeValueNanos(between(0, 100)), @@ -162,11 +166,12 @@ public void testCancelOnFailure() { public void testCollectWarnings() throws Exception { List allProfiles = new ArrayList<>(); Map> allWarnings = new HashMap<>(); - ActionListener> rootListener = new ActionListener<>() { + ActionListener rootListener = new ActionListener<>() { @Override - public void onResponse(List result) { + public void onResponse(EsqlQueryResponse.Profile result) { assertThat( - result.stream().collect(Collectors.toMap(p -> p, p -> 1, Integer::sum)), + // TODO: test planner profiles here? + result.getDriverProfiles().stream().collect(Collectors.toMap(p -> p, p -> 1, Integer::sum)), equalTo(allProfiles.stream().collect(Collectors.toMap(p -> p, p -> 1, Integer::sum))) ); Map> responseHeaders = threadPool.getThreadContext() @@ -202,7 +207,7 @@ public void onFailure(Exception e) { ); } else { var resp = randomProfiles(); - allProfiles.addAll(resp); + allProfiles.addAll(resp.getDriverProfiles()); int numWarnings = randomIntBetween(1, 5); Map warnings = new HashMap<>(); for (int i = 0; i < numWarnings; i++) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSenderTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSenderTests.java index 92c77f7bd47c7..03a0aca56ddec 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSenderTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSenderTests.java @@ -35,6 +35,7 @@ import org.elasticsearch.threadpool.FixedExecutorBuilder; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.transport.TransportService; +import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.junit.After; import org.junit.Before; @@ -121,7 +122,7 @@ public void testOnePass() { Queue sent = ConcurrentCollections.newQueue(); var future = sendRequests(targetShards, randomBoolean(), -1, (node, shardIds, aliasFilters, listener) -> { sent.add(new NodeRequest(node, shardIds, aliasFilters)); - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); }); safeGet(future); assertThat(sent.size(), equalTo(2)); @@ -140,7 +141,7 @@ public void testMissingShards() { var targetShards = List.of(targetShard(shard1, node1), targetShard(shard3), targetShard(shard4, node2, node3)); var future = sendRequests(targetShards, true, -1, (node, shardIds, aliasFilters, listener) -> { assertThat(shard3, not(in(shardIds))); - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); }); ComputeResponse resp = safeGet(future); assertThat(resp.totalShards, equalTo(3)); @@ -171,7 +172,7 @@ public void testRetryThenSuccess() { if (node.equals(node4) && shardIds.contains(shard2)) { failures.put(shard2, new IOException("test")); } - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), failures))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, failures))); }); try { future.actionGet(1, TimeUnit.MINUTES); @@ -200,7 +201,7 @@ public void testRetryButFail() { if (shardIds.contains(shard5)) { failures.put(shard5, new IOException("test failure for shard5")); } - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), failures))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, failures))); }); var error = expectThrows(Exception.class, future::actionGet); assertNotNull(ExceptionsHelper.unwrap(error, IOException.class)); @@ -225,7 +226,7 @@ public void testDoNotRetryOnRequestLevelFailure() { if (node1.equals(node) && failed.compareAndSet(false, true)) { runWithDelay(() -> listener.onFailure(new IOException("test request level failure"), true)); } else { - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); } }); Exception exception = expectThrows(Exception.class, future::actionGet); @@ -245,7 +246,7 @@ public void testAllowPartialResults() { if (node1.equals(node) && failed.compareAndSet(false, true)) { runWithDelay(() -> listener.onFailure(new IOException("test request level failure"), true)); } else { - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); } }); ComputeResponse resp = safeGet(future); @@ -266,7 +267,7 @@ public void testNonFatalErrorIsRetriedOnAnotherShard() { if (Objects.equals(node1, node)) { runWithDelay(() -> listener.onFailure(new RuntimeException("test request level non fatal failure"), false)); } else { - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); } })); assertThat(response.totalShards, equalTo(1)); @@ -324,7 +325,7 @@ public void testLimitConcurrentNodes() { sent.add(new NodeRequest(node, shardIds, aliasFilters)); runWithDelay(() -> { concurrentRequests.decrementAndGet(); - listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of())); + listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of())); }); })); assertThat(sent.size(), equalTo(5)); @@ -347,7 +348,7 @@ public void testSkipNodes() { var response = safeGet(sendRequests(targetShards, randomBoolean(), 1, (node, shardIds, aliasFilters, listener) -> { runWithDelay(() -> { if (processed.incrementAndGet() == 1) { - listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of())); + listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of())); } else { listener.onSkip(); } @@ -369,7 +370,7 @@ public void testSkipRemovesPriorNonFatalErrors() { if (Objects.equals(node.getId(), node1.getId()) && shardIds.equals(List.of(shard1))) { listener.onFailure(new RuntimeException("test request level non fatal failure"), false); } else if (Objects.equals(node.getId(), node3.getId()) && shardIds.equals(List.of(shard2))) { - listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of())); + listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of())); } else if (Objects.equals(node.getId(), node2.getId()) && shardIds.equals(List.of(shard1))) { listener.onSkip(); } @@ -394,7 +395,7 @@ public void testQueryHotShardsFirst() { var sent = Collections.synchronizedList(new ArrayList()); safeGet(sendRequests(targetShards, randomBoolean(), -1, (node, shardIds, aliasFilters, listener) -> { sent.add(node.getId()); - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); })); assertThat(sent, equalTo(List.of("node-1", "node-2", "node-3", "node-4"))); } @@ -407,7 +408,7 @@ public void testQueryHotShardsFirstWhenIlmMovesShard() { var sent = ConcurrentCollections.newQueue(); safeGet(sendRequests(targetShards, randomBoolean(), -1, (node, shardIds, aliasFilters, listener) -> { sent.add(new NodeRequest(node, shardIds, aliasFilters)); - runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(List.of(), Map.of()))); + runWithDelay(() -> listener.onResponse(new DataNodeComputeResponse(EsqlQueryResponse.Profile.EMPTY, Map.of()))); })); assertThat(groupRequests(sent, 1), equalTo(Map.of(node1, List.of(shard1)))); assertThat(groupRequests(sent, 1), anyOf(equalTo(Map.of(node2, List.of(shard2))), equalTo(Map.of(warmNode2, List.of(shard2))))); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java index fac3495697da8..a68fd1ba9700e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java @@ -33,6 +33,7 @@ import org.elasticsearch.xpack.esql.parser.EsqlParser; import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; +import org.elasticsearch.xpack.esql.planner.PlannerProfile; import org.elasticsearch.xpack.esql.planner.mapper.Mapper; import java.io.IOException; @@ -290,16 +291,20 @@ static LogicalPlan parse(String query) { Map mapping = loadMapping("mapping-basic.json"); EsIndex test = new EsIndex("test", mapping, Map.of("test", IndexMode.STANDARD)); IndexResolution getIndexResult = IndexResolution.valid(test); - var logicalOptimizer = new LogicalPlanOptimizer(new LogicalOptimizerContext(TEST_CFG, FoldContext.small())); + var logicalOptimizer = new LogicalPlanOptimizer( + new LogicalOptimizerContext(TEST_CFG, FoldContext.small()), + new PlannerProfile(false, "") + ); var analyzer = new Analyzer( new AnalyzerContext(EsqlTestUtils.TEST_CFG, new EsqlFunctionRegistry(), getIndexResult, emptyPolicyResolution()), - TEST_VERIFIER + TEST_VERIFIER, + new PlannerProfile(false, "") ); return logicalOptimizer.optimize(analyzer.analyze(new EsqlParser().createStatement(query))); } static PhysicalPlan mapAndMaybeOptimize(LogicalPlan logicalPlan) { - var physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(TEST_CFG)); + var physicalPlanOptimizer = new PhysicalPlanOptimizer(new PhysicalOptimizerContext(TEST_CFG), new PlannerProfile(false, "")); var mapper = new Mapper(); var physical = mapper.map(logicalPlan); if (randomBoolean()) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/telemetry/PlanExecutorMetricsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/telemetry/PlanExecutorMetricsTests.java index 8f4b2ea757327..a290222fbd376 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/telemetry/PlanExecutorMetricsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/telemetry/PlanExecutorMetricsTests.java @@ -150,7 +150,7 @@ public void testFailedMetric() { return null; }).when(esqlClient).execute(eq(EsqlResolveFieldsAction.TYPE), any(), any()); - var planExecutor = new PlanExecutor(indexResolver, MeterRegistry.NOOP, new XPackLicenseState(() -> 0L), mockQueryLog()); + var planExecutor = new PlanExecutor(indexResolver, MeterRegistry.NOOP, new XPackLicenseState(() -> 0L), mockQueryLog(), ""); var enrichResolver = mockEnrichResolver(); var request = new EsqlQueryRequest();