tracing_better_stack/config.rs
1use std::time::Duration;
2
3/// Configuration for the Better Stack tracing layer.
4///
5/// This struct contains all the configuration options for sending logs to Better Stack.
6/// Use [`BetterStackConfig::builder`] to create a new configuration.
7///
8/// # Example
9///
10/// ```rust
11/// use std::time::Duration;
12/// use tracing_better_stack::BetterStackConfig;
13///
14/// let config = BetterStackConfig::builder(
15/// "s1234567.us-east-9.betterstackdata.com",
16/// "source_token_here"
17/// )
18/// .batch_size(200)
19/// .batch_timeout(Duration::from_secs(10))
20/// .include_location(false)
21/// .build();
22/// ```
23#[derive(Debug, Clone)]
24pub struct BetterStackConfig {
25 /// The ingesting host provided by Better Stack for your source.
26 ///
27 /// This is the hostname where logs will be sent, without the protocol.
28 /// Better Stack provides unique hosts for each source, typically in the format:
29 /// `s1234567.us-east-9.betterstackdata.com`
30 ///
31 /// You can find this in your Better Stack dashboard when viewing your source.
32 pub ingesting_host: String,
33
34 /// The source token for authentication with Better Stack.
35 ///
36 /// This token authenticates your application with Better Stack.
37 /// It should be kept secret and not committed to version control.
38 /// You can find this in your Better Stack dashboard when viewing your source.
39 pub source_token: String,
40
41 /// Maximum number of events to batch before sending.
42 ///
43 /// Once this limit is reached, the batch will be sent immediately,
44 /// even if the batch timeout hasn't expired.
45 ///
46 /// Default: 100
47 pub batch_size: usize,
48
49 /// Maximum time to wait before sending a batch.
50 ///
51 /// If this duration elapses and there are any events in the batch,
52 /// they will be sent even if the batch size hasn't been reached.
53 ///
54 /// Default: 5 seconds
55 pub batch_timeout: Duration,
56
57 /// Maximum number of retry attempts for failed requests.
58 ///
59 /// When a request to Better Stack fails, the layer will retry
60 /// with exponential backoff up to this many times.
61 ///
62 /// Default: 3
63 pub max_retries: usize,
64
65 /// Initial delay before the first retry attempt.
66 ///
67 /// This delay will be doubled for each subsequent retry,
68 /// up to `max_retry_delay`.
69 ///
70 /// Default: 100ms
71 pub initial_retry_delay: Duration,
72
73 /// Maximum delay between retry attempts.
74 ///
75 /// The retry delay won't exceed this value, even with
76 /// exponential backoff.
77 ///
78 /// Default: 10 seconds
79 pub max_retry_delay: Duration,
80
81 /// Whether to include file and line location in log events.
82 ///
83 /// When enabled, adds a `location` field to each log event
84 /// containing the source file path and line number.
85 ///
86 /// Default: true
87 pub include_location: bool,
88
89 /// Whether to include span context in log events.
90 ///
91 /// When enabled, adds a `spans` field to each log event
92 /// containing information about the active spans and their fields.
93 ///
94 /// Default: true
95 pub include_spans: bool,
96}
97
98impl BetterStackConfig {
99 /// Creates a new configuration builder with the required ingesting host and source token.
100 ///
101 /// This is the recommended way to create a `BetterStackConfig`. The builder
102 /// provides a fluent API for setting optional configuration values.
103 ///
104 /// # Arguments
105 ///
106 /// * `ingesting_host` - The Better Stack ingesting host for your source
107 /// * `source_token` - Your Better Stack source token for authentication
108 ///
109 /// # Example
110 ///
111 /// ```rust
112 /// use tracing_better_stack::BetterStackConfig;
113 ///
114 /// let config = BetterStackConfig::builder(
115 /// "s1234567.us-east-9.betterstackdata.com",
116 /// "your_source_token"
117 /// )
118 /// .batch_size(50)
119 /// .build();
120 /// ```
121 pub fn builder(
122 ingesting_host: impl Into<String>,
123 source_token: impl Into<String>,
124 ) -> BetterStackConfigBuilder {
125 BetterStackConfigBuilder::new(ingesting_host, source_token)
126 }
127
128 /// Returns the full ingestion URL for sending logs to Better Stack.
129 ///
130 /// This is an internal method used by the sender module.
131 /// It constructs the complete URL from the ingesting host,
132 /// automatically adding the appropriate protocol:
133 /// - `https://` for production Better Stack hosts
134 /// - `http://` for localhost or 127.0.0.1 (useful for testing)
135 pub(crate) fn ingestion_url(&self) -> String {
136 // For testing with localhost, use http instead of https
137 if self.ingesting_host.starts_with("localhost")
138 || self.ingesting_host.starts_with("127.0.0.1")
139 {
140 format!("http://{}", self.ingesting_host)
141 } else {
142 format!("https://{}", self.ingesting_host)
143 }
144 }
145}
146
147/// Builder for creating a [`BetterStackConfig`] with a fluent API.
148///
149/// This builder is created via [`BetterStackConfig::builder`] and provides
150/// methods to customize the configuration before building the final config.
151///
152/// # Example
153///
154/// ```rust
155/// use std::time::Duration;
156/// use tracing_better_stack::BetterStackConfig;
157///
158/// let config = BetterStackConfig::builder(
159/// "s1234567.us-east-9.betterstackdata.com",
160/// "source_token"
161/// )
162/// .batch_size(200)
163/// .batch_timeout(Duration::from_secs(10))
164/// .max_retries(5)
165/// .include_location(false)
166/// .build();
167/// ```
168pub struct BetterStackConfigBuilder {
169 config: BetterStackConfig,
170}
171
172impl BetterStackConfigBuilder {
173 /// Creates a new builder with the required ingesting host and source token.
174 ///
175 /// This method is typically not called directly. Use [`BetterStackConfig::builder`] instead.
176 ///
177 /// # Arguments
178 ///
179 /// * `ingesting_host` - The Better Stack ingesting host for your source
180 /// * `source_token` - Your Better Stack source token for authentication
181 pub fn new(ingesting_host: impl Into<String>, source_token: impl Into<String>) -> Self {
182 Self {
183 config: BetterStackConfig {
184 ingesting_host: ingesting_host.into(),
185 source_token: source_token.into(),
186 batch_size: 100,
187 batch_timeout: Duration::from_secs(5),
188 max_retries: 3,
189 initial_retry_delay: Duration::from_millis(100),
190 max_retry_delay: Duration::from_secs(10),
191 include_location: true,
192 include_spans: true,
193 },
194 }
195 }
196
197 /// Sets the maximum number of events to batch before sending.
198 ///
199 /// Once this limit is reached, the batch will be sent immediately.
200 ///
201 /// Default: 100
202 ///
203 /// # Example
204 ///
205 /// ```rust
206 /// # use tracing_better_stack::BetterStackConfig;
207 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
208 /// .batch_size(200)
209 /// .build();
210 /// ```
211 pub fn batch_size(mut self, size: usize) -> Self {
212 self.config.batch_size = size;
213 self
214 }
215
216 /// Sets the maximum time to wait before sending a batch.
217 ///
218 /// If this duration elapses and there are any events in the batch,
219 /// they will be sent even if the batch size hasn't been reached.
220 ///
221 /// Default: 5 seconds
222 ///
223 /// # Example
224 ///
225 /// ```rust
226 /// # use std::time::Duration;
227 /// # use tracing_better_stack::BetterStackConfig;
228 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
229 /// .batch_timeout(Duration::from_secs(10))
230 /// .build();
231 /// ```
232 pub fn batch_timeout(mut self, timeout: Duration) -> Self {
233 self.config.batch_timeout = timeout;
234 self
235 }
236
237 /// Sets the maximum number of retry attempts for failed requests.
238 ///
239 /// When a request fails, the layer will retry with exponential backoff.
240 ///
241 /// Default: 3
242 ///
243 /// # Example
244 ///
245 /// ```rust
246 /// # use tracing_better_stack::BetterStackConfig;
247 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
248 /// .max_retries(5)
249 /// .build();
250 /// ```
251 pub fn max_retries(mut self, retries: usize) -> Self {
252 self.config.max_retries = retries;
253 self
254 }
255
256 /// Sets the initial delay before the first retry attempt.
257 ///
258 /// This delay will be doubled for each subsequent retry.
259 ///
260 /// Default: 100ms
261 ///
262 /// # Example
263 ///
264 /// ```rust
265 /// # use std::time::Duration;
266 /// # use tracing_better_stack::BetterStackConfig;
267 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
268 /// .initial_retry_delay(Duration::from_millis(200))
269 /// .build();
270 /// ```
271 pub fn initial_retry_delay(mut self, delay: Duration) -> Self {
272 self.config.initial_retry_delay = delay;
273 self
274 }
275
276 /// Sets the maximum delay between retry attempts.
277 ///
278 /// The retry delay won't exceed this value, even with exponential backoff.
279 ///
280 /// Default: 10 seconds
281 ///
282 /// # Example
283 ///
284 /// ```rust
285 /// # use std::time::Duration;
286 /// # use tracing_better_stack::BetterStackConfig;
287 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
288 /// .max_retry_delay(Duration::from_secs(30))
289 /// .build();
290 /// ```
291 pub fn max_retry_delay(mut self, delay: Duration) -> Self {
292 self.config.max_retry_delay = delay;
293 self
294 }
295
296 /// Sets whether to include file and line location in log events.
297 ///
298 /// When enabled, adds a `location` field to each log event.
299 ///
300 /// Default: true
301 ///
302 /// # Example
303 ///
304 /// ```rust
305 /// # use tracing_better_stack::BetterStackConfig;
306 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
307 /// .include_location(false)
308 /// .build();
309 /// ```
310 pub fn include_location(mut self, include: bool) -> Self {
311 self.config.include_location = include;
312 self
313 }
314
315 /// Sets whether to include span context in log events.
316 ///
317 /// When enabled, adds a `spans` field to each log event with active span information.
318 ///
319 /// Default: true
320 ///
321 /// # Example
322 ///
323 /// ```rust
324 /// # use tracing_better_stack::BetterStackConfig;
325 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
326 /// .include_spans(false)
327 /// .build();
328 /// ```
329 pub fn include_spans(mut self, include: bool) -> Self {
330 self.config.include_spans = include;
331 self
332 }
333
334 /// Builds the final [`BetterStackConfig`] with all the configured options.
335 ///
336 /// # Example
337 ///
338 /// ```rust
339 /// # use tracing_better_stack::BetterStackConfig;
340 /// let config = BetterStackConfig::builder("s1234567.us-east-9.betterstackdata.com", "your-source-token")
341 /// .batch_size(200)
342 /// .build(); // Returns the final BetterStackConfig
343 /// ```
344 pub fn build(self) -> BetterStackConfig {
345 self.config
346 }
347}