timber_rust/logger/
base.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Dante Doménech Martinez dante19031999@gmail.com
3
4use crate::logger::loggable::Loggable;
5use crate::{LoggerStatus, Message};
6use std::any::Any;
7use std::sync::Arc;
8
9/// The core interface for logging backends (e.g., File, Console, Network).
10///
11/// Implementors must be [`Send`] and [`Sync`] to allow the [Logger] to be shared
12/// across multiple threads. The [`Any`] bound enables runtime type introspection
13/// via the `as_any` method.
14pub trait LoggerImpl: Send + Sync + Any {
15    /// Returns the current [LoggerStatus] of the logging backend.
16    ///
17    /// This provides a quick check to see if the logging service is [`Running`][`LoggerStatus::Running`]
18    /// or has become [`Broken`][`LoggerStatus::Broken`] (e.g., due to a disk failure or network disconnection).
19    /// The specific behavior is determined by the implementation.
20    fn status(&self) -> LoggerStatus;
21
22    /// Processes a single [Message]. The specific behavior (writing to disk,
23    /// printing, etc.) is determined by the implementation.
24    fn log(&self, message: Message);
25
26    /// Returns a reference to the underlying type as [Any] for downcasting.
27    fn as_any(&self) -> &dyn Any;
28}
29
30/// A thread-safe, high-level wrapper around a logging implementation.
31///
32/// [`Logger`] acts as the primary entry point for the application. It uses
33/// an [`Arc`] internally to allow cheap cloning and safe sharing across
34/// asynchronous tasks or threads.
35///
36/// Loggers can be easily built using [`LoggerFactory`][`crate::LoggerFactory`].
37///
38/// Because it uses an [`Arc`] internally, cloning a [Logger] is extremely cheap—
39/// it only increments a reference count. This allows you to pass the logger
40/// into multiple threads, closures, or asynchronous tasks easily.
41#[derive(Clone)]
42pub struct Logger {
43    m_impl: Arc<dyn LoggerImpl + Send + Sync>,
44}
45
46impl Logger {
47    /// Creates a new [`Logger`] instance with the specified [backend implementation][`crate::LoggerImpl`].
48    ///
49    /// # Example
50    /// ```
51    /// # use timber_rust::Logger;
52    /// # use timber_rust::SilentLogger;
53    /// let logger = Logger::new(SilentLogger::new());
54    /// ```
55    pub fn new(implementation: Box<dyn LoggerImpl + Send + Sync>) -> Logger {
56        Logger {
57            m_impl: Arc::from(implementation),
58        }
59    }
60
61    /// Returns the current [LoggerStatus] of the underlying logging backend.
62    ///
63    /// This provides a quick check to see if the logging service is [`Running`][`LoggerStatus::Running`]
64    /// or has become [`Broken`][`LoggerStatus::Broken`] (e.g., due to a disk failure or network disconnection).
65    pub fn status(&self) -> LoggerStatus {
66        self.m_impl.status()
67    }
68
69    /// Logs an entry that implements the [Loggable] trait.
70    ///
71    /// This method uses static dispatch (monomorphization) to resolve the
72    /// input `T` into a [Message] before passing it to the internal implementation.
73    ///
74    /// The enumeration [`LogLevel`][`crate::LogLevel`] implements [`Display`][`std::fmt::Display`] and can be used as levels.
75    ///
76    /// # Returns
77    /// Returns a reference to `self` to enable **Method Chaining** (Fluent API).
78    ///
79    /// # Example
80    /// ```
81    /// # use timber_rust::Logger;
82    /// # use timber_rust::SilentLogger;
83    /// # use timber_rust::LogLevel;
84    /// # let logger = Logger::new(SilentLogger::new());
85    /// logger.log((LogLevel::Info, "Step 1"))
86    ///       .log((LogLevel::Info, "Step 2"));
87    /// ```
88    ///
89    /// # Arguments
90    /// * `message` - Anything that can be converted into a log message,
91    ///   typically a tuple such as `(Level::Info, "Hello World")`.
92    pub fn log<T: Loggable>(&self, message: T) -> &Logger {
93        self.m_impl.log(message.to_message());
94        self
95    }
96
97    /// Provides access to the underlying [LoggerImpl].
98    ///
99    /// This is useful for accessing backend-specific methods or performing
100    /// downcasts via [Any].
101    pub fn get_implementation(&self) -> &dyn LoggerImpl {
102        &*self.m_impl
103    }
104
105    /// Destroys the logger and returns the underlying [LoggerImpl].
106    ///
107    /// Another logger may be using this implementation elsewhere.
108    ///
109    /// This is useful for accessing backend-specific methods or performing
110    /// downcasts via [Any].
111    pub fn take_implementation(self) -> Arc<dyn LoggerImpl> {
112        self.m_impl
113    }
114}