Skip to content

Commit b12117e

Browse files
authored
Handle metrics for the same query but with different setups (#3531)
Planner metrics previously assumed that it was only reasonable to have a query once within a single block. Having setup can make this more complicated, so this changes the keys for the metrics to have the setup too. There were a couple unrelated cleanups along the way: 1. `markDirty()` was annotated `@Nullable`, but is `void` 2. `putMetrics` took `isDirectyMetrics`, but that parameter was never used, so I removed it.
1 parent a17539a commit b12117e

File tree

8 files changed

+181
-51
lines changed

8 files changed

+181
-51
lines changed

yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/YamlExecutionContext.java

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,10 @@ public synchronized PlannerMetricsProto.Info putMetrics(@Nonnull final String bl
179179
@Nonnull final String query,
180180
final int lineNumber,
181181
@Nonnull final PlannerMetricsProto.Info info,
182-
boolean isDirtyMetrics) {
183-
return actualMetricsMap.put(new QueryAndLocation(blockName, query, lineNumber), info);
182+
@Nonnull final List<String> setups) {
183+
return actualMetricsMap.put(new QueryAndLocation(blockName, query, lineNumber, setups), info);
184184
}
185185

186-
@Nullable
187186
@SuppressWarnings("UnusedReturnValue")
188187
public synchronized void markDirty() {
189188
this.isDirtyMetrics = true;
@@ -388,10 +387,7 @@ public void saveMetricsAsBinaryProto() {
388387
final var condensedMetricsMap = new LinkedHashMap<PlannerMetricsProto.Identifier, PlannerMetricsProto.Info>();
389388
for (final var entry : actualMetricsMap.entrySet()) {
390389
final var queryAndLocation = entry.getKey();
391-
final var identifier = PlannerMetricsProto.Identifier.newBuilder()
392-
.setBlockName(queryAndLocation.getBlockName())
393-
.setQuery(queryAndLocation.getQuery())
394-
.build();
390+
final var identifier = queryAndLocation.getIdentifier();
395391
if (condensedMetricsMap.containsKey(identifier)) {
396392
logger.warn("⚠️ Repeated query in block {} at line {}", queryAndLocation.getBlockName(),
397393
queryAndLocation.getLineNumber());
@@ -423,20 +419,25 @@ public void saveMetricsAsYaml() {
423419

424420
final var mmap = LinkedListMultimap.<String, Map<String, Object>>create();
425421
for (final var entry : actualMetricsMap.entrySet()) {
426-
final var identifier = entry.getKey();
422+
final var identifier = entry.getKey().getIdentifier();
427423
final var info = entry.getValue();
428424
final var countersAndTimers = info.getCountersAndTimers();
429-
final var infoMap =
430-
ImmutableMap.<String, Object>of("query", identifier.getQuery(),
431-
"explain", info.getExplain(),
432-
"task_count", countersAndTimers.getTaskCount(),
433-
"task_total_time_ms", TimeUnit.NANOSECONDS.toMillis(countersAndTimers.getTaskTotalTimeNs()),
434-
"transform_count", countersAndTimers.getTransformCount(),
435-
"transform_time_ms", TimeUnit.NANOSECONDS.toMillis(countersAndTimers.getTransformTimeNs()),
436-
"transform_yield_count", countersAndTimers.getTransformYieldCount(),
437-
"insert_time_ms", TimeUnit.NANOSECONDS.toMillis(countersAndTimers.getInsertTimeNs()),
438-
"insert_new_count", countersAndTimers.getInsertNewCount(),
439-
"insert_reused_count", countersAndTimers.getInsertReusedCount());
425+
final var infoMap = new LinkedHashMap<String, Object>();
426+
infoMap.put("query", identifier.getQuery());
427+
// only include setup if it is non-empty, in part so that the PR that adds setup doesn't change every
428+
// metric in the yaml files
429+
if (identifier.getSetupsCount() > 0) {
430+
infoMap.put("setup", identifier.getSetupsList());
431+
}
432+
infoMap.put("explain", info.getExplain());
433+
infoMap.put("task_count", countersAndTimers.getTaskCount());
434+
infoMap.put("task_total_time_ms", TimeUnit.NANOSECONDS.toMillis(countersAndTimers.getTaskTotalTimeNs()));
435+
infoMap.put("transform_count", countersAndTimers.getTransformCount());
436+
infoMap.put("transform_time_ms", TimeUnit.NANOSECONDS.toMillis(countersAndTimers.getTransformTimeNs()));
437+
infoMap.put("transform_yield_count", countersAndTimers.getTransformYieldCount());
438+
infoMap.put("insert_time_ms", TimeUnit.NANOSECONDS.toMillis(countersAndTimers.getInsertTimeNs()));
439+
infoMap.put("insert_new_count", countersAndTimers.getInsertNewCount());
440+
infoMap.put("insert_reused_count", countersAndTimers.getInsertReusedCount());
440441
mmap.put(identifier.getBlockName(), infoMap);
441442
}
442443

@@ -513,23 +514,31 @@ private static String baseName(@Nonnull final String resourcePath) {
513514

514515
private static class QueryAndLocation {
515516
@Nonnull
516-
private final String blockName;
517-
private final String query;
517+
private final PlannerMetricsProto.Identifier identifier;
518518
private final int lineNumber;
519519

520-
public QueryAndLocation(@Nonnull final String blockName, final String query, final int lineNumber) {
521-
this.blockName = blockName;
522-
this.query = query;
520+
public QueryAndLocation(@Nonnull final String blockName, final String query, final int lineNumber,
521+
@Nonnull List<String> setups) {
522+
identifier = PlannerMetricsProto.Identifier.newBuilder()
523+
.setBlockName(blockName)
524+
.setQuery(query)
525+
.addAllSetups(setups)
526+
.build();
523527
this.lineNumber = lineNumber;
524528
}
525529

530+
@Nonnull
531+
public PlannerMetricsProto.Identifier getIdentifier() {
532+
return identifier;
533+
}
534+
526535
@Nonnull
527536
public String getBlockName() {
528-
return blockName;
537+
return identifier.getBlockName();
529538
}
530539

531540
public String getQuery() {
532-
return query;
541+
return identifier.getQuery();
533542
}
534543

535544
public int getLineNumber() {
@@ -542,12 +551,12 @@ public boolean equals(final Object o) {
542551
return false;
543552
}
544553
final QueryAndLocation that = (QueryAndLocation)o;
545-
return lineNumber == that.lineNumber && Objects.equals(blockName, that.blockName) && Objects.equals(query, that.query);
554+
return lineNumber == that.lineNumber && Objects.equals(identifier, that.identifier);
546555
}
547556

548557
@Override
549558
public int hashCode() {
550-
return Objects.hash(blockName, query, lineNumber);
559+
return Objects.hash(identifier, lineNumber);
551560
}
552561
}
553562

yaml-tests/src/main/java/com/apple/foundationdb/relational/yamltests/command/QueryConfig.java

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ String decorateQuery(@Nonnull String query) {
134134
}
135135

136136
final void checkResult(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription,
137-
@Nonnull YamlConnection connection) {
137+
@Nonnull YamlConnection connection, @Nonnull List<String> setups) {
138138
try {
139-
checkResultInternal(currentQuery, actual, queryDescription);
139+
checkResultInternal(currentQuery, actual, queryDescription, setups);
140140
} catch (AssertionFailedError e) {
141141
throw executionContext.wrapContext(e,
142142
() -> "‼️Check result failed in config at line " + getLineNumber() + " against connection for versions " + connection.getVersions(),
@@ -163,7 +163,7 @@ final void checkError(@Nonnull SQLException actual, @Nonnull String queryDescrip
163163
}
164164

165165
abstract void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
166-
@Nonnull String queryDescription) throws SQLException;
166+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException;
167167

168168
void checkErrorInternal(@Nonnull SQLException e, @Nonnull String queryDescription) throws SQLException {
169169
final var diffMessage = String.format(Locale.ROOT, "‼️ statement failed with the following error at line %s:%n" +
@@ -181,7 +181,8 @@ private static QueryConfig getCheckResultConfig(boolean isExpectedOrdered, @Null
181181
return new QueryConfig(configName, value, lineNumber, executionContext) {
182182

183183
@Override
184-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
184+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
185+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
185186
logger.debug("⛳️ Matching results of query '{}'", queryDescription);
186187
try (RelationalResultSet resultSet = (RelationalResultSet)actual) {
187188
final var matchResult = Matchers.matchResultSet(getVal(), resultSet, isExpectedOrdered);
@@ -220,7 +221,8 @@ String decorateQuery(@Nonnull String query) {
220221

221222
@SuppressWarnings({"PMD.CloseResource", "PMD.EmptyWhileStmt"}) // lifetime of autocloseable resource persists beyond method
222223
@Override
223-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
224+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
225+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
224226
logger.debug("⛳️ Matching plan for query '{}'", queryDescription);
225227
final var resultSet = (RelationalResultSet) actual;
226228
resultSet.next();
@@ -231,6 +233,7 @@ void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @
231233
final var identifier = PlannerMetricsProto.Identifier.newBuilder()
232234
.setBlockName(blockName)
233235
.setQuery(currentQuery)
236+
.addAllSetups(setups)
234237
.build();
235238
final var expectedPlannerMetricsInfo = metricsMap.get(identifier);
236239

@@ -302,7 +305,7 @@ void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @
302305
.setInsertReusedCount(actualPlannerMetrics.getLong(8)))
303306
.build();
304307
if (expectedPlannerMetricsInfo == null) {
305-
executionContext.putMetrics(blockName, currentQuery, lineNumber, actualInfo, true);
308+
executionContext.putMetrics(blockName, currentQuery, lineNumber, actualInfo, setups);
306309
executionContext.markDirty();
307310
logger.debug("⭐️ Successfully inserted new planner metrics at line {}", getLineNumber());
308311
} else {
@@ -331,7 +334,7 @@ void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @
331334
actualCountersAndTimers,
332335
metricsDescriptor.findFieldByName("insert_reused_count"),
333336
lineNumber);
334-
executionContext.putMetrics(blockName, currentQuery, lineNumber, actualInfo, isDifferent);
337+
executionContext.putMetrics(blockName, currentQuery, lineNumber, actualInfo, setups);
335338
if (isDifferent) {
336339
if (executionContext.shouldCorrectMetrics()) {
337340
executionContext.markDirty();
@@ -364,7 +367,8 @@ private static QueryConfig getCheckErrorConfig(@Nullable Object value, int lineN
364367
return new QueryConfig(QUERY_CONFIG_ERROR, value, lineNumber, executionContext) {
365368

366369
@Override
367-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
370+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
371+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
368372
Matchers.ResultSetPrettyPrinter resultSetPrettyPrinter = new Matchers.ResultSetPrettyPrinter();
369373
if (actual instanceof ErrorCapturingResultSet) {
370374
Matchers.printRemaining((ErrorCapturingResultSet) actual, resultSetPrettyPrinter);
@@ -406,7 +410,8 @@ private static QueryConfig getCheckCountConfig(@Nullable Object value, int lineN
406410
return new QueryConfig(QUERY_CONFIG_COUNT, value, lineNumber, executionContext) {
407411

408412
@Override
409-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) {
413+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
414+
@Nonnull String queryDescription, @Nonnull List<String> setups) {
410415
logger.debug("⛳️ Matching count of update query '{}'", queryDescription);
411416
if (!Matchers.matches(getVal(), actual)) {
412417
reportTestFailure(String.format(Locale.ROOT, "‼️ Expected count value %d, but got %d at line %d",
@@ -428,7 +433,8 @@ String decorateQuery(@Nonnull String query) {
428433

429434
@SuppressWarnings("PMD.CloseResource") // lifetime of autocloseable persists beyond method
430435
@Override
431-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
436+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
437+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
432438
logger.debug("⛳️ Matching plan hash of query '{}'", queryDescription);
433439
final var resultSet = (RelationalResultSet) actual;
434440
resultSet.next();
@@ -445,7 +451,8 @@ public static QueryConfig getNoCheckConfig(int lineNumber, @Nonnull YamlExecutio
445451
return new QueryConfig(QUERY_CONFIG_NO_CHECKS, null, lineNumber, executionContext) {
446452
@SuppressWarnings("PMD.CloseResource") // lifetime of autocloseable persists beyond method
447453
@Override
448-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
454+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
455+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
449456
if (actual instanceof RelationalResultSet) {
450457
final var resultSet = (RelationalResultSet) actual;
451458
// slurp
@@ -462,7 +469,8 @@ void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @
462469
private static QueryConfig getMaxRowConfig(@Nonnull Object value, int lineNumber, @Nonnull YamlExecutionContext executionContext) {
463470
return new QueryConfig(QUERY_CONFIG_MAX_ROWS, value, lineNumber, executionContext) {
464471
@Override
465-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
472+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
473+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
466474
Assert.failUnchecked("No results to check on a maxRow config");
467475
}
468476
};
@@ -472,7 +480,7 @@ private static QueryConfig getSetupConfig(final Object value, final int lineNumb
472480
return new QueryConfig(QUERY_CONFIG_SETUP, value, lineNumber, executionContext) {
473481
@Override
474482
void checkResultInternal(@Nonnull final String currentQuery, @Nonnull final Object actual,
475-
@Nonnull final String queryDescription) throws SQLException {
483+
@Nonnull final String queryDescription, @Nonnull List<String> setups) throws SQLException {
476484
Assert.failUnchecked("No results to check on a setup config");
477485
}
478486
};
@@ -482,7 +490,8 @@ private static QueryConfig getDebuggerConfig(@Nonnull Object value, int lineNumb
482490
return new QueryConfig(QUERY_CONFIG_DEBUGGER, DebuggerImplementation.valueOf(((String)value).toUpperCase(Locale.ROOT)),
483491
lineNumber, executionContext) {
484492
@Override
485-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
493+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
494+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
486495
Assert.failUnchecked("No results to check on a debugger config");
487496
}
488497
};
@@ -496,7 +505,8 @@ public static QueryConfig getSupportedVersionConfig(Object rawVersion, final int
496505
}
497506
return new QueryConfig(QUERY_CONFIG_SUPPORTED_VERSION, rawVersion, lineNumber, executionContext) {
498507
@Override
499-
void checkResultInternal(@Nonnull final String currentQuery, @Nonnull final Object actual, @Nonnull final String queryDescription) throws SQLException {
508+
void checkResultInternal(@Nonnull final String currentQuery, @Nonnull final Object actual,
509+
@Nonnull final String queryDescription, @Nonnull final List<String> setups) throws SQLException {
500510
// Nothing to do, this query is supported
501511
// SupportedVersion configs are not executed
502512
Assertions.fail("Supported version configs are not meant to be executed.");
@@ -516,7 +526,8 @@ public static QueryConfig getNoOpConfig(int lineNumber, @Nonnull YamlExecutionCo
516526
return new QueryConfig(QUERY_CONFIG_NO_OP, null, lineNumber, executionContext) {
517527
@SuppressWarnings("PMD.CloseResource") // lifetime of autocloseable persists beyond method
518528
@Override
519-
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual, @Nonnull String queryDescription) throws SQLException {
529+
void checkResultInternal(@Nonnull String currentQuery, @Nonnull Object actual,
530+
@Nonnull String queryDescription, @Nonnull List<String> setups) throws SQLException {
520531
// This should not be executed
521532
Assertions.fail("NoOp Config should not be executed");
522533
}
@@ -647,7 +658,7 @@ public SkipConfig(final String configMap, final Object value, final int lineNumb
647658

648659
@Override
649660
void checkResultInternal(@Nonnull final String currentQuery, @Nonnull final Object actual,
650-
@Nonnull final String queryDescription) throws SQLException {
661+
@Nonnull final String queryDescription, @Nonnull final List<String> setups) throws SQLException {
651662
Assertions.fail("Skipped config should not be executed: Line: " + getLineNumber() + " " + message);
652663
}
653664

@@ -673,7 +684,8 @@ public boolean shouldExecute(YamlConnection connection) {
673684
}
674685

675686
@Override
676-
void checkResultInternal(@Nonnull final String currentQuery, @Nonnull final Object actual, @Nonnull final String queryDescription) throws SQLException {
687+
void checkResultInternal(@Nonnull final String currentQuery, @Nonnull final Object actual,
688+
@Nonnull final String queryDescription, @Nonnull final List<String> setups) throws SQLException {
677689
Assertions.fail("Check version config should not be executed: Line: " + getLineNumber());
678690
}
679691

0 commit comments

Comments
 (0)