[−][src]Crate 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:
[dependencies]
rocket_newrelic = { git = "https://github.com/sd2k/rocket_newrelic" }
Then add a &Transaction
request guard to any handlers you
wish to instrument:
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:
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.
#![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<Value>) -> Result<User, ()> { Ok(User {}) } #[post("/users", data = "<user>")] fn create_user(transaction: &Transaction, user: Json<Value>) { // Add attributes to a transaction if let Some(Value::String(name)) = user.get("name") { transaction.add_attribute("user name", name); } if let Some(Some(age)) = user.get("age").map(|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<reqwest::Response, reqwest::Error> = 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::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.
Structs
NewRelic | A Rocket fairing which instruments requests using New Relic. |
Enums
Transaction | A New Relic transaction. |