public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client
@ 2024-06-18 14:21 Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox v4 1/4] CLI: print fatal errors including causes Gabriel Goller
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Gabriel Goller @ 2024-06-18 14:21 UTC (permalink / raw)
  To: pbs-devel

Instead of using format_err! and format! to create error messages, we
want to move to anyhow::Context and add information to already
existing anyhow::Error's. 
Before we start to gradually phase out the format! error calls, we
need to print the whole context + error, because the default 
anyhow::Error Display implementation doesn't print the actual error.

This series starts with the proxmox-backup-client and includes a patch
from Fabian that introduces pretty-printing of errors (including 
the context) and some other high-level stuff from me. The scope 
is not to remove every format call and add a context everywhere, 
but to enable this change in the future.

v4:
 - inlined eprintln's arguments
 - removed readme.rst (to be moved to the Developer Documentation)

v3: 
 - rebased
 - applied Max's fixup

v2:
 - moved explanation to readme.rst file
 - remove unwrap, use take() in `if let`
 - cargo fmt

proxmox:

Gabriel Goller (1):
  CLI: print fatal errors including causes

 proxmox-router/src/cli/command.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)


proxmox-backup:

Gabriel Goller (3):
  pxar: remove ArchiveError
  pxar: add UniqueContext helper
  pxar: use anyhow::Error in PxarBackupStream

 pbs-client/src/pxar/create.rs        | 48 +++++++++++++---------------
 pbs-client/src/pxar_backup_stream.rs | 18 +++++------
 2 files changed, 32 insertions(+), 34 deletions(-)


Summary over all repositories:
  3 files changed, 34 insertions(+), 36 deletions(-)

-- 
Generated by git-murpp 0.5.0


_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pbs-devel] [PATCH proxmox v4 1/4] CLI: print fatal errors including causes
  2024-06-18 14:21 [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Gabriel Goller
@ 2024-06-18 14:22 ` Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 2/4] pxar: remove ArchiveError Gabriel Goller
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gabriel Goller @ 2024-06-18 14:22 UTC (permalink / raw)
  To: pbs-devel

as a first step of improving our error handling story, printing context
and causes if the error contains them.

The downside to adding context is that the default Display implementation
will *just* print the context, which hides the root cause. This is why
we print the errors using the pretty-print formatter in this change.

Originally-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 proxmox-router/src/cli/command.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/proxmox-router/src/cli/command.rs b/proxmox-router/src/cli/command.rs
index 7a26ffb9..a97c9d48 100644
--- a/proxmox-router/src/cli/command.rs
+++ b/proxmox-router/src/cli/command.rs
@@ -83,7 +83,7 @@ async fn handle_simple_command_future(
             }
         }
         Err(err) => {
-            eprintln!("Error: {}", err);
+            eprintln!("Error: {err:?}");
             return Err(err);
         }
     }
@@ -135,7 +135,7 @@ fn handle_simple_command(
             }
         }
         Err(err) => {
-            eprintln!("Error: {}", err);
+            eprintln!("Error: {err:?}");
             return Err(err);
         }
     }
-- 
2.43.0



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v4 2/4] pxar: remove ArchiveError
  2024-06-18 14:21 [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox v4 1/4] CLI: print fatal errors including causes Gabriel Goller
@ 2024-06-18 14:22 ` Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 3/4] pxar: add UniqueContext helper Gabriel Goller
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gabriel Goller @ 2024-06-18 14:22 UTC (permalink / raw)
  To: pbs-devel

The sole purpose of the ArchiveError was to add the file-path to the
error. Using anyhow::Error we can add this information using the context
and don't need this struct anymore.

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 pbs-client/src/pxar/create.rs | 25 +------------------------
 1 file changed, 1 insertion(+), 24 deletions(-)

diff --git a/pbs-client/src/pxar/create.rs b/pbs-client/src/pxar/create.rs
index 9a41bf3e..c9a8c744 100644
--- a/pbs-client/src/pxar/create.rs
+++ b/pbs-client/src/pxar/create.rs
@@ -1,6 +1,5 @@
 use std::collections::{HashMap, HashSet};
 use std::ffi::{CStr, CString, OsStr};
-use std::fmt;
 use std::io::{self, Read};
 use std::mem::size_of;
 use std::ops::Range;
@@ -117,25 +116,11 @@ pub fn is_virtual_file_system(magic: i64) -> bool {
         SYSFS_MAGIC)
 }
 
-#[derive(Debug)]
-struct ArchiveError {
-    path: PathBuf,
-    error: Error,
 }
 
-impl ArchiveError {
-    fn new(path: PathBuf, error: Error) -> Self {
-        Self { path, error }
     }
 }
 
-impl std::error::Error for ArchiveError {}
-
-impl fmt::Display for ArchiveError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "error at {:?}: {}", self.path, self.error)
-    }
-}
 
 #[derive(Eq, PartialEq, Hash)]
 pub(crate) struct HardLinkInfo {
@@ -353,14 +338,6 @@ impl Archiver {
         self.feature_flags & self.fs_feature_flags
     }
 
-    fn wrap_err(&self, err: Error) -> Error {
-        if err.downcast_ref::<ArchiveError>().is_some() {
-            err
-        } else {
-            ArchiveError::new(self.path.clone(), err).into()
-        }
-    }
-
     fn archive_dir_contents<'a, T: SeqWrite + Send>(
         &'a mut self,
         encoder: &'a mut Encoder<'_, T>,
@@ -409,7 +386,7 @@ impl Archiver {
                     &file_entry.stat,
                 )
                 .await
-                .map_err(|err| self.wrap_err(err))?;
+                .context(format!("error at {:?}", self.path))?;
             }
             self.path = old_path;
             self.entry_counter = entry_counter;
-- 
2.43.0



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v4 3/4] pxar: add UniqueContext helper
  2024-06-18 14:21 [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox v4 1/4] CLI: print fatal errors including causes Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 2/4] pxar: remove ArchiveError Gabriel Goller
@ 2024-06-18 14:22 ` Gabriel Goller
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 4/4] pxar: use anyhow::Error in PxarBackupStream Gabriel Goller
  2024-06-19  9:36 ` [pbs-devel] applied-series: [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Wolfgang Bumiller
  4 siblings, 0 replies; 6+ messages in thread
From: Gabriel Goller @ 2024-06-18 14:22 UTC (permalink / raw)
  To: pbs-devel

To create a pxar archive, we recursively traverse the target folder.
If there is an error further down and we add a context using anyhow,
the context will be duplicated and we get an output like:

> Error: error at "xattr/xattr.txt": error at "xattr/xattr.txt": E2BIG [skip]

This is obviously not optimal, so in recursive contexts we can use the
UniqueContext, which quickly checks the context from the last item in
the error chain and only adds it if it is unique.

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 pbs-client/src/pxar/create.rs | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/pbs-client/src/pxar/create.rs b/pbs-client/src/pxar/create.rs
index c9a8c744..89a5b5ab 100644
--- a/pbs-client/src/pxar/create.rs
+++ b/pbs-client/src/pxar/create.rs
@@ -1,5 +1,6 @@
 use std::collections::{HashMap, HashSet};
 use std::ffi::{CStr, CString, OsStr};
+use std::fmt::Display;
 use std::io::{self, Read};
 use std::mem::size_of;
 use std::ops::Range;
@@ -116,12 +117,32 @@ pub fn is_virtual_file_system(magic: i64) -> bool {
         SYSFS_MAGIC)
 }
 
+trait UniqueContext<T> {
+    fn unique_context<S>(self, context: S) -> Result<T, anyhow::Error>
+    where
+        S: Display + Send + Sync + 'static;
 }
 
+impl<T> UniqueContext<T> for Result<T, anyhow::Error> {
+    fn unique_context<S>(self, context: S) -> Result<T, anyhow::Error>
+    where
+        S: Display + Send + Sync + 'static,
+    {
+        match self {
+            Ok(ok) => Ok(ok),
+            Err(err) => {
+                let last_error = err.chain().next();
+                if let Some(e) = last_error {
+                    if e.to_string() == context.to_string() {
+                        return Err(err);
+                    }
+                }
+                Err(err.context(context))
+            }
+        }
     }
 }
 
-
 #[derive(Eq, PartialEq, Hash)]
 pub(crate) struct HardLinkInfo {
     st_dev: u64,
@@ -386,7 +407,7 @@ impl Archiver {
                     &file_entry.stat,
                 )
                 .await
-                .context(format!("error at {:?}", self.path))?;
+                .unique_context(format!("error at {:?}", self.path))?;
             }
             self.path = old_path;
             self.entry_counter = entry_counter;
-- 
2.43.0



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v4 4/4] pxar: use anyhow::Error in PxarBackupStream
  2024-06-18 14:21 [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Gabriel Goller
                   ` (2 preceding siblings ...)
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 3/4] pxar: add UniqueContext helper Gabriel Goller
@ 2024-06-18 14:22 ` Gabriel Goller
  2024-06-19  9:36 ` [pbs-devel] applied-series: [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Wolfgang Bumiller
  4 siblings, 0 replies; 6+ messages in thread
From: Gabriel Goller @ 2024-06-18 14:22 UTC (permalink / raw)
  To: pbs-devel

Instead of storing the error as a string in the PxarBackupStream, we
store it as an anyhow::Error. As we can't clone an anyhow::Error, we take
it out from the mutex and return it. This won't change anything as
the consumation of the stream will stop if it gets a Some(Err(..)).

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 pbs-client/src/pxar_backup_stream.rs | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/pbs-client/src/pxar_backup_stream.rs b/pbs-client/src/pxar_backup_stream.rs
index cdbcdfec..4370da6c 100644
--- a/pbs-client/src/pxar_backup_stream.rs
+++ b/pbs-client/src/pxar_backup_stream.rs
@@ -5,7 +5,7 @@ use std::pin::Pin;
 use std::sync::{mpsc, Arc, Mutex};
 use std::task::{Context, Poll};
 
-use anyhow::{format_err, Error};
+use anyhow::Error;
 use futures::future::{AbortHandle, Abortable};
 use futures::stream::Stream;
 use nix::dir::Dir;
@@ -29,7 +29,7 @@ pub struct PxarBackupStream {
     rx: Option<std::sync::mpsc::Receiver<Result<Vec<u8>, Error>>>,
     pub suggested_boundaries: Option<std::sync::mpsc::Receiver<u64>>,
     handle: Option<AbortHandle>,
-    error: Arc<Mutex<Option<String>>>,
+    error: Arc<Mutex<Option<Error>>>,
 }
 
 impl Drop for PxarBackupStream {
@@ -98,7 +98,7 @@ impl PxarBackupStream {
             .await
             {
                 let mut error = error2.lock().unwrap();
-                *error = Some(err.to_string());
+                *error = Some(err);
             }
         };
 
@@ -142,18 +142,18 @@ impl Stream for PxarBackupStream {
     fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
         {
             // limit lock scope
-            let error = self.error.lock().unwrap();
-            if let Some(ref msg) = *error {
-                return Poll::Ready(Some(Err(format_err!("{}", msg))));
+            let mut error = self.error.lock().unwrap();
+            if let Some(err) = error.take() {
+                return Poll::Ready(Some(Err(err)));
             }
         }
 
         match proxmox_async::runtime::block_in_place(|| self.rx.as_ref().unwrap().recv()) {
             Ok(data) => Poll::Ready(Some(data)),
             Err(_) => {
-                let error = self.error.lock().unwrap();
-                if let Some(ref msg) = *error {
-                    return Poll::Ready(Some(Err(format_err!("{}", msg))));
+                let mut error = self.error.lock().unwrap();
+                if let Some(err) = error.take() {
+                    return Poll::Ready(Some(Err(err)));
                 }
                 Poll::Ready(None) // channel closed, no error
             }
-- 
2.43.0



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [pbs-devel] applied-series: [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client
  2024-06-18 14:21 [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Gabriel Goller
                   ` (3 preceding siblings ...)
  2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 4/4] pxar: use anyhow::Error in PxarBackupStream Gabriel Goller
@ 2024-06-19  9:36 ` Wolfgang Bumiller
  4 siblings, 0 replies; 6+ messages in thread
From: Wolfgang Bumiller @ 2024-06-19  9:36 UTC (permalink / raw)
  To: Gabriel Goller; +Cc: pbs-devel

applied, thanks


_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel




^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-06-19  9:36 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-18 14:21 [pbs-devel] [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Gabriel Goller
2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox v4 1/4] CLI: print fatal errors including causes Gabriel Goller
2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 2/4] pxar: remove ArchiveError Gabriel Goller
2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 3/4] pxar: add UniqueContext helper Gabriel Goller
2024-06-18 14:22 ` [pbs-devel] [PATCH proxmox-backup v4 4/4] pxar: use anyhow::Error in PxarBackupStream Gabriel Goller
2024-06-19  9:36 ` [pbs-devel] applied-series: [PATCH proxmox{, -backup} v4 0/4] output full anyhow context in client Wolfgang Bumiller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal