Improve verbosity (closes #4 closes #19)

This commit is contained in:
Maurus Decimus
2026-07-18 11:41:08 +02:00
parent 9fc9178b67
commit 846fc88f7e
13 changed files with 554 additions and 44 deletions
+42 -10
View File
@@ -7,18 +7,19 @@
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU8, AtomicU64, Ordering};
use std::time::Duration;
use std::time::{Duration, Instant};
use serde_json::Value;
use ureq::Agent;
use ureq::config::{Config, RedirectAuthHeaders};
use ureq::tls::{RootCerts, TlsConfig};
use ureq::{ResponseExt, http::Uri};
use crate::exchange_graph::error::GraphError;
use crate::exchange_graph::retry::{HttpClass, classify_http_status, is_throttled};
use crate::jmap::http::{RetryPolicy, retry_after_header};
use crate::jmap::http::{RetryPolicy, cross_host, retry_after_header};
use crate::jmap::retry::{self, RateLimitState};
use crate::logging::{LEVEL_BODIES, LEVEL_DEFAULT, LEVEL_PROGRESS, Logger};
use crate::logging::{HttpCall, LEVEL_BODIES, LEVEL_DEFAULT, LEVEL_PROGRESS, Logger};
const MAX_BODY: u64 = 256 * 1024 * 1024;
const LONG_RETRY_THRESHOLD: Duration = Duration::from_secs(10);
@@ -321,9 +322,12 @@ impl GraphClient {
for value in extra_prefer {
req = req.header("Prefer", *value);
}
let logger = self.logger();
let started = Instant::now();
match req.call() {
Ok(mut resp) => {
let status = resp.status().as_u16();
let final_uri = resp.get_uri().clone();
let retry_after = resp
.headers()
.get("retry-after")
@@ -335,18 +339,37 @@ impl GraphClient {
.and_then(|v| v.to_str().ok())
.map(str::to_owned);
match resp.body_mut().with_config().limit(MAX_BODY).read_to_vec() {
Ok(bytes) => Attempt::Ok {
status,
body: bytes,
retry_after,
content_type,
},
Ok(bytes) => {
warn_on_redirect(&logger, method, url, &final_uri);
logger.trace_http(&HttpCall {
proto: "Graph",
method,
url,
status,
elapsed: started.elapsed(),
note: None,
request: None,
request_type: None,
response: &bytes,
response_type: content_type.as_deref(),
});
Attempt::Ok {
status,
body: bytes,
retry_after,
content_type,
}
}
Err(e) => Attempt::Transport(GraphError::Transport(format!(
"reading response body: {e}"
))),
}
}
Err(e) => Attempt::Transport(map_ureq_error(e)),
Err(e) => {
let err = map_ureq_error(e);
logger.trace_http_error("Graph", method, url, &err.to_string(), started.elapsed());
Attempt::Transport(err)
}
}
}
@@ -387,6 +410,15 @@ struct RetryLog<'a> {
body: &'a [u8],
}
fn warn_on_redirect(logger: &Logger, method: &str, requested: &str, final_uri: &Uri) {
let landed = final_uri.to_string();
if cross_host(requested, &landed) {
logger.warn(&format!(
"{method} {requested} was redirected across hosts to {landed}; verify the Graph endpoint host is reachable directly without redirection"
));
}
}
fn map_ureq_error(err: ureq::Error) -> GraphError {
match err {
ureq::Error::Io(e) => GraphError::Transport(format!("io: {e}")),