better_fetch/plugins/
logger.rs1use async_trait::async_trait;
2use tracing::{error, info, info_span, warn};
3
4use crate::hooks::{ErrorContext, Hooks};
5use crate::plugin::Plugin;
6
7#[derive(Debug, Clone)]
9pub struct LoggerPlugin {
10 pub enabled: bool,
12 pub verbose: bool,
14}
15
16impl LoggerPlugin {
17 pub fn new() -> Self {
19 Self {
20 enabled: true,
21 verbose: false,
22 }
23 }
24
25 pub fn enabled(mut self, enabled: bool) -> Self {
27 self.enabled = enabled;
28 self
29 }
30
31 pub fn verbose(mut self, verbose: bool) -> Self {
33 self.verbose = verbose;
34 self
35 }
36}
37
38impl Default for LoggerPlugin {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44#[async_trait]
45impl Plugin for LoggerPlugin {
46 fn id(&self) -> &'static str {
48 "logger"
49 }
50
51 fn hooks(&self) -> Hooks {
52 let enabled = self.enabled;
53 let verbose = self.verbose;
54
55 Hooks::new()
56 .on_request(move |ctx| {
57 let enabled = enabled;
58 let verbose = verbose;
59 async move {
60 if enabled {
61 let span = info_span!(
62 "http.request",
63 method = %ctx.method,
64 url = %ctx.url,
65 retry_attempt = ctx.retry_attempt,
66 );
67 let _guard = span.enter();
68 if verbose {
69 info!("better-fetch request");
70 } else {
71 info!("better-fetch request");
72 }
73 }
74 Ok(ctx)
75 }
76 })
77 .on_response_stream({
78 let enabled = self.enabled;
79 let verbose = self.verbose;
80 move |ctx| {
81 let enabled = enabled;
82 let verbose = verbose;
83 async move {
84 if enabled {
85 let span = info_span!(
86 "http.response",
87 status = %ctx.status,
88 url = %ctx.request.url,
89 streaming = true,
90 );
91 let _guard = span.enter();
92 if verbose {
93 info!("better-fetch stream response");
94 } else {
95 info!("better-fetch stream response");
96 }
97 }
98 Ok(crate::hooks::StreamingResponseMeta {
99 status: ctx.status,
100 headers: ctx.headers,
101 })
102 }
103 }
104 })
105 .on_response({
106 let enabled = self.enabled;
107 let verbose = self.verbose;
108 move |ctx| {
109 let enabled = enabled;
110 let verbose = verbose;
111 async move {
112 if enabled {
113 let status = ctx.response.status();
114 let span = info_span!(
115 "http.response",
116 status = %status,
117 url = %ctx.request.url,
118 streaming = false,
119 );
120 let _guard = span.enter();
121 if verbose {
122 info!("better-fetch response");
123 } else {
124 info!("better-fetch response");
125 }
126 }
127 Ok(ctx.response)
128 }
129 }
130 })
131 .on_retry({
132 let enabled = self.enabled;
133 move |ctx| {
134 let enabled = enabled;
135 async move {
136 if enabled {
137 warn!(
138 retry_attempt = ctx.request.retry_attempt,
139 next_attempt = ctx.request.retry_attempt + 1,
140 status = %ctx.response.status(),
141 url = %ctx.request.url,
142 "better-fetch retry"
143 );
144 }
145 }
146 }
147 })
148 .on_error({
149 let enabled = self.enabled;
150 move |ctx: ErrorContext| {
151 let enabled = enabled;
152 async move {
153 if enabled {
154 let status = ctx.response.as_ref().map(|r| r.status().as_u16());
155 let body_preview = ctx.response_body_preview(256);
156 error!(
157 error = %ctx.error,
158 url = %ctx.request.url,
159 ?status,
160 body_preview = body_preview.as_deref(),
161 retry_attempt = ctx.request.retry_attempt,
162 "better-fetch error"
163 );
164 }
165 }
166 }
167 })
168 }
169}