tower_http/trace/
on_failure.rs1use super::{Latency, DEFAULT_ERROR_LEVEL};
2use crate::LatencyUnit;
3use std::{fmt, time::Duration};
4use tracing::{Level, Span};
5
6pub trait OnFailure<FailureClass> {
13    fn on_failure(&mut self, failure_classification: FailureClass, latency: Duration, span: &Span);
25}
26
27impl<FailureClass> OnFailure<FailureClass> for () {
28    #[inline]
29    fn on_failure(&mut self, _: FailureClass, _: Duration, _: &Span) {}
30}
31
32impl<F, FailureClass> OnFailure<FailureClass> for F
33where
34    F: FnMut(FailureClass, Duration, &Span),
35{
36    fn on_failure(&mut self, failure_classification: FailureClass, latency: Duration, span: &Span) {
37        self(failure_classification, latency, span)
38    }
39}
40
41#[derive(Clone, Debug)]
45pub struct DefaultOnFailure {
46    level: Level,
47    latency_unit: LatencyUnit,
48}
49
50impl Default for DefaultOnFailure {
51    fn default() -> Self {
52        Self {
53            level: DEFAULT_ERROR_LEVEL,
54            latency_unit: LatencyUnit::Millis,
55        }
56    }
57}
58
59impl DefaultOnFailure {
60    pub fn new() -> Self {
62        Self::default()
63    }
64
65    pub fn level(mut self, level: Level) -> Self {
71        self.level = level;
72        self
73    }
74
75    pub fn latency_unit(mut self, latency_unit: LatencyUnit) -> Self {
79        self.latency_unit = latency_unit;
80        self
81    }
82}
83
84impl<FailureClass> OnFailure<FailureClass> for DefaultOnFailure
85where
86    FailureClass: fmt::Display,
87{
88    fn on_failure(&mut self, failure_classification: FailureClass, latency: Duration, _: &Span) {
89        let latency = Latency {
90            unit: self.latency_unit,
91            duration: latency,
92        };
93        event_dynamic_lvl!(
94            self.level,
95            classification = %failure_classification,
96            %latency,
97            "response failed"
98        );
99    }
100}