Skip to content

docs: Document integrations and the Hub better #291

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

Merged
merged 4 commits into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
34 changes: 31 additions & 3 deletions sentry-anyhow/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
//! Adds support for capturing Sentry errors from `anyhow::Error`.
//! Adds support for capturing Sentry errors from [`anyhow::Error`].
//!
//! This integration adds a new event *source*, which allows you to create events directly
//! from an [`anyhow::Error`] struct. As it is only an event source it only needs to be
//! enabled using the `anyhow` cargo feature, it does not need to be enabled in the call to
//! [`sentry::init`](https://docs.rs/sentry/*/sentry/fn.init.html).
//!
//! This integration does not need to be installed, instead it provides an extra function to
//! capture [`anyhow::Error`], optionally exposing it as a method on the
//! [`sentry::Hub`](https://docs.rs/sentry/*/sentry/struct.Hub.html) using the
//! [`AnyhowHubExt`] trait.
//!
//! Like a plain [`std::error::Error`] being captured, [`anyhow::Error`] is captured with a
//! chain of all error sources, if present. See
//! [`sentry::capture_error`](https://docs.rs/sentry/*/sentry/fn.capture_error.html) for
//! details of this.
//!
//! # Example
//!
Expand All @@ -13,6 +28,8 @@
//! capture_anyhow(&err);
//! }
//! ```
//!
//! [`anyhow::Error`]: https://docs.rs/anyhow/*/anyhow/struct.Error.html
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think intra-doc-links should handle this?

Which reminds me, the relative links from above relative links will also fail when this is converted to the README via cargo-readme :-(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what happened here. When trying to use the plain intra-doc links cargo +nightly doc did not give any warning, suggesting it was happy with the link, but they did not work, they just rendered literally. I have no idea what I was doing wrong and failed to find. This was the only way I got this to link correctly, it's not very nice but at least it's not wrong.

If you can get it to work with the intra-doc link then let me know what I did wrong!


#![doc(html_favicon_url = "https://sentry-brand.storage.googleapis.com/favicon.ico")]
#![doc(html_logo_url = "https://sentry-brand.storage.googleapis.com/sentry-glyph-black.png")]
Expand All @@ -22,16 +39,27 @@
use sentry_core::types::Uuid;
use sentry_core::Hub;

/// Captures an `anyhow::Error`.
/// Captures an [`anyhow::Error`].
///
/// This will capture an anyhow error as a sentry event if a
/// [`sentry::Client`](../../struct.Client.html) is initialised, otherwise it will be a
/// no-op. The event is dispatched to the thread-local hub, with semantics as described in
/// [`Hub::current`].
///
/// See [module level documentation](index.html) for more information.
///
/// [`anyhow::Error`]: https://docs.rs/anyhow/*/anyhow/struct.Error.html
pub fn capture_anyhow(e: &anyhow::Error) -> Uuid {
Hub::with_active(|hub| hub.capture_anyhow(e))
}

/// Hub extension methods for working with `anyhow`.
/// Hub extension methods for working with [`anyhow`].
///
/// [`anyhow`]: https://docs.rs/anyhow
pub trait AnyhowHubExt {
/// Captures an [`anyhow::Error`] on a specific hub.
///
/// [`anyhow::Error`]: https://docs.rs/anyhow/*/anyhow/struct.Error.html
fn capture_anyhow(&self, e: &anyhow::Error) -> Uuid;
}

Expand Down
6 changes: 6 additions & 0 deletions sentry-core/src/clientoptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@ pub struct ClientOptions {
pub in_app_exclude: Vec<&'static str>,
// Integration options
/// A list of integrations to enable.
///
/// See [`sentry::integrations`](integrations/index.html#installing-integrations) for
/// how to use this to enable extra integrations.
pub integrations: Vec<Arc<dyn Integration>>,
/// Whether to add default integrations.
///
/// See [`sentry::integrations`](integrations/index.html#default-integrations) for
/// details how this works and interacts with manually installed integrations.
pub default_integrations: bool,
// Hooks
/// Callback that is executed before event sending.
Expand Down
57 changes: 35 additions & 22 deletions sentry-core/src/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,29 @@ impl HubImpl {
/// The central object that can manages scopes and clients.
///
/// This can be used to capture events and manage the scope. This object is
/// internally synchronized so it can be used from multiple threads if needed.
/// [`Send`][std::marker::Send] and [`Sync`][std::marker::Sync] so it can be used from
/// multiple threads if needed.
///
/// Each thread has its own thread-local (`Hub::current()`) hub, which is
/// automatically derived from the main hub (`Hub::main()`).
/// Each thread has its own thread-local ( see [`Hub::current`]) hub, which is
/// automatically derived from the main hub ([`Hub::main`]).
///
/// In most situations developers do not need to interface with the hub directly. Instead
/// toplevel convenience functions are expose that will automatically dispatch
/// to the thread-local (`Hub::current()`) hub. In some situations this might not be
/// to the thread-local ([`Hub::current`]) hub. In some situations this might not be
/// possible in which case it might become necessary to manually work with the
/// hub. This is for instance the case when working with async code.
///
/// Hubs that are wrapped in `Arc`s can be bound to the current thread with
/// Hubs that are wrapped in [`Arc`]s can be bound to the current thread with
/// the `run` static method.
///
/// Most common operations:
///
/// * `Hub::new`: creates a brand new hub
/// * `Hub::current`: returns the thread local hub
/// * `Hub::with`: invoke a callback with the thread local hub
/// * `Hub::with_active`: like `Hub::with` but does not invoke the callback if
/// * [`Hub::new`]: creates a brand new hub
/// * [`Hub::current`]: returns the thread local hub
/// * [`Hub::with`]: invoke a callback with the thread local hub
/// * [`Hub::with_active`]: like `Hub::with` but does not invoke the callback if
/// the client is not in a supported state or not bound
/// * `Hub::new_from_top`: creates a new hub with just the top scope of another hub.
/// * [`Hub::new_from_top`]: creates a new hub with just the top scope of another hub.
#[derive(Debug)]
pub struct Hub {
#[cfg(feature = "client")]
Expand Down Expand Up @@ -115,31 +116,36 @@ impl Hub {
})
}

/// Returns the current hub.
/// Returns the current, thread-local hub.
///
/// By default each thread gets a different thread local hub. If an
/// atomically reference counted hub is available it can override this
/// one here by calling `Hub::run` with a closure.
/// Invoking this will return the current thread-local hub. The first
/// time it is called on a thread, a new thread-local hub will be
/// created based on the topmost scope of the hub on the main thread as
/// returned by [`Hub::main`]. If the main thread did not yet have a
/// hub it will be created when invoking this function.
///
/// To have control over which hub is installed as the current
/// thread-local hub, use [`Hub::run`].
///
/// This method is unavailable if the client implementation is disabled.
/// When using the minimal API set use `Hub::with_active` instead.
/// When using the minimal API set use [`Hub::with_active`] instead.
#[cfg(feature = "client")]
pub fn current() -> Arc<Hub> {
Hub::with(Arc::clone)
}

/// Returns the main thread's hub.
///
/// This is similar to `current` but instead of picking the current
/// thread's hub it returns the main thread's hub instead.
/// This is similar to [`Hub::current`] but instead of picking the
/// current thread's hub it returns the main thread's hub instead.
#[cfg(feature = "client")]
pub fn main() -> Arc<Hub> {
PROCESS_HUB.0.clone()
}

/// Invokes the callback with the default hub.
///
/// This is a slightly more efficient version than `Hub::current()` and
/// This is a slightly more efficient version than [`Hub::current`] and
/// also unavailable in minimal mode.
#[cfg(feature = "client")]
pub fn with<F, R>(f: F) -> R
Expand All @@ -149,7 +155,7 @@ impl Hub {
if USE_PROCESS_HUB.with(Cell::get) {
f(&PROCESS_HUB.0)
} else {
// not on safety: this is safe because even though we change the Arc
// note on safety: this is safe because even though we change the Arc
// by temorary binding we guarantee that the original Arc stays alive.
// For more information see: run
THREAD_HUB.with(|stack| unsafe {
Expand All @@ -159,7 +165,7 @@ impl Hub {
}
}

/// Like `Hub::with` but only calls the function if a client is bound.
/// Like [`Hub::with`] but only calls the function if a client is bound.
///
/// This is useful for integrations that want to do efficiently nothing if there is no
/// client bound. Additionally this internally ensures that the client can be safely
Expand All @@ -181,6 +187,13 @@ impl Hub {
}

/// Binds a hub to the current thread for the duration of the call.
///
/// During the execution of `f` the given hub will be installed as the
/// thread-local hub. So any call to [`Hub::current`] during this time
/// will return the provided hub.
///
/// Once the function is finished executing, including after it
/// paniced, the original hub is re-installed if one was present.
#[cfg(feature = "client")]
pub fn run<F: FnOnce() -> R, R>(hub: Arc<Hub>, f: F) -> R {
let mut restore_process_hub = false;
Expand Down Expand Up @@ -331,11 +344,11 @@ impl Hub {

/// End the current Release Health Session.
///
/// See the global [`end_session`](crate::end_session_with)
/// for more documentation.
/// See the global [`sentry::end_session`](crate::end_session) for more documentation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks for fixing this ;-)

pub fn end_session(&self) {
self.end_session_with_status(SessionStatus::Exited)
}

/// End the current Release Health Session with the given [`SessionStatus`].
///
/// See the global [`end_session_with_status`](crate::end_session_with_status)
Expand Down
2 changes: 2 additions & 0 deletions sentry-core/src/scope/real.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ impl Scope {
}

/// Removes a tag.
///
/// If the tag is not set, does nothing.
pub fn remove_tag(&mut self, key: &str) {
self.tags.remove(key);
}
Expand Down
2 changes: 1 addition & 1 deletion sentry-core/src/session.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Release Health Sessions
//!
//! https://develop.sentry.dev/sdk/sessions/
//! <https://develop.sentry.dev/sdk/sessions/>

use std::sync::{Arc, Condvar, Mutex, MutexGuard};
use std::thread::JoinHandle;
Expand Down
1 change: 0 additions & 1 deletion sentry-panic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#![doc(html_logo_url = "https://sentry-brand.storage.googleapis.com/sentry-glyph-black.png")]
#![warn(missing_docs)]
#![deny(unsafe_code)]
#![warn(missing_doc_code_examples)]

use std::panic::{self, PanicInfo};
use std::sync::Once;
Expand Down
6 changes: 3 additions & 3 deletions sentry/src/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use crate::{ClientOptions, Integration};
/// also sets the `dsn`, `release`, `environment`, and proxy settings based on
/// environment variables.
///
/// When the `default_integrations` option is set to `true` (by default), the
/// following integrations will be added *before* any manually defined
/// integrations, depending on enabled feature flags:
/// When the [`ClientOptions::default_integrations`] option is set to
/// `true` (the default), the following integrations will be added *before*
/// any manually defined integrations, depending on enabled feature flags:
///
/// 1. [`AttachStacktraceIntegration`] (`feature = "backtrace"`)
/// 2. [`DebugImagesIntegration`] (`feature = "debug-images"`)
Expand Down
47 changes: 45 additions & 2 deletions sentry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,51 @@ pub use crate::init::{init, ClientInitGuard};

/// Available Sentry Integrations.
///
/// See the [`apply_defaults`] function for more information on which integrations are
/// used by default.
/// Integrations extend the functionality of the SDK for some common frameworks and
/// libraries. Integrations come two primary kinds: as event *sources* or as event
/// *processors*.
///
/// Integrations which are *sources*, like e.g. the
/// [`sentry::integrations::anyhow`](integrations::anyhow) integration, usually provide one
/// or more functions to create new events. They will usually provide their own extension
/// trait exposing a new method on the [`Hub`].
///
/// Integrations which *process* events in some way usually implement the
/// [`Itegration`](crate::Integration) trait and need to be installed when sentry is
/// initialised.
///
/// # Installing Integrations
///
/// Processing integrations which implement [`Integration`](crate::Integration) need to be
/// installed when sentry is initialised. This is done using the
/// [`ClientOptions::add_integration`](crate::ClientOptions::add_integration) function, which you can
/// use to add extra integrations.
///
/// For example if you disabled the default integrations (see below) but still wanted the
/// [`sentry::integrations::debug_images`](integrations::debug_images) integration enabled,
/// you could do this as such:
///
/// ```
/// # #[cfg(feature = "debug-images")] {
/// use sentry::ClientOptions;
/// use sentry::integrations::debug_images::DebugImagesIntegration;
///
/// let options = ClientOptions {
/// default_integrations: false,
/// ..Default::default()
/// }.add_integration(DebugImagesIntegration::new());
/// let _guard = sentry::init(options);
/// # }
/// ```
///
/// # Default Integrations
///
/// The [`ClientOptions::default_integrations`](crate::ClientOptions::default_integrations)
/// option is a boolean field that when enabled will enable a number of default integrations
/// **before** any integrations provided by
/// [`ClientOptions::integrations`](crate::ClientOptions::integrations) are installed. This
/// is done using the [`apply_defaults`] function, which should be consulted for more
/// details and the list of which integrations are enabled by default.
///
/// [`apply_defaults`]: ../fn.apply_defaults.html
pub mod integrations {
Expand Down