https://github.com/sd2k/rocket_newrelic
A Rocket fairing providing New Relic instrumentation
https://github.com/sd2k/rocket_newrelic
Last synced: over 1 year ago
JSON representation
A Rocket fairing providing New Relic instrumentation
- Host: GitHub
- URL: https://github.com/sd2k/rocket_newrelic
- Owner: sd2k
- Created: 2019-05-22T11:37:49.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2024-03-21T12:53:43.000Z (over 2 years ago)
- Last Synced: 2025-04-01T20:42:54.806Z (over 1 year ago)
- Language: Rust
- Size: 25.4 KB
- Stars: 0
- Watchers: 2
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Rocket NewRelic
[](https://travis-ci.org/sd2k/rocket_newrelic)
[](https://docs.rs/rocket_newrelic)
[](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