Skip to main content

Crate lemon_bugsnag_rs

Crate lemon_bugsnag_rs 

Source
Expand description

The lemon-bugsnag-rs crate offers developers a low-friction way to interface with the BugSnag error-reporting and sessions APIs.

§Goals

  • Low friction and ease of use.

    • This crate should offer little resistance to implementation for users at all skill and experience levels.
    • This crate should require no specialized knowledge of Rust, the BugSnag API, hardware, etc. A user with the ability to write a Hello World Rust application and skim the BugSnag documentation should be able to have this crate working and delivering payloads in a matter of minutes. We’ve even tried to reduce that second burden as much as possible.
    • As part of the above goal, we have created builders that allow the user to elide the burden of turning their Strings into &strs, explicitly wrapping arguments in Options, manually creating vectors for single items, and so on.
  • Flexibility.

    • In addition to some of the ease-of-use considerations which cross into this domain, we have also done our best to create a structure of features that allows the user of this library significant control over which non-critical code is compiled into their final product. Features such as optional-builders and convenience-intos allow users to exchange ease of use and flexibility for tighter control over this library’s footprint.
  • Thorough documentation. Thoooorough.

    • We tested and documented setters and getters. Big whoop. Wanna fight about it?
    • We set a goal of 100% documentation and 100% test coverage. Probably a bit excessive, but it gave us a quantifiable goal, and we stuck to it.
  • Code organization tightly coupled with usage.

    • We completely restructured the code three or four times. Frankly, we’re still not 100% satisfied with this. We built the structures to reflect the BugSnag API payload 1:1, but that led to the user having to write an awful lot of use statements, since everything was so heavily segmented. We tried to alleviate this somewhat by flattening the larger payload structs, but I personally find this to be unsatisfying as it breaks the 1:1 relationship between the file structure and the payload structure.
  • Consistency.

    • Switching from synchronous to asynchronous, from sessions to error-reporting, or from Reqwest to Ureq, should be as close to seamless as possible. The APIs for all variations of API, backend, and blocking/non-blocking should differ only where absolutely necessary.
  • Things that still need doing:

    • Develop a guide for contributors.
    • Audit the constraints on trait inputs.
    • We’re not entirely thrilled with the blocking and non_blocking idioms we used in place of async, since async is a reserved word in Rust. This is currently in a mixed state, where the traits and structs have Sync and Async in their names, but the functions are using the blocking() and non_blocking() names.

§Features

Default features [ error-client, reqwest, sync ]

  • default — The default feature set enables synchronous requests to the BugSnag error-reporting API using the Reqwest networking library. Many of the examples spread throughout this documentation make use of features not included in the default feature set. Please see comments in the example code as well as the rest of the features documentation for more information.

Runtimes

  • tokio — Enables the Tokio asynchronous runtime.

API client types

  • error-client (enabled by default) — Supports communication with the BugSnag error-reporting API.
  • session-client — Supports communication with the BugSnag session-reporting API.

Networking back-end clients

  • reqwest (enabled by default) — Enables the Reqwest networking client.
  • ureq — Enables the Ureq networking client.

Network back-end types

  • async — Enables the optional asynchronous network operations when using clients, such as Reqwest, which support them. Also enables the async-trait dependency, which allows for the easy creation of asynchronous functions in traits.
  • sync (enabled by default) — Enables blocking network operations for clients that support them.

Helpers and convenience features

  • convenience-intos — Enables From and To implementations that are intended to reduce friction when constructing builders and clients. For instance, when this feature is enabled, a single Breadcrumb struct will be automatically converted into a Vec<Breadcrumb> when used in contexts that expect a vector of Breadcrumbs, such as in some of the struct builders used in the library. Likewise, a Breadcrumb will be turned into an Option<Vec<Breadcrumb>> when appropriate assuming this feature is enabled.

    All builders and structures in this library benefit from convenience-intos in this manner.

  • optional-builders — Enables builders for all structs at all levels of the payload structure.

§Examples

The quickest starts.

Error API, asynchronous client.

This example requires the

dep:tokio, async, error-client, and reqwest features.

// The ClientBuilder is the basis for most operations in this library.
use lemon_bugsnag_rs::common::builder::client_builder::ClientBuilder;
// This brings the `non_blocking()` function  of DeciderTraitAsync into
// scope. DeciderTraitSync and DeciderTraitAsync are the functions that
// allow you to choose whether you want a blocking or non-blocking client.
// This is required even if your chosen networking backend only offers one
// or the other.
use lemon_bugsnag_rs::common::traits::decider_trait_async::DeciderTraitAsync;
// This brings into scope the `build()` function of
// `BackendBuilderTraitAsync,` which is implemented by the builders that
// create and configure the asynchronous networking client you will use to
// send your BugSnag payload.
use lemon_bugsnag_rs::common::traits::backend_builder_trait_async::BackendBuilderTraitAsync;
// Provides the `send()` function for asynchronous backend clients.
use lemon_bugsnag_rs::common::traits::client_trait_async::ClientTraitAsync;

// To use the bundle rather than import each item separately:
// use lemon_bugsnag_rs::common::bundle::*;

// Start by retrieving a builder for BugSnag error-reporting API clients.
let mut cb = ClientBuilder::error();

cb.configure(
    "Your API key goes here",
    // An arbitrary string declaring an error class for this payload.
    "An error class for your message",
    "The error message you wish to record",
    // A string to identify the source of the error report. For example,
    // "Company Name mobile app," "web API," or, "lemon-bugsnag-rs," depending
    // on how you want to track errors.
    "Notifier name",
    "Notifier version",
    // Optional. Used to provide information about the language, libraries,
    // and frameworks used by the application reporting the error.
    "Rust 1.82.0 with lemon-bugsnag-rs",
    // Release stage of application reporting the error.
    "dev"
);

// Choose the `Reqwest` backend, which is the only currently-implemented
// networking backend that supports asynchronous operations. If additional
// asynchronous backends are implemented in the future, you would select
// one of them by replacing reqwest() with the appropriate backend name.
let mut client = cb.reqwest().non_blocking().build().unwrap();

// Send your payload. This must be done from an async context, such as
// an async function, or using `block_on()` or the equivalent from an
// async runtime.
match client.send().await {
    Ok(response) => {
        // Looks good. Do stuff.
    },
    Err(error) => {
        // A bummer has happened. Handle it.
    },
}

   

Error API, synchronous Reqwest client.

This example requires the

error-client, reqwest, and sync features.

use lemon_bugsnag_rs::common::bundle::*;

// Start by retrieving a builder for BugSnag error-reporting API clients.
let mut cb = ClientBuilder::error();

cb.configure(
    "Your API key goes here",
    // An arbitrary string declaring an error class for this payload.
    "An error class for your message",
    "The error message you wish to record",
    // A string to identify the source of the error report. For example,
    // "Company Name mobile app," "web API," or, "lemon-bugsnag-rs," depending
    // on how you want to track errors.
    "Notifier name",
    "Notifier version",
    // Optional. Used to provide information about the language, libraries,
    // and frameworks used by the application reporting the error.
    "Rust 1.82.0 with lemon-bugsnag-rs",
    // Release stage of application reporting the error.
    "dev"
);

// Choose the `Reqwest` non-blocking backend.
let mut client = cb.reqwest().blocking().build().unwrap();

// Send your payload.
match client.send() {
    Ok(response) => {
        // Looks good. Do stuff.
    },
    Err(error) => {
        // A bummer has happened. Handle it.
    }
}

   

Sessions API, asynchronous client

This example requires the

dep:tokio, session-client, reqwest, and async features.

use lemon_bugsnag_rs::common::bundle::*;

// Start by retrieving a builder for BugSnag error-reporting API clients.
let mut cb = ClientBuilder::session();

cb.configure(
    "Your API key goes here",
    // A string to identify the source of the error report. For example,
    // "Company Name mobile app," "web API," or, "lemon-bugsnag-rs," depending
    // on how you want to track errors.
    "A name to identify your application",
    "Notifier version",
    // Release stage of application reporting the error.
    "dev",
    "Application version",
);

// Choose the `Reqwest` backend, which supports asynchronous operations. If
// additional asynchronous backends are implemented in the future, you could
// select one of them by replacing reqwest() with the appropriate backend
// name.
let mut client = cb.reqwest().non_blocking().build().unwrap();
match client.send().await {
    Ok(response) => {
        // Looks good. Do stuff.
    },
    Err(error) => {
        // A bummer has happened. Handle it.
    },
}

   

Sessions API, synchronous client using the Ureq backend.

This example requires the

session-client, ureq, and sync features.

use lemon_bugsnag_rs::common::builder::client_builder::ClientBuilder;
use lemon_bugsnag_rs::common::traits::backend_builder_trait_sync::BackendBuilderTraitSync;
// Provides the `send()` function for synchronous backend clients.
use lemon_bugsnag_rs::common::traits::client_trait_sync::ClientTraitSync;

// To use the bundle rather than import each item separately:
// use lemon_bugsnag_rs::common::bundle::*;

// Start by retrieving a builder for BugSnag error-reporting API clients.
let mut cb = ClientBuilder::session();

cb.configure(
    "Your API key goes here",
    // A string to identify the source of the error report. For example,
    // "Company Name mobile app," "web API," or, "lemon-bugsnag-rs," depending
    // on how you want to track errors.
    "A name to identify your application",
    "Notifier version",
    // Release stage of application reporting the error.
    "dev",
    "Application version",
);

// Choose the `Ureq` backend.
let mut client = cb.ureq().build().unwrap();

let result = client.send();
if result.is_ok() {
    let response = result.unwrap();
    // Due to the way the Ureq clients are implemented, you will want to
    // check the HTTP response code to ensure you received the expected result.
    if response.status() != 200 {
        // Looks good. Do stuff.
    } else {
        // Possible 40x or 50x. Process as appropriate.
    }
} else {
    // A bummer has happened. Handle it.
}

Modules§

common
Includes structs and trait common to all builders and clients.
errorerror-client
Contains structs and enums used for BugSnag error-reporting API builders, clients, and payloads.
sessionsession-client
Contains structs and enums used for BugSnag sessions API builders, clients, and payloads.