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}