timber_rust/factory/loki.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Dante Doménech Martinez dante19031999@gmail.com
3
4#![cfg(feature = "loki")]
5#![cfg_attr(docsrs, doc(cfg(feature = "loki")))]
6
7use crate::{Logger, LokiLogger, service};
8
9/// A factory for creating Grafana Loki loggers using a fluent builder pattern.
10///
11/// This factory provides two paths for construction:
12/// 1. **Standard**: Uses the default network-based Loki service.
13/// 2. **Injected**: Allows providing a custom implementation of the [`Loki`][service::Loki] trait.
14pub struct Loki {}
15
16/// A middle-state builder that holds the Loki configuration.
17///
18/// From here, you can either build a standard logger or transition to
19/// a service-injected state.
20pub struct LokiConfig {
21 config: service::LokiConfig,
22}
23
24/// A final-state builder that holds both configuration and a specific service implementation.
25///
26/// This state is typically used in unit tests to inject a mock Loki service
27/// or in specialized environments where a custom HTTP client is required.
28pub struct LokiFactoryService {
29 config: service::LokiConfig,
30 service: Box<dyn service::Loki + Send + Sync>,
31}
32
33impl Loki {
34 /// Begins the building process by providing a [`LokiConfig`].
35 pub fn config(self, config: service::LokiConfig) -> LokiConfig {
36 LokiConfig { config }
37 }
38
39 /// Shortcut to create a factory state with a pre-defined configuration and service.
40 pub fn service(
41 self,
42 config: service::LokiConfig,
43 service: Box<dyn service::Loki + Send + Sync>,
44 ) -> LokiFactoryService {
45 LokiFactoryService { config, service }
46 }
47}
48
49impl LokiConfig {
50 /// Creates a new LokiFactoryConfig
51 pub fn new(config: service::LokiConfig) -> Self {
52 Self { config }
53 }
54
55 /// Returns a reference to the internal configuration.
56 pub fn get_config(&self) -> &service::LokiConfig {
57 &self.config
58 }
59
60 /// Sets underlying configuration.
61 pub fn config(self, config: service::LokiConfig) -> Self {
62 Self { config, ..self }
63 }
64
65 /// Finalizes the builder and returns a high-level [`Logger`].
66 ///
67 /// This will initialize the default background worker and HTTP client.
68 pub fn build(self) -> Logger {
69 Logger::new(self.build_impl())
70 }
71
72 /// Builds the underlying [`LokiLogger`] implementation without the generic wrapper.
73 pub fn build_impl(self) -> Box<LokiLogger> {
74 LokiLogger::new(self.config)
75 }
76
77 /// Injects a custom service into the current building process.
78 ///
79 /// Use this to override the default networking logic.
80 pub fn service(self, service: Box<dyn service::Loki + Send + Sync>) -> LokiFactoryService {
81 LokiFactoryService {
82 config: self.config,
83 service,
84 }
85 }
86}
87
88impl LokiFactoryService {
89 /// Creates a new LokiFactoryService
90 pub fn new(config: service::LokiConfig, service: Box<dyn service::Loki + Send + Sync>) -> Self {
91 Self { config, service }
92 }
93
94 /// Returns a reference to the internal configuration.
95 pub fn get_config(&self) -> &service::LokiConfig {
96 &self.config
97 }
98
99 /// Returns a reference to the internal service.
100 pub fn get_service(&self) -> &(dyn service::Loki + Send + Sync) {
101 self.service.as_ref()
102 }
103
104 /// Sets underlying configuration.
105 pub fn config(self, config: service::LokiConfig) -> Self {
106 Self { config, ..self }
107 }
108
109 /// Sets the underlying service.
110 pub fn service(self, service: Box<dyn service::Loki + Send + Sync>) -> Self {
111 Self { service, ..self }
112 }
113
114 /// Finalizes the builder using the provided custom service and returns a [`Logger`].
115 pub fn build(self) -> Logger {
116 Logger::new(self.build_impl())
117 }
118
119 /// Builds the underlying [`LokiLogger`] using the custom service.
120 pub fn build_impl(self) -> Box<LokiLogger> {
121 LokiLogger::with_service(self.config, self.service)
122 }
123}