diff --git a/src/server/metrics.rs b/src/server/metrics.rs index 66d0d77eb5..7dedf1a221 100644 --- a/src/server/metrics.rs +++ b/src/server/metrics.rs @@ -23,9 +23,9 @@ pub struct MetricTimer { #[derive(Debug, Clone)] pub struct Metrics { - client: Option, - tags: Option, - timer: Option, + pub client: Option, + pub tags: Option, + pub timer: Option, } impl Drop for Metrics { @@ -63,21 +63,27 @@ impl FromRequest for Metrics { type Future = Ready>; fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { - let exts = req.extensions(); - let def_tags = Tags::from(req.head()); - let tags = exts.get::().unwrap_or(&def_tags); - - future::ok(Metrics { - client: match req.app_data::>() { - Some(v) => Some(*v.metrics.clone()), - None => { - warn!("⚠️ metric error: No App State"); - None - } - }, - tags: Some(tags.clone()), - timer: None, - }) + future::ok(metrics_from_request( + req, + req.app_data::>() + .map(|state| state.metrics.clone()), + )) + } +} + +pub fn metrics_from_request(req: &HttpRequest, client: Option>) -> Metrics { + let exts = req.extensions(); + let def_tags = Tags::from(req.head()); + let tags = exts.get::().unwrap_or(&def_tags); + + if client.is_none() { + warn!("⚠️ metric error: No App State"); + } + + Metrics { + client: client.as_deref().cloned(), + tags: Some(tags.clone()), + timer: None, } } diff --git a/src/tokenserver/extractors.rs b/src/tokenserver/extractors.rs index 19200fea3d..e25840481e 100644 --- a/src/tokenserver/extractors.rs +++ b/src/tokenserver/extractors.rs @@ -12,7 +12,7 @@ use actix_web::{ Error, FromRequest, HttpRequest, }; use actix_web_httpauth::extractors::bearer::BearerAuth; -use futures::future::LocalBoxFuture; +use futures::future::{self, LocalBoxFuture, Ready}; use hmac::{Hmac, Mac, NewMac}; use lazy_static::lazy_static; use regex::Regex; @@ -22,8 +22,8 @@ use sha2::Sha256; use super::db::{models::Db, params, pool::DbPool, results}; use super::error::{ErrorLocation, TokenserverError}; use super::support::TokenData; -use super::{LogItemsMutator, NodeType, ServerState}; -use crate::server::metrics::Metrics; +use super::{LogItemsMutator, NodeType, ServerState, TokenserverMetrics}; +use crate::server::metrics; use crate::settings::Secrets; lazy_static! { @@ -329,7 +329,7 @@ impl FromRequest for TokenData { let state = get_server_state(&req)?.as_ref().as_ref().unwrap(); let oauth_verifier = state.oauth_verifier.clone(); - let mut metrics = Metrics::extract(&req).await?; + let TokenserverMetrics(mut metrics) = TokenserverMetrics::extract(&req).await?; metrics.start_timer("tokenserver.oauth_token_verification", None); web::block(move || oauth_verifier.verify_token(auth.token())) @@ -419,6 +419,26 @@ impl FromRequest for KeyId { } } +impl FromRequest for TokenserverMetrics { + type Config = (); + type Error = Error; + type Future = Ready>; + + fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future { + let state = match get_server_state(req) { + // XXX: Tokenserver state will no longer be an Option once the Tokenserver + // code is rolled out, so we will eventually be able to remove this unwrap(). + Ok(state) => state.as_ref().as_ref().unwrap(), + Err(e) => return future::err(e), + }; + + future::ok(TokenserverMetrics(metrics::metrics_from_request( + req, + Some(state.metrics.clone()), + ))) + } +} + fn get_server_state(req: &HttpRequest) -> Result<&Data>, Error> { req.app_data::>>().ok_or_else(|| { error!("⚠️ Could not load the app state"); diff --git a/src/tokenserver/mod.rs b/src/tokenserver/mod.rs index 9857e4e0d3..5669ef1520 100644 --- a/src/tokenserver/mod.rs +++ b/src/tokenserver/mod.rs @@ -85,6 +85,8 @@ impl ServerState { } } +pub struct TokenserverMetrics(Metrics); + #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub enum NodeType { #[serde(rename = "mysql")]