Spaces:
Build error
Build error
File size: 2,869 Bytes
d8435ba |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
use std::future::{ready, Ready};
use std::sync::Arc;
use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
use actix_web::Error;
use futures_util::future::LocalBoxFuture;
use parking_lot::Mutex;
use crate::common::telemetry_ops::requests_telemetry::{
ActixTelemetryCollector, ActixWorkerTelemetryCollector,
};
pub struct ActixTelemetryService<S> {
service: S,
telemetry_data: Arc<Mutex<ActixWorkerTelemetryCollector>>,
}
pub struct ActixTelemetryTransform {
telemetry_collector: Arc<Mutex<ActixTelemetryCollector>>,
}
/// Actix telemetry service. It hooks every request and looks into response status code.
///
/// More about actix service with similar example
/// <https://actix.rs/docs/middleware/>
impl<S, B> Service<ServiceRequest> for ActixTelemetryService<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
actix_web::dev::forward_ready!(service);
fn call(&self, request: ServiceRequest) -> Self::Future {
let match_pattern = request
.match_pattern()
.unwrap_or_else(|| "unknown".to_owned());
let request_key = format!("{} {}", request.method(), match_pattern);
let future = self.service.call(request);
let telemetry_data = self.telemetry_data.clone();
Box::pin(async move {
let instant = std::time::Instant::now();
let response = future.await?;
let status = response.response().status().as_u16();
telemetry_data
.lock()
.add_response(request_key, status, instant);
Ok(response)
})
}
}
impl ActixTelemetryTransform {
pub fn new(telemetry_collector: Arc<Mutex<ActixTelemetryCollector>>) -> Self {
Self {
telemetry_collector,
}
}
}
/// Actix telemetry transform. It's a builder for an actix service
///
/// More about actix transform with similar example
/// <https://actix.rs/docs/middleware/>
impl<S, B> Transform<S, ServiceRequest> for ActixTelemetryTransform
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Transform = ActixTelemetryService<S>;
type InitError = ();
type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(ActixTelemetryService {
service,
telemetry_data: self
.telemetry_collector
.lock()
.create_web_worker_telemetry(),
}))
}
}
|