userver: userver/logging/log.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
log.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/logging/log.hpp
4/// @brief Logging helpers
5
6#include <chrono>
7
8#include <userver/compiler/select.hpp>
9#include <userver/logging/fwd.hpp>
10#include <userver/logging/level.hpp>
11#include <userver/logging/log_filepath.hpp>
12#include <userver/logging/log_helper.hpp>
13
14USERVER_NAMESPACE_BEGIN
15
16namespace logging {
17
18namespace impl {
19
20void SetDefaultLoggerRef(LoggerRef new_logger) noexcept;
21
22extern bool has_background_threads_which_can_log;
23
24} // namespace impl
25
26/// @brief Returns the default logger previously set by SetDefaultLogger. If the
27/// logger was not set - returns a logger that does no logging.
28///
29/// @note While the coroutine engine is running, any reference to the default
30/// logger is guaranteed to be alive. No lifetime guarantees are given
31/// for the default logger reference outside the engine's lifetime. The rule of
32/// thumb there is not to keep this reference in any extended scope.
33LoggerRef GetDefaultLogger() noexcept;
34
35/// @brief Atomically replaces the default logger.
36///
37/// @warning Do not use this class if you are using a component system.
38class DefaultLoggerGuard final {
39 public:
40 /// Atomically replaces the default logger.
41 ///
42 /// @warning The logger should live as long as someone is using it.
43 /// Generally speaking - it should live for a lifetime of the application,
44 /// or for a lifetime of the coroutine engine.
45 explicit DefaultLoggerGuard(LoggerPtr new_default_logger) noexcept;
46
47 DefaultLoggerGuard(DefaultLoggerGuard&&) = delete;
48 DefaultLoggerGuard& operator=(DefaultLoggerGuard&&) = delete;
49
50 ~DefaultLoggerGuard();
51
52 private:
53 LoggerRef logger_prev_;
54 const Level level_prev_;
55 LoggerPtr logger_new_;
56};
57
58/// @brief Allows to override default log level within a scope. Primarily for
59/// use in tests.
60class DefaultLoggerLevelScope final {
61 public:
62 explicit DefaultLoggerLevelScope(logging::Level level);
63
64 DefaultLoggerLevelScope(DefaultLoggerLevelScope&&) = delete;
65 DefaultLoggerLevelScope& operator=(DefaultLoggerLevelScope&&) = delete;
66
67 ~DefaultLoggerLevelScope();
68
69 private:
70 impl::LoggerBase& logger_;
71 const Level level_initial_;
72};
73
74/// @brief Sets new log level for the default logger
75/// @note Prefer using logging::DefaultLoggerLevelScope if possible
77
78/// Returns log level for the default logger
80
81/// Returns true if the provided log level is greater or equal to
82/// the current log level and to the tracing::Span (if any) local log level.
83bool ShouldLog(Level level) noexcept;
84
85/// Sets new log level for a logger
86void SetLoggerLevel(LoggerRef, Level);
87
88bool LoggerShouldLog(LoggerRef logger, Level level) noexcept;
89
90bool LoggerShouldLog(const LoggerPtr& logger, Level level) noexcept;
91
92Level GetLoggerLevel(LoggerRef logger) noexcept;
93
94/// Forces flush of default logger message queue
95void LogFlush();
96
97/// Forces flush of `logger` message queue
98void LogFlush(LoggerRef logger);
99
100namespace impl {
101
102// Not thread-safe, static lifetime data
103class RateLimitData {
104 public:
105 uint64_t count_since_reset = 0;
106 uint64_t dropped_count = 0;
107 std::chrono::steady_clock::time_point last_reset_time{};
108};
109
110// Represents a single rate limit usage
111class RateLimiter {
112 public:
113 RateLimiter(RateLimitData& data, Level level) noexcept;
114 bool ShouldLog() const { return should_log_; }
115 void SetShouldNotLog() { should_log_ = false; }
116 Level GetLevel() const { return level_; }
117 friend LogHelper& operator<<(LogHelper& lh, const RateLimiter& rl) noexcept;
118
119 private:
120 const Level level_;
121 bool should_log_{true};
122 uint64_t dropped_count_{0};
123};
124
125// Register location during static initialization for dynamic debug logs.
126class StaticLogEntry final {
127 public:
128 StaticLogEntry(const char* path, int line) noexcept;
129
130 StaticLogEntry(StaticLogEntry&&) = delete;
131 StaticLogEntry& operator=(StaticLogEntry&&) = delete;
132
133 bool ShouldNotLog(LoggerRef logger, Level level) const noexcept;
134 bool ShouldNotLog(const LoggerPtr& logger, Level level) const noexcept;
135
136 private:
137 static constexpr std::size_t kContentSize =
138 compiler::SelectSize().For64Bit(40).For32Bit(24);
139
140 alignas(void*) std::byte content_[kContentSize];
141};
142
143template <class NameHolder, int Line>
144struct EntryStorage final {
145 static inline StaticLogEntry entry{NameHolder::Get(), Line};
146};
147
148} // namespace impl
149
150} // namespace logging
151
152/// @cond
153// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
154#define USERVER_IMPL_LOG_TO(logger, level)
155 USERVER_NAMESPACE::logging::LogHelper(logger, level).AsLvalue()
156
157// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
158#define USERVER_IMPL_DYNAMIC_DEBUG_ENTRY
159 []() noexcept -> const USERVER_NAMESPACE::logging::impl::StaticLogEntry& {
160 struct NameHolder {
161 static constexpr const char* Get() noexcept {
162 return USERVER_FILEPATH.data();
163 }
164 };
165 const auto& entry =
166 USERVER_NAMESPACE::logging::impl::EntryStorage<NameHolder,
167 __LINE__>::entry;
168 return entry;
169 }
170/// @endcond
171
172/// @brief If lvl matches the verbosity then builds a stream and evaluates a
173/// message for the specified logger.
174/// @hideinitializer
175// static_cast<int> below are workarounds for -Wtautological-compare
176// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
177#define LOG_TO(logger, lvl)
178 __builtin_expect(
179 USERVER_IMPL_DYNAMIC_DEBUG_ENTRY().ShouldNotLog((logger), (lvl)),
180 static_cast<int>(lvl) <
181 static_cast<int>(USERVER_NAMESPACE::logging::Level::kInfo))
182 ? USERVER_NAMESPACE::logging::impl::Noop{}
183 : USERVER_IMPL_LOG_TO((logger), (lvl))
184
185/// @brief If lvl matches the verbosity then builds a stream and evaluates a
186/// message for the default logger.
187/// @hideinitializer
188// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
189#define LOG(lvl) LOG_TO(USERVER_NAMESPACE::logging::GetDefaultLogger(), (lvl))
190
191/// @brief Evaluates a message and logs it to the default logger if its level is
192/// below or equal to logging::Level::kTrace
193// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
194#define LOG_TRACE() LOG(USERVER_NAMESPACE::logging::Level::kTrace)
195
196/// @brief Evaluates a message and logs it to the default logger if its level is
197/// below or equal to logging::Level::kDebug
198// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
199#define LOG_DEBUG() LOG(USERVER_NAMESPACE::logging::Level::kDebug)
200
201/// @brief Evaluates a message and logs it to the default logger if its level is
202/// below or equal to logging::Level::kInfo
203// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
204#define LOG_INFO() LOG(USERVER_NAMESPACE::logging::Level::kInfo)
205
206/// @brief Evaluates a message and logs it to the default logger if its level is
207/// below or equal to logging::Level::kWarning
208// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
209#define LOG_WARNING() LOG(USERVER_NAMESPACE::logging::Level::kWarning)
210
211/// @brief Evaluates a message and logs it to the default logger if its level is
212/// below or equal to logging::Level::kError
213// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
214#define LOG_ERROR() LOG(USERVER_NAMESPACE::logging::Level::kError)
215
216/// @brief Evaluates a message and logs it to the default logger if its level is
217/// below or equal to logging::Level::kCritical
218// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
219#define LOG_CRITICAL() LOG(USERVER_NAMESPACE::logging::Level::kCritical)
220
221///////////////////////////////////////////////////////////////////////////////
222
223/// @brief Evaluates a message and logs it to the `logger` if its level is below
224/// or equal to logging::Level::kTrace
225// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
226#define LOG_TRACE_TO(logger)
227 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kTrace)
228
229/// @brief Evaluates a message and logs it to the `logger` if its level is below
230/// or equal to logging::Level::kDebug
231// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
232#define LOG_DEBUG_TO(logger)
233 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kDebug)
234
235/// @brief Evaluates a message and logs it to the `logger` if its level is below
236/// or equal to logging::Level::kInfo
237// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
238#define LOG_INFO_TO(logger)
239 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kInfo)
240
241/// @brief Evaluates a message and logs it to the `logger` if its level is below
242/// or equal to logging::Level::kWarning
243// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
244#define LOG_WARNING_TO(logger)
245 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kWarning)
246
247/// @brief Evaluates a message and logs it to the `logger` if its level is below
248/// or equal to logging::Level::kError
249// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
250#define LOG_ERROR_TO(logger)
251 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kError)
252
253/// @brief Evaluates a message and logs it to the `logger` if its level is below
254/// or equal to logging::Level::kCritical
255// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
256#define LOG_CRITICAL_TO(logger)
257 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kCritical)
258
259///////////////////////////////////////////////////////////////////////////////
260
261/// @brief If lvl matches the verbosity then builds a stream and evaluates a
262/// message for the logger. Ignores log messages that occur too often.
263/// @hideinitializer
264// Note: we have to jump through the hoops to keep lazy evaluation of the logged
265// data AND log the dropped logs count from the correct LogHelper in the face of
266// multithreading and coroutines.
267// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
268#define LOG_LIMITED_TO(logger, lvl)
269 for (USERVER_NAMESPACE::logging::impl::RateLimiter log_limited_to_rl{
270 []() -> USERVER_NAMESPACE::logging::impl::RateLimitData& {
271 thread_local USERVER_NAMESPACE::logging::impl::RateLimitData
272 rl_data;
273 return rl_data;
274 }(),
275 (lvl)};
276 log_limited_to_rl.ShouldLog(); log_limited_to_rl.SetShouldNotLog())
277 LOG_TO((logger), log_limited_to_rl.GetLevel()) << log_limited_to_rl
278
279/// @brief If lvl matches the verbosity then builds a stream and evaluates a
280/// message for the default logger. Ignores log messages that occur too often.
281// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
282#define LOG_LIMITED(lvl)
283 LOG_LIMITED_TO(USERVER_NAMESPACE::logging::GetDefaultLogger(), lvl)
284
285/// @brief Evaluates a message and logs it to the default logger if the log
286/// message does not occur too often and default logger level is below or equal
287/// to logging::Level::kTrace.
288// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
289#define LOG_LIMITED_TRACE()
290 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kTrace)
291
292/// @brief Evaluates a message and logs it to the default logger if the log
293/// message does not occur too often and default logger level is below or equal
294/// to logging::Level::kDebug.
295// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
296#define LOG_LIMITED_DEBUG()
297 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kDebug)
298
299/// @brief Evaluates a message and logs it to the default logger if the log
300/// message does not occur too often and default logger level is below or equal
301/// to logging::Level::kInfo.
302// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
303#define LOG_LIMITED_INFO() LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kInfo)
304
305/// @brief Evaluates a message and logs it to the default logger if the log
306/// message does not occur too often and default logger level is below or equal
307/// to logging::Level::kWarning.
308// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
309#define LOG_LIMITED_WARNING()
310 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kWarning)
311
312/// @brief Evaluates a message and logs it to the default logger if the log
313/// message does not occur too often and default logger level is below or equal
314/// to logging::Level::kError.
315// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
316#define LOG_LIMITED_ERROR()
317 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kError)
318
319/// @brief Evaluates a message and logs it to the default logger if the log
320/// message does not occur too often and default logger level is below or equal
321/// to logging::Level::kCritical.
322// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
323#define LOG_LIMITED_CRITICAL()
324 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kCritical)
325
326///////////////////////////////////////////////////////////////////////////////
327
328/// @brief Evaluates a message and logs it to the `logger` if the log message
329/// does not occur too often and `logger` level is below or equal to
330/// logging::Level::kTrace.
331// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
332#define LOG_LIMITED_TRACE_TO(logger)
333 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kTrace)
334
335/// @brief Evaluates a message and logs it to the `logger` if the log message
336/// does not occur too often and `logger` level is below or equal to
337/// logging::Level::kDebug.
338// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
339#define LOG_LIMITED_DEBUG_TO(logger)
340 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kDebug)
341
342/// @brief Evaluates a message and logs it to the `logger` if the log message
343/// does not occur too often and `logger` level is below or equal to
344/// logging::Level::kInfo.
345// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
346#define LOG_LIMITED_INFO_TO(logger)
347 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kInfo)
348
349/// @brief Evaluates a message and logs it to the `logger` if the log message
350/// does not occur too often and `logger` level is below or equal to
351/// logging::Level::kWarning.
352// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
353#define LOG_LIMITED_WARNING_TO(logger)
354 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kWarning)
355
356/// @brief Evaluates a message and logs it to the `logger` if the log message
357/// does not occur too often and `logger` level is below or equal to
358/// logging::Level::kError.
359// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
360#define LOG_LIMITED_ERROR_TO(logger)
361 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kError)
362
363/// @brief Evaluates a message and logs it to the `logger` if the log message
364/// does not occur too often and `logger` level is below or equal to
365/// logging::Level::kCritical.
366// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
367#define LOG_LIMITED_CRITICAL_TO(logger)
368 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kCritical)
369
370USERVER_NAMESPACE_END