axum_prometheus/lifecycle/mod.rs
1//! Request lifecycle hooks that can be used to further customize how and what callbacks to run
2//! on events.
3//!
4//! `axum-prometheus` is built on top of lifecycle hooks. Using this module allows you to customize
5//! behavior even more.
6use bytes::Buf;
7use http::{HeaderMap, Request, Response};
8use tower_http::classify::ClassifiedResponse;
9
10mod body;
11mod future;
12pub mod layer;
13pub mod service;
14
15/// Trait that defines callbacks for [`LifeCycle`] to call.
16///
17/// [`LifeCycle`]: service::LifeCycle
18pub trait Callbacks<FailureClass>: Sized {
19 /// Additional data to attach to callbacks.
20 type Data;
21
22 /// Create an instance of `Self::Data` from the request.
23 ///
24 /// This method is called immediately after the request is received by [`Service::call`].
25 ///
26 /// The value returned here will be passed to the other methods in this trait.
27 ///
28 /// [`Service::call`]: tower::Service::call
29 fn prepare<B>(&mut self, request: &Request<B>) -> Self::Data;
30
31 /// Perform some action when a response has been generated.
32 ///
33 /// This method is called when the inner [`Service`]'s response future
34 /// completes with `Ok(response)`, regardless if the response is classified
35 /// as a success or a failure.
36 ///
37 /// If the response is the start of a stream (as determined by the
38 /// classifier passed to [`LifeCycle::new`] or [`LifeCycleLayer::new`]) then
39 /// `classification` will be [`ClassifiedResponse::RequiresEos(())`],
40 /// otherwise it will be [`ClassifiedResponse::Ready`].
41 ///
42 /// The default implementation does nothing and returns immediately.
43 ///
44 /// [`ClassifiedResponse::RequiresEos(())`]: tower_http::classify::ClassifiedResponse::RequiresEos
45 /// [`Service`]: tower::Service
46 /// [`LifeCycle::new`]: service::LifeCycle::new
47 /// [`LifeCycleLayer::new`]: layer::LifeCycleLayer::new
48 #[inline]
49 fn on_response<B>(
50 &mut self,
51 _response: &Response<B>,
52 _classification: ClassifiedResponse<FailureClass, ()>,
53 _data: &mut Self::Data,
54 ) {
55 }
56
57 /// Perform some action when a stream has ended.
58 ///
59 /// This is called when [`Body::poll_frame`] produces `Ok(trailers)` with the [`Frame::into_trailers`] method,
60 /// regardless if the trailers are classified as a failure.
61 ///
62 /// A stream that ends successfully will trigger two callbacks.
63 /// [`on_response`] will be called once the response has been generated and
64 /// the stream has started and [`on_eos`] will be called once the stream has
65 /// ended.
66 ///
67 /// If the trailers were classified as a success then `classification` will
68 /// be `Ok(())` otherwise `Err(failure_class)`.
69 ///
70 /// The default implementation does nothing and returns immediately.
71 ///
72 /// [`on_response`]: Callbacks::on_response
73 /// [`on_eos`]: Callbacks::on_eos
74 /// [`Body::poll_frame`]: http_body::Body::poll_frame
75 /// [`Frame::into_trailers`]: http_body::Frame::into_trailers
76 #[inline]
77 fn on_eos(
78 self,
79 _trailers: Option<&HeaderMap>,
80 _classification: Result<(), FailureClass>,
81 _data: Self::Data,
82 ) {
83 }
84
85 /// Perform some action when an error has been encountered.
86 ///
87 /// This method is only called in the following scenarios:
88 ///
89 /// - The inner [`Service`]'s response future resolves to an error.
90 /// - [`Body::poll_frame`] returns an error.
91 ///
92 /// That means this method is _not_ called if a response is classified as a
93 /// failure (then [`on_response`] is called) or an end-of-stream is
94 /// classified as a failure (then [`on_eos`] is called).
95 ///
96 /// `failed_at` specifies where the error happened.
97 ///
98 /// The default implementation does nothing and returns immediately.
99 ///
100 /// [`Service`]: tower::Service
101 /// [`on_response`]: Callbacks::on_response
102 /// [`on_eos`]: Callbacks::on_eos
103 /// [`Service::call`]: tower::Service::call
104 /// [`Body::poll_frame`]: http_body::Body::poll_frame
105 fn on_failure(
106 self,
107 _failed_at: FailedAt,
108 _failure_classification: FailureClass,
109 _data: &mut Self::Data,
110 ) {
111 }
112}
113
114/// A trait that allows to hook into [`http_body::Body::poll_frame`]'s lifecycle.
115pub trait OnBodyChunk<B: Buf> {
116 type Data;
117
118 /// Perform some action when a response body chunk has been generated.
119 ///
120 /// This is called when [`Body::poll_frame`] returns `Some(Ok(frame))`, and [`Frame::into_data`] returns with `Some(chunk)`,
121 /// regardless if the chunk is empty or not.
122 ///
123 /// The default implementation does nothing and returns immediately.
124 ///
125 /// [`Body::poll_frame`]: http_body::Body::poll_frame
126 /// [`Frame::into_data`]: http_body::Frame::into_data
127 #[inline]
128 fn call(&mut self, _body: &B, _exact_body_size: Option<u64>, _data: &mut Self::Data) {}
129}
130
131/// Enum used to specify where an error was encountered.
132#[derive(Debug)]
133pub enum FailedAt {
134 /// Generating the response failed.
135 Response,
136 /// Generating the response body failed.
137 Body,
138 /// Generating the response trailers failed.
139 Trailers,
140}