From c820b7c8918b45c0d41c13f940f72e09bf24b565 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Wed, 18 Nov 2020 21:57:20 +0100 Subject: [PATCH 1/4] docs: Document integrations and the Hub better This adds more documentation for how to use integrations and uses much more intra-doc links. The Hub documentation as well as the anyhow integration documentation have also seen various improvements. --- sentry-anyhow/src/lib.rs | 32 ++++++++++++++++-- sentry-core/src/clientoptions.rs | 6 ++++ sentry-core/src/hub.rs | 57 ++++++++++++++++++++------------ sentry-core/src/scope/real.rs | 2 ++ sentry-core/src/session.rs | 2 +- sentry-panic/src/lib.rs | 1 - sentry/src/defaults.rs | 6 ++-- sentry/src/lib.rs | 47 ++++++++++++++++++++++++-- 8 files changed, 121 insertions(+), 32 deletions(-) diff --git a/sentry-anyhow/src/lib.rs b/sentry-anyhow/src/lib.rs index 40b551268..dca229e5b 100644 --- a/sentry-anyhow/src/lib.rs +++ b/sentry-anyhow/src/lib.rs @@ -1,4 +1,17 @@ -//! 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`](../../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`](../../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`](../../fn.capture_error.html) for details of this. //! //! # Example //! @@ -13,6 +26,8 @@ //! capture_anyhow(&err); //! } //! ``` +//! +//! [`anyhow::Error`]: https://docs.rs/anyhow/*/anyhow/struct.Error.html #![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")] @@ -22,16 +37,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; } diff --git a/sentry-core/src/clientoptions.rs b/sentry-core/src/clientoptions.rs index 8100216be..676d5719b 100644 --- a/sentry-core/src/clientoptions.rs +++ b/sentry-core/src/clientoptions.rs @@ -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>, /// 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. diff --git a/sentry-core/src/hub.rs b/sentry-core/src/hub.rs index bf0a1e818..3bb9d4f8f 100644 --- a/sentry-core/src/hub.rs +++ b/sentry-core/src/hub.rs @@ -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")] @@ -115,14 +116,19 @@ 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::with(Arc::clone) @@ -130,8 +136,8 @@ impl Hub { /// 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 { PROCESS_HUB.0.clone() @@ -139,7 +145,7 @@ impl Hub { /// 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: F) -> R @@ -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 { @@ -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 @@ -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 R, R>(hub: Arc, f: F) -> R { let mut restore_process_hub = false; @@ -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. 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) diff --git a/sentry-core/src/scope/real.rs b/sentry-core/src/scope/real.rs index 44afba525..3080f91cc 100644 --- a/sentry-core/src/scope/real.rs +++ b/sentry-core/src/scope/real.rs @@ -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); } diff --git a/sentry-core/src/session.rs b/sentry-core/src/session.rs index b9be41a88..cf7eda53a 100644 --- a/sentry-core/src/session.rs +++ b/sentry-core/src/session.rs @@ -1,6 +1,6 @@ //! Release Health Sessions //! -//! https://develop.sentry.dev/sdk/sessions/ +//! use std::sync::{Arc, Condvar, Mutex, MutexGuard}; use std::thread::JoinHandle; diff --git a/sentry-panic/src/lib.rs b/sentry-panic/src/lib.rs index 487b0f407..d7de4062d 100644 --- a/sentry-panic/src/lib.rs +++ b/sentry-panic/src/lib.rs @@ -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; diff --git a/sentry/src/defaults.rs b/sentry/src/defaults.rs index 3213fe1a0..c58bd18da 100644 --- a/sentry/src/defaults.rs +++ b/sentry/src/defaults.rs @@ -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"`) diff --git a/sentry/src/lib.rs b/sentry/src/lib.rs index d75636bc0..0982d6f61 100644 --- a/sentry/src/lib.rs +++ b/sentry/src/lib.rs @@ -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::integrations`](crate::ClientOptions::integrations) field, 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: +/// +/// ``` +/// use sentry::ClientOptions; +/// use sentry::integrations::debug_images::DebugImagesIntegration; +/// +/// let options = ClientOptions { +/// // Add a DSN. +/// default_integrations: false, +/// integrations: vec![DebugImagesIntegration::default()], +/// ..Default::default() +/// }; +/// 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 by default enabled. /// /// [`apply_defaults`]: ../fn.apply_defaults.html pub mod integrations { From f62ffee52c30c7cfa8670197b0ba38ba19f267e1 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Thu, 19 Nov 2020 09:26:30 +0100 Subject: [PATCH 2/4] Use ClientOptions::add_integration Suggestions from review, add_integration was the most important. Co-authored-by: Arpad Borsos --- sentry/src/lib.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sentry/src/lib.rs b/sentry/src/lib.rs index 0982d6f61..da4e3877b 100644 --- a/sentry/src/lib.rs +++ b/sentry/src/lib.rs @@ -107,7 +107,7 @@ pub use crate::init::{init, ClientInitGuard}; /// /// Processing integrations which implement [`Integration`](crate::Integration) need to be /// installed when sentry is initialised. This is done using the -/// [`ClientOptions::integrations`](crate::ClientOptions::integrations) field, which you can +/// [`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 @@ -119,11 +119,9 @@ pub use crate::init::{init, ClientInitGuard}; /// use sentry::integrations::debug_images::DebugImagesIntegration; /// /// let options = ClientOptions { -/// // Add a DSN. /// default_integrations: false, -/// integrations: vec![DebugImagesIntegration::default()], /// ..Default::default() -/// }; +/// }.add_integration(DebugImagesIntegration::new()); /// let _guard = sentry::init(options); /// ``` /// @@ -134,7 +132,7 @@ pub use crate::init::{init, ClientInitGuard}; /// **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 by default enabled. +/// details and the list of which integrations are enabled by default. /// /// [`apply_defaults`]: ../fn.apply_defaults.html pub mod integrations { From b9e5b1f743d9a7ac586435dcd9488cdc3e4ebc8b Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Thu, 19 Nov 2020 13:26:53 +0100 Subject: [PATCH 3/4] Skip this doctest if the feature is not available We this will get tested in some other configuration that does have the feature, it's fine. --- sentry/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry/src/lib.rs b/sentry/src/lib.rs index da4e3877b..534144f67 100644 --- a/sentry/src/lib.rs +++ b/sentry/src/lib.rs @@ -115,6 +115,7 @@ pub use crate::init::{init, ClientInitGuard}; /// you could do this as such: /// /// ``` +/// # #[cfg(feature = "debug-images")] { /// use sentry::ClientOptions; /// use sentry::integrations::debug_images::DebugImagesIntegration; /// @@ -123,6 +124,7 @@ pub use crate::init::{init, ClientInitGuard}; /// ..Default::default() /// }.add_integration(DebugImagesIntegration::new()); /// let _guard = sentry::init(options); +/// # } /// ``` /// /// # Default Integrations From 93b58c7adda6b31ed0b9bccc1f13ab0b6caaafc8 Mon Sep 17 00:00:00 2001 From: Floris Bruynooghe Date: Thu, 19 Nov 2020 13:34:14 +0100 Subject: [PATCH 4/4] Make links work for stand-alone crate This is not as nice as now they point to docs.rs, but it seems impossible to otherwise point to the sentry crate with intra-doc links as we'd need circular dependencies for the doc feature, which cargo doesn't allow. --- sentry-anyhow/src/lib.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sentry-anyhow/src/lib.rs b/sentry-anyhow/src/lib.rs index dca229e5b..ddfd7c235 100644 --- a/sentry-anyhow/src/lib.rs +++ b/sentry-anyhow/src/lib.rs @@ -3,15 +3,17 @@ //! 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`](../../fn.init.html). +//! [`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`](../../struct.Hub.html) using the [`AnyhowHubExt`] trait. +//! [`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`](../../fn.capture_error.html) for details of this. +//! [`sentry::capture_error`](https://docs.rs/sentry/*/sentry/fn.capture_error.html) for +//! details of this. //! //! # Example //!