mirror of
https://github.com/storytold/voder-proxy.git
synced 2026-10-19 07:43:12 +00:00
add newrelic logging capability
This commit is contained in:
Generated
+17
@@ -420,6 +420,22 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "newrelic"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7ec1eb312ccd33c2d88ff317d59164465a41014ad465ba8a67e2c062343e3a8"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"newrelic-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "newrelic-sys"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a9b9030b5f433ac2afb956eeaf89020e07d3cb9b0561cd07f1737c97a4af93a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
@@ -835,6 +851,7 @@ dependencies = [
|
|||||||
"hyper",
|
"hyper",
|
||||||
"hyper-reverse-proxy",
|
"hyper-reverse-proxy",
|
||||||
"log",
|
"log",
|
||||||
|
"newrelic",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ futures = "0.1"
|
|||||||
hyper = "0.12"
|
hyper = "0.12"
|
||||||
hyper-reverse-proxy = "0.4"
|
hyper-reverse-proxy = "0.4"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
|
newrelic = "0.2.2"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
serde = "1.0.104"
|
serde = "1.0.104"
|
||||||
serde_derive = "1.0.104"
|
serde_derive = "1.0.104"
|
||||||
|
|||||||
+28
-6
@@ -2,6 +2,8 @@
|
|||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use] extern crate serde_derive;
|
||||||
|
|
||||||
|
pub mod newrelic_logger;
|
||||||
|
|
||||||
use anyhow::Result as AnyhowResult;
|
use anyhow::Result as AnyhowResult;
|
||||||
use futures::future::{self, Future};
|
use futures::future::{self, Future};
|
||||||
use hyper::Method;
|
use hyper::Method;
|
||||||
@@ -19,18 +21,22 @@ use std::sync::Arc;
|
|||||||
use rand::seq::IteratorRandom;
|
use rand::seq::IteratorRandom;
|
||||||
use hyper::http::header::HeaderName;
|
use hyper::http::header::HeaderName;
|
||||||
use hyper::header::HeaderValue;
|
use hyper::header::HeaderValue;
|
||||||
|
use newrelic::App;
|
||||||
|
use crate::newrelic_logger::NewRelicLogger;
|
||||||
|
|
||||||
type BoxFut = Box<dyn Future<Item=Response<Body>, Error=hyper::Error> + Send>;
|
type BoxFut = Box<dyn Future<Item=Response<Body>, Error=hyper::Error> + Send>;
|
||||||
|
|
||||||
const ENV_DEFAULT_ROUTE : &'static str = "DEFAULT_ROUTE";
|
const ENV_DEFAULT_ROUTE : &'static str = "DEFAULT_ROUTE";
|
||||||
|
const ENV_NEWRELIC_API_KEY : &'static str = "NEWRELIC_API_KEY";
|
||||||
const ENV_PROXY_CONFIG_FILE : &'static str = "PROXY_CONFIG_FILE";
|
const ENV_PROXY_CONFIG_FILE : &'static str = "PROXY_CONFIG_FILE";
|
||||||
const ENV_RUST_LOG : &'static str = "RUST_LOG";
|
const ENV_RUST_LOG : &'static str = "RUST_LOG";
|
||||||
const ENV_SERVICE_PORT : &'static str = "SERVICE_PORT";
|
const ENV_SERVICE_PORT : &'static str = "SERVICE_PORT";
|
||||||
|
|
||||||
const DEFAULT_DEFAULT_ROUTE : &'static str = "http://127.0.0.1:12345";
|
const DEFAULT_DEFAULT_ROUTE : &'static str = "http://127.0.0.1:12345";
|
||||||
|
const DEFAULT_NEWRELIC_API_KEY : &'static str = "";
|
||||||
const DEFAULT_PROXY_CONFIG_FILE : &'static str = "proxy_configs.toml";
|
const DEFAULT_PROXY_CONFIG_FILE : &'static str = "proxy_configs.toml";
|
||||||
const DEFAULT_RUST_LOG: &'static str = "tokio_reactor=warn,hyper=info,debug";
|
const DEFAULT_RUST_LOG : &'static str = "tokio_reactor=warn,hyper=info,debug";
|
||||||
const DEFAULT_SERVICE_PORT: u16 = 5555;
|
const DEFAULT_SERVICE_PORT : u16 = 5555;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
struct ProxyConfigs {
|
struct ProxyConfigs {
|
||||||
@@ -198,6 +204,7 @@ fn main() -> AnyhowResult<()> {
|
|||||||
|
|
||||||
let default_route = get_env_string(ENV_DEFAULT_ROUTE, DEFAULT_DEFAULT_ROUTE);
|
let default_route = get_env_string(ENV_DEFAULT_ROUTE, DEFAULT_DEFAULT_ROUTE);
|
||||||
let service_port = get_env_num::<u16>(ENV_SERVICE_PORT, DEFAULT_SERVICE_PORT)?;
|
let service_port = get_env_num::<u16>(ENV_SERVICE_PORT, DEFAULT_SERVICE_PORT)?;
|
||||||
|
let newrelic_api_key = get_env_string(ENV_NEWRELIC_API_KEY, DEFAULT_NEWRELIC_API_KEY);
|
||||||
|
|
||||||
info!("Default route: {}", default_route);
|
info!("Default route: {}", default_route);
|
||||||
|
|
||||||
@@ -219,23 +226,38 @@ fn main() -> AnyhowResult<()> {
|
|||||||
default_route: default_route,
|
default_route: default_route,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let newrelic_logger = if newrelic_api_key.is_empty() {
|
||||||
|
NewRelicLogger::null_instance()
|
||||||
|
} else {
|
||||||
|
NewRelicLogger::try_new_or_null("voder-proxy", &newrelic_api_key)
|
||||||
|
};
|
||||||
|
|
||||||
|
let newrelic_logger = Arc::new(newrelic_logger);
|
||||||
|
|
||||||
let make_service = make_service_fn(move |socket: &AddrStream| {
|
let make_service = make_service_fn(move |socket: &AddrStream| {
|
||||||
let remote_addr = socket.remote_addr();
|
let remote_addr = socket.remote_addr();
|
||||||
info!("Got a request from: {:?}", remote_addr);
|
info!("Got a request from: {:?}", remote_addr);
|
||||||
|
|
||||||
let router2 = router.clone();
|
let router2 = router.clone();
|
||||||
|
let newrelic_logger2 = newrelic_logger.clone();
|
||||||
|
|
||||||
service_fn(move |req: Request<Body>| {
|
service_fn(move |req: Request<Body>| {
|
||||||
let router3 = router2.clone();
|
let router3 = router2.clone();
|
||||||
|
let newrelic_logger3 = newrelic_logger2.clone();
|
||||||
|
|
||||||
match (req.method(), req.uri().path()) {
|
match (req.method(), req.uri().path()) {
|
||||||
(&Method::POST, "/speak") =>
|
(&Method::POST, "/speak") => {
|
||||||
speak_proxy(req, remote_addr.clone(), router3, "/speak"),
|
let _droppable_transaction = newrelic_logger3.web_transaction("proxy /speak");
|
||||||
(&Method::POST, "/speak_spectrogram") =>
|
speak_proxy(req, remote_addr.clone(), router3, "/speak")
|
||||||
speak_proxy(req, remote_addr.clone(), router3, "/speak_spectrogram"),
|
},
|
||||||
|
(&Method::POST, "/speak_spectrogram") => {
|
||||||
|
let _droppable_transaction = newrelic_logger3.web_transaction("proxy /speak_spectrogram");
|
||||||
|
speak_proxy(req, remote_addr.clone(), router3, "/speak_spectrogram")
|
||||||
|
},
|
||||||
(&Method::GET, "/proxy_health") =>
|
(&Method::GET, "/proxy_health") =>
|
||||||
health_check_response(req),
|
health_check_response(req),
|
||||||
_ => {
|
_ => {
|
||||||
|
let _droppable_transaction = newrelic_logger3.web_transaction("unmatched endpoint");
|
||||||
let forward = router3.get_random_host();
|
let forward = router3.get_random_host();
|
||||||
info!("Forwarding to `{}` random host: {}", &forward, req.uri());
|
info!("Forwarding to `{}` random host: {}", &forward, req.uri());
|
||||||
hyper_reverse_proxy::call(remote_addr.ip(), &forward, req)
|
hyper_reverse_proxy::call(remote_addr.ip(), &forward, req)
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use anyhow::Result as AnyhowResult;
|
||||||
|
use newrelic::{App, Transaction};
|
||||||
|
|
||||||
|
pub struct NewRelicLogger {
|
||||||
|
newrelic_api: Option<App>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NewRelicLogger {
|
||||||
|
pub fn new(app_name: &str, api_key: &str) -> AnyhowResult<Self> {
|
||||||
|
let newrelic_api = App::new(app_name, api_key)?;
|
||||||
|
Ok(Self {
|
||||||
|
newrelic_api: Some(newrelic_api),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn null_instance() -> Self {
|
||||||
|
Self {
|
||||||
|
newrelic_api: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_new_or_null(app_name: &str, api_key: &str) -> Self {
|
||||||
|
match Self::new(app_name, api_key) {
|
||||||
|
Ok(instance) => instance,
|
||||||
|
Err(_) => Self::null_instance(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn web_transaction(&self, transaction_name: &str) -> Option<Transaction> {
|
||||||
|
if let Some(ref newrelic_api) = self.newrelic_api {
|
||||||
|
info!("Logging request to NewRelic");
|
||||||
|
return newrelic_api.web_transaction(transaction_name).ok();
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user