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 class Sink;
25 class PatternFormatter;
26 class UserClockSource;
27 
28 namespace detail
29 {
30 class BackendWorker;
31 class BacktraceStorage;
32 class LoggerManager;
33 
34 /***/
36 {
37 public:
38  /***/
39  LoggerBase(std::string logger_name, std::vector<std::shared_ptr<Sink>> sinks,
40  PatternFormatterOptions pattern_formatter_options, ClockSourceType clock_source,
41  UserClockSource* user_clock)
42  : _logger_name(static_cast<std::string&&>(logger_name)),
43  _user_clock(user_clock),
44  _clock_source(clock_source),
45  _pattern_formatter_options(static_cast<PatternFormatterOptions&&>(pattern_formatter_options))
46  {
47 #if defined(QUILL_ENABLE_ASSERTIONS) || !defined(NDEBUG)
48  for (auto const& sink : sinks)
49  {
50  QUILL_ASSERT(sink, "sink pointer is nullptr in LoggerBase constructor");
51  }
52 #endif
53 
54  this->_sinks = static_cast<std::vector<std::shared_ptr<Sink>>&&>(sinks);
55  }
56 
57  /***/
58  LoggerBase(LoggerBase const&) = delete;
59  LoggerBase& operator=(LoggerBase const&) = delete;
60 
61  /***/
62  virtual ~LoggerBase() = default;
63 
68  QUILL_NODISCARD std::string const& get_logger_name() const noexcept { return _logger_name; }
69 
74  QUILL_NODISCARD UserClockSource* get_user_clock_source() const noexcept { return _user_clock; }
75 
80  QUILL_NODISCARD ClockSourceType get_clock_source_type() const noexcept { return _clock_source; }
81 
86  QUILL_NODISCARD PatternFormatterOptions const& get_pattern_formatter_options() const noexcept
87  {
88  return _pattern_formatter_options;
89  }
90 
96  QUILL_NODISCARD std::vector<std::shared_ptr<Sink>> const& get_sinks() const noexcept
97  {
98  return _sinks;
99  }
100 
104  void mark_invalid() { _valid.store(false, std::memory_order_release); }
105 
110  QUILL_NODISCARD bool is_valid_logger() const noexcept
111  {
112  return _valid.load(std::memory_order_acquire);
113  }
114 
118  QUILL_NODISCARD LogLevel get_log_level() const noexcept
119  {
120  auto const* self = this;
121 
122 #if defined(__GNUC__) && !defined(__clang__)
123  // GCC warns about potential null pointer access when logger might be
124  // uninitialized during LTO analysis
125  asm volatile("" : "+r"(self) : : "memory");
126 #endif
127 
128  return self->_log_level.load(std::memory_order_relaxed);
129  }
130 
135  void set_log_level(LogLevel new_log_level)
136  {
137  if (QUILL_UNLIKELY(new_log_level == LogLevel::Backtrace))
138  {
139  QUILL_THROW(QuillError{"LogLevel::Backtrace is only used internally. Please don't use it."});
140  }
141 
142  _log_level.store(new_log_level, std::memory_order_relaxed);
143  }
144 
161  void set_immediate_flush(uint32_t flush_every_n_messages = 1)
162  {
163  _message_flush_threshold.store(flush_every_n_messages, std::memory_order_relaxed);
164  }
165 
170  template <LogLevel log_statement_level>
171  QUILL_NODISCARD QUILL_ATTRIBUTE_HOT bool should_log_statement() const noexcept
172  {
173  return log_statement_level >= get_log_level();
174  }
175 
181  QUILL_NODISCARD QUILL_ATTRIBUTE_HOT bool should_log_statement(LogLevel log_statement_level) const noexcept
182  {
183  return log_statement_level >= get_log_level();
184  }
185 
186 protected:
187  friend class BackendWorker;
188  friend class LoggerManager;
189 
190  static inline QUILL_THREAD_LOCAL ThreadContext* _thread_context = nullptr; /* Set and accessed by the frontend */
191 
192  // -- frontend access BEGIN --
193  std::string _logger_name; /* Set by the frontend once, accessed by the frontend AND backend */
194  UserClockSource* _user_clock{nullptr}; /* A non-owned pointer to a custom timestamp clock, valid only when provided. used by frontend only */
195  std::atomic<uint32_t> _message_flush_threshold{0}; /* used by frontend only */
196  std::atomic<uint32_t> _messages_since_last_flush{0}; /* used by frontend only */
197  ClockSourceType _clock_source; /* Set by the frontend and accessed by the frontend AND backend */
198  std::atomic<LogLevel> _log_level{LogLevel::Info}; /* used by frontend only */
199  std::atomic<LogLevel> _backtrace_flush_level{LogLevel::None};
200  std::atomic<bool> _valid{true}; /* Updated by the frontend at any time, accessed by the backend */
201  // -- frontend access END --
202 
203  PatternFormatterOptions _pattern_formatter_options; /* Set by the frontend once and accessed by the backend to initialise PatternFormatter */
204  std::vector<std::shared_ptr<Sink>> _sinks; /* Set by the frontend once and accessed by the backend */
205  std::shared_ptr<PatternFormatter> _pattern_formatter; /* The backend thread will set this once, we never access it on the frontend */
206  std::shared_ptr<BacktraceStorage> _backtrace_storage; /* The backend thread will construct this, we never access it on the frontend */
207 };
208 } // namespace detail
209 
210 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:171
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:181
QUILL_NODISCARD std::string const & get_logger_name() const noexcept
Returns the name of the logger.
Definition: LoggerBase.h:68
std::atomic< bool > _valid
Updated by the frontend at any time, accessed by the backend.
Definition: LoggerBase.h:200
Base class for sinks.
Definition: Sink.h:40
QUILL_NODISCARD ClockSourceType get_clock_source_type() const noexcept
Returns the type of clock source being used.
Definition: LoggerBase.h:80
Definition: PatternFormatter.h:33
QUILL_NODISCARD PatternFormatterOptions const & get_pattern_formatter_options() const noexcept
Returns the pattern formatter options.
Definition: LoggerBase.h:86
QUILL_NODISCARD bool is_valid_logger() const noexcept
Checks if the logger is valid.
Definition: LoggerBase.h:110
Configuration options for the PatternFormatter.
Definition: PatternFormatterOptions.h:23
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:24
void set_immediate_flush(uint32_t flush_every_n_messages=1)
Sets the flush interval for logging based on message count.
Definition: LoggerBase.h:161
QUILL_NODISCARD std::vector< std::shared_ptr< Sink > > const & get_sinks() const noexcept
Returns a const reference to the sinks vector.
Definition: LoggerBase.h:96
Definition: LoggerBase.h:35
QUILL_NODISCARD LogLevel get_log_level() const noexcept
Definition: LoggerBase.h:118
custom exception
Definition: QuillError.h:45
void set_log_level(LogLevel new_log_level)
Set the log level of the logger.
Definition: LoggerBase.h:135
Base class that provides a timestamp for log statements based on a user-provided clock source...
Definition: UserClockSource.h:25
QUILL_NODISCARD UserClockSource * get_user_clock_source() const noexcept
Returns the user-defined clock source.
Definition: LoggerBase.h:74
Definition: BackendWorker.h:77
Definition: LoggerManager.h:33
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:104
Definition: ThreadContextManager.h:53