timber_rust/factory/vec.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Dante Doménech Martinez dante19031999@gmail.com
3
4use crate::{Concurrency, DirectLogger, Logger, QueuedLogger, service};
5
6/// A factory for creating loggers that store messages in an in-memory [`Vec`].
7///
8/// The `Vector` factory is ideal for unit testing, allowing you to capture
9/// logs in a thread-safe list and verify them later. Unlike string-based loggers,
10/// this preserves the structured [`Message`][`crate::Message`] data.
11///
12/// ### Default Configuration
13/// - **Capacity**: `1024` (Pre-allocated slots for log messages).
14/// - **Max Retries**: `3` (Attempts to re-send if the buffer is temporarily locked).
15/// - **Worker Count**: `1` (Ensures sequential insertion order in async mode).
16pub struct Vector {
17 capacity: usize,
18 max_retries: usize,
19 worker_count: usize,
20}
21
22impl Vector {
23 /// Creates a new `Vector` factory with explicit settings.
24 pub fn new(capacity: usize, max_retries: usize, worker_count: usize) -> Self {
25 Self {
26 capacity,
27 max_retries,
28 worker_count,
29 }
30 }
31
32 /// Returns the initial pre-allocated capacity for the message buffer.
33 pub fn get_capacity(&self) -> usize {
34 self.capacity
35 }
36
37 /// Returns the currently configured maximum retry attempts.
38 pub fn get_max_retries(&self) -> usize {
39 self.max_retries
40 }
41
42 /// Returns the currently configured background worker count.
43 pub fn get_worker_count(&self) -> usize {
44 self.worker_count
45 }
46
47 /// Sets the initial capacity of the internal vector.
48 ///
49 /// Pre-allocating capacity helps avoid expensive reallocations during
50 /// high-frequency logging events.
51 pub fn capacity(self, capacity: usize) -> Self {
52 Self { capacity, ..self }
53 }
54
55 /// Updates the maximum number of retry attempts for the buffer.
56 pub fn max_retries(self, max_retries: usize) -> Self {
57 Self {
58 max_retries,
59 ..self
60 }
61 }
62
63 /// Updates the background worker count.
64 ///
65 /// Note: Using multiple workers with a vector may result in logs being
66 /// inserted out of chronological order.
67 pub fn worker_count(self, worker_count: usize) -> Self {
68 Self {
69 worker_count,
70 ..self
71 }
72 }
73
74 /// Finalizes the builder and returns a high-level [`Logger`].
75 pub fn build(self, concurrency: Concurrency) -> Logger {
76 match concurrency {
77 Concurrency::Sync => Logger::new(self.build_impl_direct()),
78 Concurrency::Async => Logger::new(self.build_impl_queued()),
79 }
80 }
81
82 /// Builds the underlying [`DirectLogger`] implementation.
83 pub fn build_impl_direct(self) -> Box<DirectLogger> {
84 let max_retries = self.max_retries;
85 DirectLogger::new(self.build_service(), max_retries)
86 }
87
88 /// Builds the underlying [`QueuedLogger`] implementation.
89 pub fn build_impl_queued(self) -> Box<QueuedLogger> {
90 let max_retries = self.max_retries;
91 let worker_count = self.worker_count;
92 QueuedLogger::new(self.build_service(), max_retries, worker_count)
93 }
94
95 /// Internal helper to construct the [`service::Vector`] instance.
96 pub fn build_service(self) -> Box<service::Vector> {
97 service::Vector::new(self.capacity)
98 }
99}
100
101impl Default for Vector {
102 /// Provides sensible defaults for in-memory message capturing.
103 ///
104 /// - **capacity**: `1024`
105 /// - **max_retries**: `3`
106 /// - **worker_count**: `1`
107 fn default() -> Self {
108 Self {
109 capacity: 1024usize,
110 max_retries: 3,
111 worker_count: 1,
112 }
113 }
114}