fix: added better errors for mclogs (#963)

* fix: added better errors for mclogs

* chore: added a warning when the log is shortened
This commit is contained in:
Maciek 2026-10-10 00:54:49 +02:00 • committed by GitHub
parent d21c0dc22b
commit 61d24b688e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 67 additions and 2 deletions

View file

@ -0,0 +1,5 @@
---
default: patch
---
# Added better informations about errors from mclogs.

View file

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

View file

@ -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()

View file

@ -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::<Vec<_>>()
.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::<MclogsResponse>(&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()
}

View file

@ -92,6 +92,7 @@ pub struct MclogsUploadResponse {
pub id: String,
pub url: String,
pub raw: String,
pub truncated: bool,
}
#[cfg(test)]