quill
LoggerBase.h
1 
7 #pragma once
8 
9 #include "quill/core/Attributes.h"
10 #include "quill/core/Common.h"
11 #include "quill/core/LogLevel.h"
12 #include "quill/core/PatternFormatterOptions.h"
13 #include "quill/core/QuillError.h"
14 #include "quill/core/ThreadContextManager.h"
15 
16 #include <atomic>
17 #include <memory>
18 #include <string>
19 #include <vector>
20 
21 QUILL_BEGIN_NAMESPACE
22 
24 QUILL_BEGIN_EXPORT
25 
26 class Sink;
27 class PatternFormatter;
28 class UserClockSource;
29 
30 QUILL_END_EXPORT
31 
32 namespace detail
33 {
34 class BackendWorker;
35 class BacktraceStorage;
36 class LoggerManager;
37 
38 /***/
40 {
41 public:
42  /***/
43  LoggerBase(std::string logger_name, std::vector<std::shared_ptr<Sink>> sinks,
44  PatternFormatterOptions pattern_formatter_options, ClockSourceType clock_source,
45  UserClockSource* user_clock)
46  : _logger_name(static_cast<std::string&&>(logger_name)),
47  _user_clock(user_clock),
48  _clock_source(clock_source),
49  _pattern_formatter_options(static_cast<PatternFormatterOptions&&>(pattern_formatter_options))
50  {
51  for (auto const& sink : sinks)
52  {
53  if (QUILL_UNLIKELY(!sink))
54  {
55  QUILL_THROW(QuillError{"sink pointer is nullptr in LoggerBase constructor"});
56  }
57  }
58 
59  this->_sinks = static_cast<std::vector<std::shared_ptr<Sink>>&&>(sinks);
60  }
61 
62  /***/
63  LoggerBase(LoggerBase const&) = delete;
64  LoggerBase& operator=(LoggerBase const&) = delete;
65 
66  /***/
67  virtual ~LoggerBase() = default;
68 
73  QUILL_NODISCARD std::string const& get_logger_name() const noexcept { return _logger_name; }
74 
79  QUILL_NODISCARD UserClockSource* get_user_clock_source() const noexcept { return _user_clock; }
80 
85  QUILL_NODISCARD ClockSourceType get_clock_source_type() const noexcept { return _clock_source; }
86 
91  QUILL_NODISCARD PatternFormatterOptions const& get_pattern_formatter_options() const noexcept
92  {
93  return _pattern_formatter_options;
94  }
95 
101  QUILL_NODISCARD std::vector<std::shared_ptr<Sink>> const& get_sinks() const noexcept
102  {
103  return _sinks;
104  }
105 
109  void mark_invalid() { _valid.store(false, std::memory_order_release); }
110 
115  QUILL_NODISCARD bool is_valid_logger() const noexcept
116  {
117  return _valid.load(std::memory_order_acquire);
118  }
119 
123  QUILL_NODISCARD LogLevel get_log_level() const noexcept
124  {
125  auto const* self = this;
126 
127 #if defined(__GNUC__) && !defined(__clang__)
128  // GCC warns about potential null pointer access when logger might be
129  // uninitialized during LTO analysis
130  asm volatile("" : "+r"(self) : : "memory");
131 #endif
132 
133  return self->_log_level.load(std::memory_order_relaxed);
134  }
135 
140  void set_log_level(LogLevel new_log_level)
141  {
142  if (QUILL_UNLIKELY(new_log_level == LogLevel::Backtrace))
143  {
144  QUILL_THROW(QuillError{"LogLevel::Backtrace is only used internally. Please don't use it."});
145  }
146 
147  _log_level.store(new_log_level, std::memory_order_relaxed);
148  }
149 
166  void set_immediate_flush(uint32_t flush_every_n_messages = 1)
167  {
168  _message_flush_threshold.store(flush_every_n_messages, std::memory_order_relaxed);
169  }
170 
175  template <LogLevel log_statement_level>
176  QUILL_NODISCARD QUILL_ATTRIBUTE_HOT bool should_log_statement() const noexcept
177  {
178  return log_statement_level >= get_log_level();
179  }
180 
186  QUILL_NODISCARD QUILL_ATTRIBUTE_HOT bool should_log_statement(LogLevel log_statement_level) const noexcept
187  {
188  return log_statement_level >= get_log_level();
189  }
190 
191  /***/
192  QUILL_NODISCARD static bool is_current_thread_backend_thread() noexcept
193  {
194  return _is_backend_thread;
195  }
196 
197 protected:
198  friend class BackendWorker;
199  friend class LoggerManager;
200 
201  /***/
202  static void set_current_thread_is_backend_thread(bool value) noexcept
203  {
204  _is_backend_thread = value;
205  }
206 
207  static inline QUILL_THREAD_LOCAL ThreadContext* _thread_context = nullptr; /* Set and accessed by the frontend */
208  static inline QUILL_THREAD_LOCAL bool _is_backend_thread{false}; /* Set and read by the current thread */
209 
210  // -- frontend access BEGIN --
211  std::string _logger_name; /* Set by the frontend once, accessed by the frontend AND backend */
212  UserClockSource* _user_clock{nullptr}; /* A non-owned pointer to a custom timestamp clock, valid only when provided. used by frontend only */
213  std::atomic<uint32_t> _message_flush_threshold{0}; /* used by frontend only */
214  std::atomic<uint32_t> _messages_since_last_flush{0}; /* used by frontend only */
215  ClockSourceType const _clock_source; /* Set once during construction and accessed by the frontend AND backend */
216  std::atomic<LogLevel> _log_level{LogLevel::Info}; /* used by frontend only */
217  std::atomic<LogLevel> _backtrace_flush_level{LogLevel::None};
218  std::atomic<bool> _valid{true}; /* Updated by the frontend at any time, accessed by the backend */
219  // -- frontend access END --
220 
221  // -- backend access BEGIN (immutable after construction, no false sharing concern) --
222  PatternFormatterOptions _pattern_formatter_options; /* Set by the frontend once and accessed by the backend to initialise PatternFormatter */
223  std::vector<std::shared_ptr<Sink>> _sinks; /* Set by the frontend once and accessed by the backend */
224  std::shared_ptr<PatternFormatter> _pattern_formatter; /* The backend thread will set this once, we never access it on the frontend */
225  std::shared_ptr<BacktraceStorage> _backtrace_storage; /* The backend thread will construct this, we never access it on the frontend */
226 };
227 } // namespace detail
228 
229 QUILL_END_NAMESPACE
QUILL_NODISCARD QUILL_ATTRIBUTE_HOT bool should_log_statement() const noexcept
Checks if the given log_statement_level can be logged by this logger.
Definition: LoggerBase.h:176
QUILL_NODISCARD QUILL_ATTRIBUTE_HOT bool should_log_statement(LogLevel log_statement_level) const noexcept
Checks if the given log_statement_level can be logged by this logger.
Definition: LoggerBase.h:186
QUILL_NODISCARD std::string const & get_logger_name() const noexcept
Returns the name of the logger.
Definition: LoggerBase.h:73
std::atomic< bool > _valid
Updated by the frontend at any time, accessed by the backend.
Definition: LoggerBase.h:218
Base class for sinks.
Definition: Sink.h:46
QUILL_NODISCARD ClockSourceType get_clock_source_type() const noexcept
Returns the type of clock source being used.
Definition: LoggerBase.h:85
Definition: PatternFormatter.h:35
QUILL_NODISCARD PatternFormatterOptions const & get_pattern_formatter_options() const noexcept
Returns the pattern formatter options.
Definition: LoggerBase.h:91
QUILL_NODISCARD bool is_valid_logger() const noexcept
Checks if the logger is valid.
Definition: LoggerBase.h:115
Configuration options for the PatternFormatter.
Definition: PatternFormatterOptions.h:24
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28
void set_immediate_flush(uint32_t flush_every_n_messages=1)
Sets the flush interval for logging based on message count.
Definition: LoggerBase.h:166
Definition: base.h:2200
QUILL_NODISCARD std::vector< std::shared_ptr< Sink > > const & get_sinks() const noexcept
Returns a const reference to the sinks vector.
Definition: LoggerBase.h:101
Definition: LoggerBase.h:39
QUILL_NODISCARD LogLevel get_log_level() const noexcept
Definition: LoggerBase.h:123
custom exception
Definition: QuillError.h:47
void set_log_level(LogLevel new_log_level)
Set the log level of the logger.
Definition: LoggerBase.h:140
Base class that provides a timestamp for log statements based on a user-provided clock source...
Definition: UserClockSource.h:27
QUILL_NODISCARD UserClockSource * get_user_clock_source() const noexcept
Returns the user-defined clock source.
Definition: LoggerBase.h:79
Definition: BackendWorker.h:80
Definition: LoggerManager.h:39
void mark_invalid()
This function sets the logger&#39;s validity flag to false, indicating that the logger is no longer valid...
Definition: LoggerBase.h:109
Definition: ThreadContextManager.h:54