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}