flyingImer commented on code in PR #4115:
URL: https://github.com/apache/polaris/pull/4115#discussion_r3251528991


##########
polaris-core/src/main/java/org/apache/polaris/core/persistence/metrics/PolarisMetricsManager.java:
##########
@@ -75,4 +80,34 @@ default void writeCommitMetrics(
       @Nonnull PolarisCallContext callCtx, @Nonnull CommitMetricsRecord 
record) {
     callCtx.getMetaStore().writeCommitReport(record);
   }
+
+  default Page<ScanMetricsRecord> listScanMetrics(

Review Comment:
   IIUC these type-specific methods (`listScanMetrics`/`listCommitMetrics`) are 
interim, since the sync aligned on consolidating to a single table with a 
`metric_type` discriminator. Is the plan to collapse these into one polymorphic 
`listMetrics(...)` as part of the schema follow-up, or do you see them staying?



##########
polaris-core/src/main/java/org/apache/polaris/core/persistence/metrics/MetricsPersistence.java:
##########
@@ -73,4 +77,56 @@ default void writeScanReport(@Nonnull ScanMetricsRecord 
record) {
   default void writeCommitReport(@Nonnull CommitMetricsRecord record) {
     // No-op by default - backends that don't support metrics silently ignore
   }
+
+  /**
+   * Lists scan metrics reports for a given table, ordered by timestamp 
descending.
+   *
+   * <p>Default implementation returns an empty page. Override in 
implementations that support
+   * metrics reads.
+   *
+   * @param catalogId the internal catalog ID
+   * @param tableId the internal table entity ID
+   * @param snapshotId optional filter by snapshot ID
+   * @param principalName optional filter by principal name
+   * @param timestampFrom optional inclusive lower bound on timestamp (epoch 
ms)
+   * @param timestampTo optional exclusive upper bound on timestamp (epoch ms)
+   * @param pageToken pagination token
+   * @return a page of scan metrics records
+   */
+  default Page<ScanMetricsRecord> listScanReports(

Review Comment:
   Dmitri flagged the #4397 conflict above. Curious, are you tracking the 
metrics methods moving off `BasePersistence` as part of that effort, or 
separately? The sync agreed to extract metrics persistence as its own SPI, so I 
want to make sure we have a clear owner for that migration.



##########
persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcBasePersistenceImpl.java:
##########
@@ -1336,4 +1337,141 @@ private void writeCommitMetricsReport(@Nonnull 
ModelCommitMetricsReport report)
           String.format("Failed to write commit metrics report due to %s", 
e.getMessage()), e);
     }
   }
+
+  @Override
+  public Page<ScanMetricsRecord> listScanReports(
+      long catalogId,
+      long tableId,
+      @Nullable Long snapshotId,
+      @Nullable String principalName,
+      @Nullable Long timestampFrom,
+      @Nullable Long timestampTo,
+      @Nonnull PageToken pageToken) {
+    try {
+      PreparedQuery query =
+          buildMetricsQuery(
+              ModelScanMetricsReport.TABLE_NAME,
+              catalogId,
+              tableId,
+              snapshotId,
+              principalName,
+              timestampFrom,
+              timestampTo,
+              pageToken);
+      List<ModelScanMetricsReport> rows =
+          datasourceOperations.executeSelect(query, 
ModelScanMetricsReport.CONVERTER);
+      return Page.mapped(
+          pageToken,
+          rows.stream().map(ModelScanMetricsReport::toRecord),
+          Function.identity(),
+          MetricsReportToken::fromRecord);
+    } catch (SQLException e) {
+      throw new RuntimeException(
+          String.format("Failed to list scan metrics reports: %s", 
e.getMessage()), e);
+    }
+  }
+
+  @Override
+  public Page<CommitMetricsRecord> listCommitReports(
+      long catalogId,
+      long tableId,
+      @Nullable Long snapshotId,
+      @Nullable String principalName,
+      @Nullable Long timestampFrom,
+      @Nullable Long timestampTo,
+      @Nonnull PageToken pageToken) {
+    try {
+      PreparedQuery query =
+          buildMetricsQuery(
+              ModelCommitMetricsReport.TABLE_NAME,
+              catalogId,
+              tableId,
+              snapshotId,
+              principalName,
+              timestampFrom,
+              timestampTo,
+              pageToken);
+      List<ModelCommitMetricsReport> rows =
+          datasourceOperations.executeSelect(query, 
ModelCommitMetricsReport.CONVERTER);
+      return Page.mapped(
+          pageToken,
+          rows.stream().map(ModelCommitMetricsReport::toRecord),
+          Function.identity(),
+          MetricsReportToken::fromRecord);
+    } catch (SQLException e) {
+      throw new RuntimeException(
+          String.format("Failed to list commit metrics reports: %s", 
e.getMessage()), e);
+    }
+  }
+
+  /**
+   * Builds a parameterized SELECT query for a metrics report table using 
keyset pagination.
+   *
+   * <p>Rows are ordered by {@code (timestamp_ms DESC, report_id DESC)}. The 
cursor from {@link
+   * MetricsReportToken} drives the keyset predicate: {@code (timestamp_ms < 
cursorTs) OR
+   * (timestamp_ms = cursorTs AND report_id < cursorId)}.
+   */
+  private PreparedQuery buildMetricsQuery(

Review Comment:
   This shared query builder with a `tableName` param makes the eventual 
single-table migration pretty mechanical. Once we consolidate, the `WHERE 
metric_type = ?` filter replaces the table-name branching. Are you thinking 
that happens in the same PR as the schema change, or is the read API shape here 
meant to be stable across that migration?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to