From 61d24b688e1080026d4609acae4bef7fc201aa14 Mon Sep 17 00:00:00 2001 From: Maciek <108873945+rozwader@users.noreply.github.com> Date: Sat, 10 Oct 2026 00:54:49 +0200 Subject: [PATCH] fix: added better errors for mclogs (#963) * fix: added better errors for mclogs * chore: added a warning when the log is shortened --- .changeset/better_mclogs_error.md | 5 +++ .../src/components/upload_mclogs.rs | 13 ++++++ packages/oneclient_app/src/view/app/debug.rs | 10 +++++ packages/oneclient_cluster/src/logs/mclogs.rs | 40 ++++++++++++++++++- packages/oneclient_cluster/src/logs/mod.rs | 1 + 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 .changeset/better_mclogs_error.md diff --git a/.changeset/better_mclogs_error.md b/.changeset/better_mclogs_error.md new file mode 100644 index 00000000..30227bb0 --- /dev/null +++ b/.changeset/better_mclogs_error.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +# Added better informations about errors from mclogs. \ No newline at end of file diff --git a/packages/oneclient_app/src/components/upload_mclogs.rs b/packages/oneclient_app/src/components/upload_mclogs.rs index 3a4d90e6..9682f2b7 100644 --- a/packages/oneclient_app/src/components/upload_mclogs.rs +++ b/packages/oneclient_app/src/components/upload_mclogs.rs @@ -31,6 +31,15 @@ impl Component for UploadToMclogs { } } +pub fn notify_log_truncated(dispatch: &crate::Actions) { + dispatch + .notify("Log was shortened") + .body("The log was too large for mclo.gs, so only its most recent part was uploaded.") + .info() + .icon(IconType::AlertTriangle) + .send(); +} + pub fn use_mclogs_feedback(upload: UseUploadLog) { let dispatch = use_dispatch(); let mut handled = use_state(|| match &*upload.peek().state() { @@ -68,6 +77,10 @@ pub fn use_mclogs_feedback(upload: UseUploadLog) { .info() .icon(IconType::LinkExternal01) .send(); + + if result.truncated { + notify_log_truncated(&dispatch); + } } Err(err) => { dispatch diff --git a/packages/oneclient_app/src/view/app/debug.rs b/packages/oneclient_app/src/view/app/debug.rs index 7625f2f4..09687335 100644 --- a/packages/oneclient_app/src/view/app/debug.rs +++ b/packages/oneclient_app/src/view/app/debug.rs @@ -221,6 +221,7 @@ impl Component for ToastController { let info = dispatch.clone(); let error = dispatch.clone(); let prog = dispatch.clone(); + let truncated = dispatch.clone(); let reset = dispatch; rect() @@ -273,6 +274,15 @@ impl Component for ToastController { .send(); }), ) + .child( + Button::new() + .secondary() + .child(Icon::new(IconType::AlertTriangle).size(16.)) + .text("mclo.gs Shortened") + .on_press(move |_| { + crate::components::upload_mclogs::notify_log_truncated(&truncated); + }), + ) .child( Button::new() .secondary() diff --git a/packages/oneclient_cluster/src/logs/mclogs.rs b/packages/oneclient_cluster/src/logs/mclogs.rs index a174cc69..692b6d9d 100644 --- a/packages/oneclient_cluster/src/logs/mclogs.rs +++ b/packages/oneclient_cluster/src/logs/mclogs.rs @@ -34,16 +34,25 @@ pub async fn upload_log_at( let path = ensure_allowed(path)?; let mut content = super::censor(&read_file_string(&path).await?).into_owned(); + let mut truncated = false; let line_count = content.lines().count(); if line_count > MAX_LINES { + truncated = true; content = content .lines() .skip(line_count - MAX_LINES) .collect::>() .join("\n"); } - if content.len() > MAX_BYTES { - let mut cut = content.len() - MAX_BYTES; + let mut encoded = form_encoded_len(content.as_bytes()); + if encoded > MAX_BYTES { + truncated = true; + let bytes = content.as_bytes(); + let mut cut = 0; + while encoded > MAX_BYTES && cut < bytes.len() { + encoded -= form_encoded_byte_len(bytes[cut]); + cut += 1; + } while cut < content.len() && !content.is_char_boundary(cut) { cut += 1; } @@ -58,7 +67,22 @@ pub async fn upload_log_at( .await .map_err(RequestError::ReqwestError)?; + let status = response.status(); let bytes = response.bytes().await.map_err(RequestError::ReqwestError)?; + + if !status.is_success() { + let reason = serde_json::from_slice::(&bytes) + .ok() + .and_then(|r| r.error) + .unwrap_or_else(|| status.to_string()); + tracing::warn!( + %status, + body = %String::from_utf8_lossy(&bytes[..bytes.len().min(512)]), + "mclogs upload rejected" + ); + return Err(LogsError::Upload(reason).into()); + } + let parsed: MclogsResponse = serde_json::from_slice(&bytes)?; if !parsed.success { @@ -76,5 +100,17 @@ pub async fn upload_log_at( id: parsed.id.unwrap_or_default(), url: parsed.url.unwrap_or_default(), raw: parsed.raw.unwrap_or_default(), + truncated, }) } + +fn form_encoded_byte_len(byte: u8) -> usize { + match byte { + b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'*' | b'-' | b'.' | b'_' | b' ' => 1, + _ => 3, + } +} + +fn form_encoded_len(bytes: &[u8]) -> usize { + bytes.iter().map(|&b| form_encoded_byte_len(b)).sum() +} diff --git a/packages/oneclient_cluster/src/logs/mod.rs b/packages/oneclient_cluster/src/logs/mod.rs index adff7df5..87f0e113 100644 --- a/packages/oneclient_cluster/src/logs/mod.rs +++ b/packages/oneclient_cluster/src/logs/mod.rs @@ -92,6 +92,7 @@ pub struct MclogsUploadResponse { pub id: String, pub url: String, pub raw: String, + pub truncated: bool, } #[cfg(test)]