Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sd2k/rocket_newrelic

A Rocket fairing providing New Relic instrumentation
https://github.com/sd2k/rocket_newrelic

Last synced: 19 days ago
JSON representation

A Rocket fairing providing New Relic instrumentation

Awesome Lists containing this project

README

        

# Rocket NewRelic

[![Build Status](https://travis-ci.org/sd2k/rocket_newrelic.svg?branch=master)](https://travis-ci.org/sd2k/rocket_newrelic)
[![docs.rs](https://docs.rs/rocket_newrelic/badge.svg)](https://docs.rs/rocket_newrelic)
[![crates.io](https://img.shields.io/crates/v/rocket_newrelic.svg)](https://crates.io/crates/rocket_newrelic)

A Rocket fairing instrumenting requests using New Relic.

Attach the fairing to your `Rocket` app, and any requests that include
a [`Transaction`] in their request guard will be instrumented using
the handler base path and name as the transaction name.

## Usage

**Important** - this fairing still requires the [New Relic daemon] to be run
alongside your app in some way, and the underlying [newrelic] and
[newrelic-sys] crates have some additional build requirements. Make sure these
are met when trying to use this crate.

Crucially the `libnewrelic` C SDK requires a few functions not provided by musl
(at least `qsort_r` and `backtrace`), so this won't (currently) build against
musl.

---

Add the crate to your Cargo.toml:

```toml
[dependencies]
rocket_newrelic = { git = "https://github.com/sd2k/rocket_newrelic" }
```

Then add a `&Transaction` request guard to any handlers you
wish to instrument:

```rust
use rocket_newrelic::Transaction;

#[get("/user/me")]
pub fn get_me(_transaction: &Transaction) -> &'static str {
"It's me!"
}
```

Finally, attach the fairing to your `Rocket` app:

```rust
use rocket_newrelic::NewRelic;

fn main() -> {
let newrelic = NewRelic::new("MY_APP_NAME", "MY_LICENSE_KEY")
.expect("Could not register with New Relic");
rocket::ignite()
.manage(newrelic)
.mount("/root", routes![get_me])
.launch();
}
```

In the above example we'd then be able to see these transactions under
`/root/get_me`.

## Advanced usage

The [`Transaction`] object used in the request guard provides a few methods
to allow further instrumentation, such as custom attributes and transaction
segments. The below example demonstrates some of this functionality; see the
methods of `Transaction` for more details.

```rust
#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate rocket;

use newrelic::{Datastore, ExternalParamsBuilder};
use rocket_contrib::json::Json;
use rocket_newrelic::{NewRelic, Transaction};
use serde_json::Value;

struct User;

// This would normally connect to a database and perhaps return some data.
fn insert_into_db(_: &Json) -> Result {
Ok(User {})
}

#[post("/users", data = "")]
fn create_user(transaction: &Transaction, user: Json) {
// Add attributes to a transaction
if let Some(Value::String(name)) = user.get("name") {
transaction.add_attribute("user name", name);
}
if let Some(age) = user.get("age").and_then(|a| a.as_i64()) {
transaction.add_attribute("user age", age);
}

// Executing a query in a datastore segment
let query = "INSERT INTO users VALUES (%s, %s);";
match transaction.datastore_segment(Datastore::Postgres, "users", "insert", query, |_| {
insert_into_db(&user)
}) {
Ok(_) => println!("Created user"),
Err(_) => println!("Could not create user"),
}

// Doing expensive operations in a custom segment
let _expensive_value: Result =
transaction.custom_segment("process user", "process", |s| {
// Nesting an external segment within the custom segment
let url = "https://logging-thing";
let external_params = ExternalParamsBuilder::new(url)
.procedure("set")
.library("reqwest")
.build()
.unwrap();
s.external_nested(&external_params, |_| {
reqwest::blocking::Client::new().post(url).send()
})
});
}

fn main() {
let newrelic = NewRelic::from_env();
rocket::ignite()
.manage(newrelic)
.mount("/", routes![create_user])
.launch();
}
```

### Diesel queries

With the `diesel` feature enabled it's possible to pass a Diesel query,
along with a `&Connection`, into the `diesel_segment_load` and
`diesel_segment_first` methods of a [`Transaction`]. This will log the SQL query
and return either all results, or the first result, respectively.

[Rocket]: rocket::Rocket
[Transaction]: crate::Transaction
[newrelic]: https://github.com/sd2k/newrelic
[newrelic-sys]: https://github.com/sd2k/newrelic-sys
[New Relic daemon]: https://docs.newrelic.com/docs/agents/c-sdk/get-started/introduction-c-sdk#architecture