andygrove commented on code in PR #6429:
URL: https://github.com/apache/datafusion-comet/pull/6429#discussion_r4196850537


##########
spark/src/test/scala/org/apache/spark/sql/comet/CometTaskMetricsSuite.scala:
##########
@@ -54,6 +54,21 @@ class CometTaskMetricsSuite extends CometTestBase with 
AdaptiveSparkPlanHelper {
 
   import testImplicits._
 
+  test("S3 HTTP metrics are independent scan counters") {

Review Comment:
   This test mostly checks how `SQLMetric` behaves, since each 
`nativeScanMetrics` call creates fresh `sum` accumulators. It would keep 
passing even if the native names never reached the scan node. The existing 
`Comet native metrics: scan` test in `CometExecSuite` already lists every 
`scan_io_*` name on a real `CometNativeScanExec`. It also asserts that the 
`object_store_*` counters stay at zero for a local file. Could you add the 
three new names to that list, with `== 0` assertions next to the 
`object_store_*` ones, and drop this test? That checks the Spark side against 
an actual scan. The zero assertions also pin down the uninstrumented-backend 
behavior the docs describe.



##########
docs/source/user-guide/latest/metrics.md:
##########
@@ -205,6 +205,23 @@ metadata and remote totals instead of dividing by zero. 
Cancellation can leave l
 work outside the final metric snapshot; these counters are not a guarantee of 
complete network
 traffic accounting after cancellation.
 
+### S3 HTTP attempts and retries

Review Comment:
   Two things here could trip up a reader. The section calls 
`object_store_get_calls` "logical" GETs. But further down, the page uses 
"logical ranges" for the reader's ranges before coalescing, and 
`object_store_get_calls` counts GETs after coalescing. Also, the fact that only 
native S3 scans fill these counters is only implied by "An uninstrumented 
transport contributes no HTTP coverage". Someone looking at a GCS or Azure scan 
will see zeros and could conclude nothing was retried.
   
   Something along these lines might read more easily. The first sentence would 
replace the one above the table, and the paragraph would replace the one below 
it:
   
   > Native Parquet scans of S3 paths also count the HTTP attempts behind each 
GET, without changing the retry policy:
   
   > `scan_io_http_attempts` equals `scan_io_http_observed_gets` plus 
`scan_io_http_retries` once the scan finishes. Each scan counts only its own 
requests, even when scans share an S3 client. HEAD requests, credential 
requests, bucket-region lookups, and redirects or protocol retries handled 
inside reqwest are not counted. Only S3 scans fill these counters. GCS, Azure, 
HTTP(S), local and HDFS scans always report zero, which does not mean their 
requests were never retried. For an S3 scan, `scan_io_http_observed_gets` 
normally matches `scan_io_object_store_get_calls`.



##########
spark/src/main/scala/org/apache/spark/sql/comet/CometMetricNode.scala:
##########
@@ -405,6 +405,12 @@ object CometMetricNode {
         SQLMetrics.createSizeMetric(sc, "Serialized Parquet footer payload 
bytes read"),
       "scan_io_object_store_get_calls" ->
         SQLMetrics.createMetric(sc, "ObjectStore GET operations after range 
coalescing"),
+      "scan_io_http_observed_gets" ->

Review Comment:
   The description says the overhead hasn't been measured. `CometReadBenchmark 
--scan-metric-overhead` from #5453 measures exactly this per-task accumulator 
cost. But it still hard-codes the original nine names and the `9` in its cases, 
so after this PR it no longer covers every scan I/O accumulator. #5453 measured 
about 41 to 52 µs per task for those nine. That suggests these three add 
roughly 15 µs to every native scan task, including local and HDFS scans that 
can never report a nonzero value. Could you add the new names to that benchmark 
and post the numbers? Also, `http_attempts` always equals `http_observed_gets + 
http_retries`. Is the third counter worth its per-task cost, or would two be 
enough?



##########
native/core/src/parquet/objectstore/s3.rs:
##########
@@ -189,7 +189,8 @@ impl S3StoreTemplate {
     fn build(&self, credentials: S3Credentials) -> Result<AmazonS3, 
object_store::Error> {
         let builder = AmazonS3Builder::new()
             .with_url(self.url.clone())
-            .with_allow_http(true);
+            .with_allow_http(true)
+            .with_http_connector(super::http_metrics::ScanHttpConnector);

Review Comment:
   Is leaving Azure out deliberate? `objectstore::azure::create_store` builds 
its own `MicrosoftAzureBuilder`. object_store's Azure client also forwards 
`GetOptions` extensions into its GET requests the same way the S3 client does. 
So `.with_http_connector(ScanHttpConnector)` there looks like all it would 
need. GCS goes through `parse_url`, so it would need its own builder. If you'd 
rather keep this PR to S3, could you open an issue for Azure and GCS coverage?



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to