Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic anyhow integration #165

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ with_client_implementation = ["im", "url", "with_backtrace"]
with_backtrace = ["backtrace", "regex"]
with_panic = ["with_backtrace"]
with_failure = ["failure", "with_backtrace"]
with_anyhow = ["anyhow"]
with_log = ["log", "with_backtrace"]
with_debug_to_log = ["log"]
with_env_logger = ["with_log", "env_logger"]
Expand All @@ -41,6 +42,7 @@ with_native_tls = ["reqwest/default-tls"]
backtrace = { version = "0.3.15", optional = true }
url = { version = "1.7.2", optional = true }
failure = { version = "0.1.5", optional = true }
anyhow = { version = "1.0.17", optional = true }
log = { version = "0.4.6", optional = true, features = ["std"] }
sentry-types = "0.11.0"
env_logger = { version = "0.6.1", optional = true }
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ testall:
checkfast: check-no-default-features check-default-features
.PHONY: checkfast

checkall: check-all-features check-no-default-features check-default-features check-failure check-log check-panic check-error-chain check-all-impls check-curl-transport check-actix
checkall: check-all-features check-no-default-features check-default-features check-failure check-log check-panic check-error-chain check-anyhow check-all-impls check-curl-transport check-actix
.PHONY: checkall

check-all-features:
Expand Down Expand Up @@ -91,6 +91,11 @@ check-error-chain:
@RUSTFLAGS=-Dwarnings cargo check --no-default-features --features 'with_error_chain'
.PHONY: check-error-chain

check-anyhow:
@echo 'NO CLIENT + ANYHOW'
@RUSTFLAGS=-Dwarnings cargo check --no-default-features --features 'with_anyhow'
.PHONY: check-anyhow

check-all-impls:
@echo 'NO CLIENT + ALL IMPLS'
@RUSTFLAGS=-Dwarnings cargo check --no-default-features --features 'with_failure,with_log,with_panic,with_error_chain'
Expand Down
97 changes: 97 additions & 0 deletions src/integrations/anyhow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//! Adds support for the anyhow crate.
//!
//! **Feature:** `with_anyhow` (disabled by default)
//!
//! This does not support capturing backtraces (which is a nightly-only feature in anyhow).
//!
//! # Example
//!
//! ```no_run
//! # extern crate sentry;
//! # extern crate anyhow;
//! # fn function_that_might_fail() -> Result<(), anyhow::Error> { Ok(()) }
//! use sentry::integrations::anyhow::capture_error;
//! # fn test() -> Result<(), anyhow::Error> {
//! let result = match function_that_might_fail() {
//! Ok(result) => result,
//! Err(err) => {
//! capture_error(&err);
//! return Err(err);
//! }
//! };
//! # Ok(()) }
//! # fn main() { test().unwrap() }
//! ```
//!
use anyhow::Error;

use crate::hub::Hub;
use crate::internals::Uuid;
use crate::protocol::{Event, Exception, Level};

/// Helper function to create an event from a `anyhow::Error`.
pub fn event_from_error(err: &anyhow::Error) -> Event<'static> {
let mut exceptions = vec![];

for cause in err.chain() {
exceptions.push(Exception {
ty: "Error".to_owned(),
module: None,
value: Some(cause.to_string()),
stacktrace: None,
..Default::default()
});
}

exceptions.reverse();
Event {
exception: exceptions.into(),
level: Level::Error,
..Default::default()
}
}

/// Captures a boxed failure (`anyhow::Error`).
///
/// This dispatches to the current hub.
pub fn capture_error(err: &Error) -> Uuid {
Hub::with_active(|hub| hub.capture_error(err))
}

/// Hub extension methods for working with failure.
pub trait AnyhowHubExt {
/// Captures a boxed failure (`anyhow::Error`).
fn capture_error(&self, err: &Error) -> Uuid;
}

impl AnyhowHubExt for Hub {
fn capture_error(&self, err: &Error) -> Uuid {
self.capture_event(event_from_error(err))
}
}

/// Extension trait providing methods to unwrap a result, preserving backtraces from the
/// underlying error in the event of a panic.
pub trait AnyhowResultExt {
/// Type of the success case
type Value;
/// Unwraps the result, panicking if it contains an error. Any backtrace attached to the
/// error will be preserved with the panic.
fn fallible_unwrap(self) -> Self::Value;
}

impl<T, E> AnyhowResultExt for Result<T, E>
where
E: Into<Error>,
{
type Value = T;
fn fallible_unwrap(self) -> Self::Value {
match self {
Ok(v) => v,
Err(e) => {
let e: Error = e.into();
panic!(e)
}
}
}
}
3 changes: 3 additions & 0 deletions src/integrations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ pub mod env_logger;

#[cfg(feature = "with_panic")]
pub mod panic;

#[cfg(feature = "with_anyhow")]
pub mod anyhow;
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
//! additional features:
//!
//! * `with_error_chain`: enables the error-chain integration
//! * `with_anyhow`: enables the anyhow integration
//! * `with_test_support`: enables the test support module
//! * `with_reqwest_transport`: enables the reqwest transport explicitly. This
//! is currently the default transport.
Expand Down