diff options
author | Alex Auvolat <alex@adnab.me> | 2022-12-05 18:43:48 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2022-12-05 18:43:48 +0100 |
commit | 5d38f2cf7f312de69a3106556fc43219ca1473c3 (patch) | |
tree | 2ecc767ffeae5dd9b4a528f8294a61385a1fb5b1 /src/https.rs | |
parent | 43a0fe14b2ae6a3e97f39169cda7ca5579a3259c (diff) | |
download | tricot-5d38f2cf7f312de69a3106556fc43219ca1473c3.tar.gz tricot-5d38f2cf7f312de69a3106556fc43219ca1473c3.zip |
Add basic support for metrics
Diffstat (limited to 'src/https.rs')
-rw-r--r-- | src/https.rs | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/src/https.rs b/src/https.rs index ba4365d..cb5e1c8 100644 --- a/src/https.rs +++ b/src/https.rs @@ -21,6 +21,8 @@ use tokio::sync::watch; use tokio_rustls::TlsAcceptor; use tokio_util::io::{ReaderStream, StreamReader}; +use opentelemetry::{metrics, KeyValue}; + use crate::cert_store::{CertStore, StoreResolver}; use crate::proxy_config::ProxyConfig; use crate::reverse_proxy; @@ -33,6 +35,11 @@ pub struct HttpsConfig { pub compress_mime_types: Vec<String>, } +struct HttpsMetrics { + requests_received: metrics::Counter<u64>, + requests_served: metrics::Counter<u64>, +} + pub async fn serve_https( config: HttpsConfig, cert_store: Arc<CertStore>, @@ -41,6 +48,18 @@ pub async fn serve_https( ) -> Result<()> { let config = Arc::new(config); + let meter = opentelemetry::global::meter("tricot"); + let metrics = Arc::new(HttpsMetrics { + requests_received: meter + .u64_counter("https_requests_received") + .with_description("Total number of requests received over HTTPS") + .init(), + requests_served: meter + .u64_counter("https_requests_served") + .with_description("Total number of requests served over HTTPS") + .init(), + }); + let mut tls_cfg = rustls::ServerConfig::builder() .with_safe_defaults() .with_no_client_auth() @@ -71,6 +90,7 @@ pub async fn serve_https( let rx_proxy_config = rx_proxy_config.clone(); let tls_acceptor = tls_acceptor.clone(); let config = config.clone(); + let metrics = metrics.clone(); let mut must_exit_2 = must_exit.clone(); let conn = tokio::spawn(async move { @@ -84,7 +104,8 @@ pub async fn serve_https( let https_config = config.clone(); let proxy_config: Arc<ProxyConfig> = rx_proxy_config.borrow().clone(); - handle_outer(remote_addr, req, https_config, proxy_config) + let metrics = metrics.clone(); + handle_outer(remote_addr, req, https_config, proxy_config, metrics) }), ) .with_upgrades(); @@ -124,17 +145,43 @@ async fn handle_outer( req: Request<Body>, https_config: Arc<HttpsConfig>, proxy_config: Arc<ProxyConfig>, + metrics: Arc<HttpsMetrics>, ) -> Result<Response<Body>, Infallible> { - match handle(remote_addr, req, https_config, proxy_config).await { + let mut tags = vec![ + KeyValue::new("method", req.method().to_string()), + KeyValue::new( + "host", + req.uri() + .authority() + .map(|auth| auth.to_string()) + .or_else(|| { + req.headers() + .get("host") + .map(|host| host.to_str().unwrap_or_default().to_string()) + }) + .unwrap_or_default(), + ), + ]; + metrics.requests_received.add(1, &tags); + + let resp = match handle(remote_addr, req, https_config, proxy_config, &mut tags).await { Err(e) => { warn!("Handler error: {}", e); - Ok(Response::builder() + Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("{}", e))) - .unwrap()) + .unwrap() } - Ok(r) => Ok(r), - } + Ok(r) => r, + }; + + tags.push(KeyValue::new( + "response_code", + resp.status().as_u16().to_string(), + )); + metrics.requests_served.add(1, &tags); + + Ok(resp) } // Custom echo service, handling two different routes and a @@ -144,6 +191,7 @@ async fn handle( req: Request<Body>, https_config: Arc<HttpsConfig>, proxy_config: Arc<ProxyConfig>, + tags: &mut Vec<KeyValue>, ) -> Result<Response<Body>, anyhow::Error> { let method = req.method().clone(); let uri = req.uri().to_string(); @@ -184,6 +232,18 @@ async fn handle( }); if let Some(proxy_to) = best_match { + tags.push(KeyValue::new("service_name", proxy_to.service_name.clone())); + tags.push(KeyValue::new( + "target_addr", + proxy_to.target_addr.to_string(), + )); + tags.push(KeyValue::new( + "https_target", + proxy_to.https_target.to_string(), + )); + tags.push(KeyValue::new("same_node", proxy_to.same_node.to_string())); + tags.push(KeyValue::new("same_site", proxy_to.same_site.to_string())); + proxy_to.calls.fetch_add(1, Ordering::SeqCst); debug!("{}{} -> {}", host, path, proxy_to); |