From 4b994ebfbd291914670a6010ca54afbe88d2300a Mon Sep 17 00:00:00 2001 From: Karol Sobczak Date: Tue, 29 Nov 2022 18:08:27 +0100 Subject: [PATCH] Print Trino version to EXPLAIN ANALYZE VERBOSE Output of EXPLAIN ANALYZE VERBOSE is often shared for troubleshooting therefore it's useful to print Trino version there. ----------------------------------------------------------- Trino version: dev Fragment 1 [SINGLE] Output layout: [orderkey, custkey, count, sum_4, avg] Output partitioning: SINGLE [] --- .../main/java/io/trino/event/QueryMonitor.java | 9 +++++---- .../trino/operator/ExplainAnalyzeOperator.java | 18 +++++++++++++----- .../sql/planner/LocalExecutionPlanner.java | 9 +++++++-- .../sql/planner/planprinter/PlanPrinter.java | 14 +++++++++++--- .../io/trino/testing/LocalQueryRunner.java | 3 ++- .../java/io/trino/execution/TaskTestUtils.java | 4 +++- docs/src/main/sphinx/sql/explain-analyze.rst | 5 +++-- .../AbstractDistributedEngineOnlyQueries.java | 3 ++- 8 files changed, 46 insertions(+), 19 deletions(-) diff --git a/core/trino-main/src/main/java/io/trino/event/QueryMonitor.java b/core/trino-main/src/main/java/io/trino/event/QueryMonitor.java index 2bfcc7962901f..23ad8714f02e6 100644 --- a/core/trino-main/src/main/java/io/trino/event/QueryMonitor.java +++ b/core/trino-main/src/main/java/io/trino/event/QueryMonitor.java @@ -108,7 +108,7 @@ public class QueryMonitor private final JsonCodec executionFailureInfoCodec; private final JsonCodec statsAndCostsCodec; private final EventListenerManager eventListenerManager; - private final String serverVersion; + private final NodeVersion serverVersion; private final String serverAddress; private final String environment; private final SessionPropertyManager sessionPropertyManager; @@ -135,7 +135,7 @@ public QueryMonitor( this.operatorStatsCodec = requireNonNull(operatorStatsCodec, "operatorStatsCodec is null"); this.statsAndCostsCodec = requireNonNull(statsAndCostsCodec, "statsAndCostsCodec is null"); this.executionFailureInfoCodec = requireNonNull(executionFailureInfoCodec, "executionFailureInfoCodec is null"); - this.serverVersion = nodeVersion.toString(); + this.serverVersion = nodeVersion; this.serverAddress = nodeInfo.getExternalAddress(); this.environment = nodeInfo.getEnvironment(); this.sessionPropertyManager = requireNonNull(sessionPropertyManager, "sessionPropertyManager is null"); @@ -351,7 +351,7 @@ private QueryContext createQueryContext(SessionRepresentation session, Optional< mergeSessionAndCatalogProperties(session), session.getResourceEstimates(), serverAddress, - serverVersion, + serverVersion.toString(), environment, queryType, retryPolicy.toString()); @@ -366,7 +366,8 @@ private Optional createTextQueryPlan(QueryInfo queryInfo, Anonymizer ano queryInfo.getQueryStats(), new ValuePrinter(metadata, functionManager, queryInfo.getSession().toSession(sessionPropertyManager)), false, - anonymizer)); + anonymizer, + serverVersion)); } } catch (Exception e) { diff --git a/core/trino-main/src/main/java/io/trino/operator/ExplainAnalyzeOperator.java b/core/trino-main/src/main/java/io/trino/operator/ExplainAnalyzeOperator.java index 27f16a4f59228..b09b3b9938650 100644 --- a/core/trino-main/src/main/java/io/trino/operator/ExplainAnalyzeOperator.java +++ b/core/trino-main/src/main/java/io/trino/operator/ExplainAnalyzeOperator.java @@ -14,6 +14,7 @@ package io.trino.operator; import com.google.common.collect.ImmutableList; +import io.trino.client.NodeVersion; import io.trino.execution.QueryInfo; import io.trino.execution.QueryPerformanceFetcher; import io.trino.execution.StageId; @@ -44,6 +45,7 @@ public static class ExplainAnalyzeOperatorFactory private final Metadata metadata; private final FunctionManager functionManager; private final boolean verbose; + private final NodeVersion version; private boolean closed; public ExplainAnalyzeOperatorFactory( @@ -52,7 +54,8 @@ public ExplainAnalyzeOperatorFactory( QueryPerformanceFetcher queryPerformanceFetcher, Metadata metadata, FunctionManager functionManager, - boolean verbose) + boolean verbose, + NodeVersion version) { this.operatorId = operatorId; this.planNodeId = requireNonNull(planNodeId, "planNodeId is null"); @@ -60,6 +63,7 @@ public ExplainAnalyzeOperatorFactory( this.metadata = requireNonNull(metadata, "metadata is null"); this.functionManager = requireNonNull(functionManager, "functionManager is null"); this.verbose = verbose; + this.version = requireNonNull(version, "version is null"); } @Override @@ -67,7 +71,7 @@ public Operator createOperator(DriverContext driverContext) { checkState(!closed, "Factory is already closed"); OperatorContext operatorContext = driverContext.addOperatorContext(operatorId, planNodeId, ExplainAnalyzeOperator.class.getSimpleName()); - return new ExplainAnalyzeOperator(operatorContext, queryPerformanceFetcher, metadata, functionManager, verbose); + return new ExplainAnalyzeOperator(operatorContext, queryPerformanceFetcher, metadata, functionManager, verbose, version); } @Override @@ -79,7 +83,7 @@ public void noMoreOperators() @Override public OperatorFactory duplicate() { - return new ExplainAnalyzeOperatorFactory(operatorId, planNodeId, queryPerformanceFetcher, metadata, functionManager, verbose); + return new ExplainAnalyzeOperatorFactory(operatorId, planNodeId, queryPerformanceFetcher, metadata, functionManager, verbose, version); } } @@ -88,6 +92,7 @@ public OperatorFactory duplicate() private final Metadata metadata; private final FunctionManager functionManager; private final boolean verbose; + private final NodeVersion version; private boolean finishing; private boolean outputConsumed; @@ -96,13 +101,15 @@ public ExplainAnalyzeOperator( QueryPerformanceFetcher queryPerformanceFetcher, Metadata metadata, FunctionManager functionManager, - boolean verbose) + boolean verbose, + NodeVersion version) { this.operatorContext = requireNonNull(operatorContext, "operatorContext is null"); this.queryPerformanceFetcher = requireNonNull(queryPerformanceFetcher, "queryPerformanceFetcher is null"); this.metadata = requireNonNull(metadata, "metadata is null"); this.functionManager = requireNonNull(functionManager, "functionManager is null"); this.verbose = verbose; + this.version = requireNonNull(version, "version is null"); } @Override @@ -158,7 +165,8 @@ public Page getOutput() metadata, functionManager, operatorContext.getSession(), - verbose); + verbose, + version); BlockBuilder builder = VARCHAR.createBlockBuilder(null, 1); VARCHAR.writeString(builder, plan); diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/LocalExecutionPlanner.java b/core/trino-main/src/main/java/io/trino/sql/planner/LocalExecutionPlanner.java index edbc545eb5265..a8d4e4c30e597 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/LocalExecutionPlanner.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/LocalExecutionPlanner.java @@ -31,6 +31,7 @@ import io.airlift.units.DataSize; import io.trino.Session; import io.trino.SystemSessionProperties; +import io.trino.client.NodeVersion; import io.trino.collect.cache.NonEvictableCache; import io.trino.exchange.ExchangeManagerRegistry; import io.trino.execution.DynamicFilterConfig; @@ -423,6 +424,7 @@ public class LocalExecutionPlanner private final TableExecuteContextManager tableExecuteContextManager; private final ExchangeManagerRegistry exchangeManagerRegistry; private final PositionsAppenderFactory positionsAppenderFactory; + private final NodeVersion version; private final NonEvictableCache accumulatorFactoryCache = buildNonEvictableCache(CacheBuilder.newBuilder() .maximumSize(1000) @@ -456,7 +458,8 @@ public LocalExecutionPlanner( DynamicFilterConfig dynamicFilterConfig, BlockTypeOperators blockTypeOperators, TableExecuteContextManager tableExecuteContextManager, - ExchangeManagerRegistry exchangeManagerRegistry) + ExchangeManagerRegistry exchangeManagerRegistry, + NodeVersion version) { this.plannerContext = requireNonNull(plannerContext, "plannerContext is null"); this.metadata = plannerContext.getMetadata(); @@ -502,6 +505,7 @@ public LocalExecutionPlanner( this.tableExecuteContextManager = requireNonNull(tableExecuteContextManager, "tableExecuteContextManager is null"); this.exchangeManagerRegistry = requireNonNull(exchangeManagerRegistry, "exchangeManagerRegistry is null"); this.positionsAppenderFactory = new PositionsAppenderFactory(blockTypeOperators); + this.version = requireNonNull(version, "version is null"); } public LocalExecutionPlan plan( @@ -955,7 +959,8 @@ public PhysicalOperation visitExplainAnalyze(ExplainAnalyzeNode node, LocalExecu analyzeContext.getQueryPerformanceFetcher(), metadata, plannerContext.getFunctionManager(), - node.isVerbose()); + node.isVerbose(), + version); return new PhysicalOperation(operatorFactory, makeLayout(node), context, source); } diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/PlanPrinter.java b/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/PlanPrinter.java index 9a1ef2382feca..80128e1f57d22 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/PlanPrinter.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/planprinter/PlanPrinter.java @@ -23,6 +23,7 @@ import io.airlift.json.JsonCodec; import io.airlift.units.Duration; import io.trino.Session; +import io.trino.client.NodeVersion; import io.trino.cost.PlanCostEstimate; import io.trino.cost.PlanNodeStatsAndCostSummary; import io.trino.cost.PlanNodeStatsEstimate; @@ -383,14 +384,16 @@ public static String textDistributedPlan( Metadata metadata, FunctionManager functionManager, Session session, - boolean verbose) + boolean verbose, + NodeVersion version) { return textDistributedPlan( outputStageInfo, queryStats, new ValuePrinter(metadata, functionManager, session), verbose, - new NoOpAnonymizer()); + new NoOpAnonymizer(), + version); } public static String textDistributedPlan( @@ -398,7 +401,8 @@ public static String textDistributedPlan( QueryStats queryStats, ValuePrinter valuePrinter, boolean verbose, - Anonymizer anonymizer) + Anonymizer anonymizer, + NodeVersion version) { List allStages = getAllStages(Optional.of(outputStageInfo)); Map tableInfos = allStages.stream() @@ -418,6 +422,10 @@ public static String textDistributedPlan( .collect(toImmutableMap(DynamicFilterDomainStats::getDynamicFilterId, identity())); TypeProvider typeProvider = getTypeProvider(allFragments); + if (verbose) { + builder.append(format("Trino version: %s\n", version)); + } + for (StageInfo stageInfo : allStages) { builder.append(formatFragment( tableScanNode -> tableInfos.get(tableScanNode.getId()), diff --git a/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java b/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java index 05a3a8094749c..35a542c1f3584 100644 --- a/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java +++ b/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java @@ -962,7 +962,8 @@ private List createDrivers(Session session, Plan plan, OutputFactory out new DynamicFilterConfig(), blockTypeOperators, tableExecuteContextManager, - exchangeManagerRegistry); + exchangeManagerRegistry, + nodeManager.getCurrentNode().getNodeVersion()); // plan query LocalExecutionPlan localExecutionPlan = executionPlanner.plan( diff --git a/core/trino-main/src/test/java/io/trino/execution/TaskTestUtils.java b/core/trino-main/src/test/java/io/trino/execution/TaskTestUtils.java index 897bd188ae21c..3ce45e3a5c247 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TaskTestUtils.java +++ b/core/trino-main/src/test/java/io/trino/execution/TaskTestUtils.java @@ -16,6 +16,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.airlift.json.ObjectMapperProvider; +import io.trino.client.NodeVersion; import io.trino.connector.CatalogHandle; import io.trino.connector.CatalogServiceProvider; import io.trino.cost.StatsAndCosts; @@ -173,7 +174,8 @@ public static LocalExecutionPlanner createTestingPlanner() new DynamicFilterConfig(), blockTypeOperators, new TableExecuteContextManager(), - new ExchangeManagerRegistry()); + new ExchangeManagerRegistry(), + new NodeVersion("test")); } public static TaskInfo updateTask(SqlTask sqlTask, List splitAssignments, OutputBuffers outputBuffers) diff --git a/docs/src/main/sphinx/sql/explain-analyze.rst b/docs/src/main/sphinx/sql/explain-analyze.rst index 2373a57c3101a..4ee39b33086e0 100644 --- a/docs/src/main/sphinx/sql/explain-analyze.rst +++ b/docs/src/main/sphinx/sql/explain-analyze.rst @@ -87,8 +87,9 @@ relevant plan nodes). Such statistics are useful when one wants to detect data a orderdate := orderdate:date:REGULAR Input: 1500000 rows (18.17MB), Filtered: 45.46%, Physical Input: 4.51MB -When the ``VERBOSE`` option is used, some operators may report additional information. -For example, the window function operator will output the following:: +When the ``VERBOSE`` option is used, Trino version is reported as well as +some operators may report additional information. For example, the window +function operator will output the following:: EXPLAIN ANALYZE VERBOSE SELECT count(clerk) OVER() FROM orders WHERE orderdate > date '1995-01-01'; diff --git a/testing/trino-testing/src/main/java/io/trino/testing/AbstractDistributedEngineOnlyQueries.java b/testing/trino-testing/src/main/java/io/trino/testing/AbstractDistributedEngineOnlyQueries.java index 65ea909864020..59fe2ca5e3d52 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/AbstractDistributedEngineOnlyQueries.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/AbstractDistributedEngineOnlyQueries.java @@ -227,7 +227,8 @@ public void testExplainAnalyzeVerbose() "'CPU time distribution \\(s\\)' = \\{count=.*, p01=.*, p05=.*, p10=.*, p25=.*, p50=.*, p75=.*, p90=.*, p95=.*, p99=.*, min=.*, max=.*}", "'Scheduled time distribution \\(s\\)' = \\{count=.*, p01=.*, p05=.*, p10=.*, p25=.*, p50=.*, p75=.*, p90=.*, p95=.*, p99=.*, min=.*, max=.*}", "'Blocked time distribution \\(s\\)' = \\{count=.*, p01=.*, p05=.*, p10=.*, p25=.*, p50=.*, p75=.*, p90=.*, p95=.*, p99=.*, min=.*, max=.*}", - "Output buffer active time: .*, buffer utilization distribution \\(%\\): \\{p01=.*, p05=.*, p10=.*, p25=.*, p50=.*, p75=.*, p90=.*, p95=.*, p99=.*, max=.*}"); + "Output buffer active time: .*, buffer utilization distribution \\(%\\): \\{p01=.*, p05=.*, p10=.*, p25=.*, p50=.*, p75=.*, p90=.*, p95=.*, p99=.*, max=.*}", + "Trino version: .*"); } @Test