You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/09/09 07:15:41 UTC

(opendal) branch xuanwo/asyncfile-trace-before created (now 5e86469cee)

This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a change to branch xuanwo/asyncfile-trace-before
in repository https://gitbox.apache.org/repos/asf/opendal.git


      at 5e86469cee Trace multipart request dispatch for isolated diagnosis

This branch includes the following new commits:

     new 5e86469cee Trace multipart request dispatch for isolated diagnosis

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(opendal) 01/01: Trace multipart request dispatch for isolated diagnosis

Posted by xu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a commit to branch xuanwo/asyncfile-trace-before
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit 5e86469cee95fdda4c887d43d4d9fa2106cc5fac
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Wed Sep 9 15:15:33 2026 +0800

    Trace multipart request dispatch for isolated diagnosis
---
 core/http-transports/reqwest/src/lib.rs | 71 +++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/core/http-transports/reqwest/src/lib.rs b/core/http-transports/reqwest/src/lib.rs
index 1d211ca04f..026da103af 100644
--- a/core/http-transports/reqwest/src/lib.rs
+++ b/core/http-transports/reqwest/src/lib.rs
@@ -72,8 +72,75 @@ impl ReqwestTransport {
     }
 }
 
+// Diagnostic-only request tracing; this module is not part of the proposed change.
+struct RequestTrace {
+    operation: &'static str,
+    part: usize,
+    size: usize,
+    status: u16,
+}
+
+static ACTIVE_PARTS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
+
+impl RequestTrace {
+    fn start(req: &Request<Buffer>) -> Option<Self> {
+        if std::env::var_os("ASYNCFILE_REQUEST_TRACE").is_none() {
+            return None;
+        }
+        let query = req.uri().query().unwrap_or_default();
+        let part = query
+            .split('&')
+            .find_map(|v| v.strip_prefix("partNumber="))
+            .and_then(|v| v.parse::<usize>().ok());
+        let operation = if req.method() == http::Method::PUT && part.is_some() {
+            "part"
+        } else if req.method() == http::Method::POST
+            && query.split('&').any(|v| v == "uploads" || v == "uploads=")
+        {
+            "create"
+        } else if req.method() == http::Method::POST && query.contains("uploadId=") {
+            "complete"
+        } else {
+            return None;
+        };
+        let trace = Self {
+            operation,
+            part: part.unwrap_or(0),
+            size: req.body().len(),
+            status: 0,
+        };
+        if operation == "part" {
+            ACTIVE_PARTS.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
+        }
+        trace.emit("begin");
+        Some(trace)
+    }
+
+    fn emit(&self, event: &str) {
+        let ns = std::time::SystemTime::now()
+            .duration_since(std::time::UNIX_EPOCH)
+            .unwrap()
+            .as_nanos();
+        let active = ACTIVE_PARTS.load(std::sync::atomic::Ordering::SeqCst);
+        eprintln!(
+            "HTTPTRACE\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
+            ns, event, self.operation, self.part, self.size, active, self.status
+        );
+    }
+}
+
+impl Drop for RequestTrace {
+    fn drop(&mut self) {
+        if self.operation == "part" {
+            ACTIVE_PARTS.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
+        }
+        self.emit("end");
+    }
+}
+
 impl HttpTransport for ReqwestTransport {
     async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
+        let mut request_trace = RequestTrace::start(&req);
         // Uri stores all string alike data in `Bytes` which means
         // the clone here is cheap.
         let uri = req.uri().clone();
@@ -119,6 +186,10 @@ impl HttpTransport for ReqwestTransport {
                 .set_source(err)
         })?;
 
+        if let Some(trace) = &mut request_trace {
+            trace.status = resp.status().as_u16();
+        }
+
         // Get content length from header so that we can check it.
         //
         // - If the request method is HEAD, we will ignore content length.