use super::{Latency, DEFAULT_ERROR_LEVEL};
use crate::LatencyUnit;
use std::{fmt, time::Duration};
use tracing::{Level, Span};
pub trait OnFailure<FailureClass> {
fn on_failure(&mut self, failure_classification: FailureClass, latency: Duration, span: &Span);
}
impl<FailureClass> OnFailure<FailureClass> for () {
#[inline]
fn on_failure(&mut self, _: FailureClass, _: Duration, _: &Span) {}
}
impl<F, FailureClass> OnFailure<FailureClass> for F
where
F: FnMut(FailureClass, Duration, &Span),
{
fn on_failure(&mut self, failure_classification: FailureClass, latency: Duration, span: &Span) {
self(failure_classification, latency, span)
}
}
#[derive(Clone, Debug)]
pub struct DefaultOnFailure {
level: Level,
latency_unit: LatencyUnit,
}
impl Default for DefaultOnFailure {
fn default() -> Self {
Self {
level: DEFAULT_ERROR_LEVEL,
latency_unit: LatencyUnit::Millis,
}
}
}
impl DefaultOnFailure {
pub fn new() -> Self {
Self::default()
}
pub fn level(mut self, level: Level) -> Self {
self.level = level;
self
}
pub fn latency_unit(mut self, latency_unit: LatencyUnit) -> Self {
self.latency_unit = latency_unit;
self
}
}
impl<FailureClass> OnFailure<FailureClass> for DefaultOnFailure
where
FailureClass: fmt::Display,
{
fn on_failure(&mut self, failure_classification: FailureClass, latency: Duration, _: &Span) {
let latency = Latency {
unit: self.latency_unit,
duration: latency,
};
event_dynamic_lvl!(
self.level,
classification = %failure_classification,
%latency,
"response failed"
);
}
}