You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "adriangb (via GitHub)" <gi...@apache.org> on 2026/04/27 20:42:57 UTC

[PR] feat: surface ObjectStoreOperation on outbound HTTP requests (HTTP backend) [arrow-rs-object-store]

adriangb opened a new pull request, #703:
URL: https://github.com/apache/arrow-rs-object-store/pull/703

   ## Summary
   
   Adds `ObjectStoreOperation { kind, location, backend }` carried via `http::Request::extensions` so a wrapping `HttpService` (tower layer, reqwest middleware, etc.) can produce useful trace spans without sniffing URLs and headers.
   
   `http::Extensions` is in-process only, so this is invisible on the wire — no behavior change for remote servers.
   
   ## Scope
   
   This PR instruments only the **HTTP** (WebDAV) backend: get / head / put / delete / copy / list (5 sites). The mechanism is in place and proven end-to-end, but AWS, GCP, and Azure each have their own request-construction style and are best landed as separate follow-up PRs (one per backend) to keep review surface small.
   
   ## Mechanism
   
   - `OperationKind` enum (`Get | Head | Put | PutMultipart | Delete | Copy | List | ListWithDelimiter`), `#[non_exhaustive]` for forward compatibility.
   - `ObjectStoreOperation::new(kind, backend).with_location(path)` — also `#[non_exhaustive]`.
   - `OperationKind::as_str()` returns a snake_case identifier suitable for span attributes (`object_store.operation = \"get\"` etc.).
   - `HttpRequestBuilder::operation(op)` helper that calls `request.extensions_mut().insert(op)` so it composes with the existing `extensions(http::Extensions)` setter without clobbering user-provided extensions.
   
   ## One subtle ordering constraint
   
   `GetOptionsExt::with_get_options` calls `self.extensions(extensions)` which **overwrites** the entire `http::Extensions` (existing behavior — not changed by this PR). So `.operation(...)` must be called *after* `.with_get_options(...)` on the get path. This is documented inline at the call site. A follow-up could make `extensions()` additive instead of overwriting if reviewers prefer that.
   
   ## Reading on the receiving side
   
   \`\`\`rust
   async fn call(&self, req: HttpRequest) -> Result<HttpResponse, HttpError> {
       if let Some(op) = req.extensions().get::<ObjectStoreOperation>() {
           span.set_attribute(\"object_store.operation\", op.kind.as_str());
           if let Some(loc) = &op.location {
               span.set_attribute(\"object_store.path\", loc.as_ref());
           }
           span.set_attribute(\"object_store.backend\", op.backend);
       }
       self.inner.call(req).await
   }
   \`\`\`
   
   ## Independence
   
   One of three independent additions for better HTTP integration seams. The others are \`impl HttpService for ClientWithMiddleware\` and \`TowerHttpConnector\`. Each PR is self-contained; they can be reviewed in any order. A tracking issue will follow once all three drafts are CI-green.
   
   ## Test plan
   
   - [x] 3 new unit tests in \`http::client::tests\` using a recording \`HttpService\` wrapper to assert kind/location/backend per operation (get, put, delete)
   - [x] \`cargo test --features=aws,azure,gcp,http --lib\` (190 tests pass)
   - [x] \`cargo fmt --all -- --check\`
   - [x] \`cargo clippy --features=aws,azure,gcp,http --lib --tests -- -D warnings\`
   - [ ] CI green
   - [ ] Follow-ups: instrument AWS, GCP, Azure backends in separate PRs
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
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: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org