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}