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
154#ifdef USERVER_FEATURE_ERASE_LOG_WITH_LEVEL
155
156// Helper macro to erase the logging related code from binary. Erases the
157// * logging registration via EntryStorage
158// * ShouldLog() calls and related `if` statements and runtime checks
159// * SourceLocation info
160// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
161#define USERVER_IMPL_ERASE_LOG
162 true
163 ? logging::impl::Noop{}
164 : USERVER_NAMESPACE::logging::LogHelper(
165 USERVER_NAMESPACE::logging::GetDefaultLogger(),
166 USERVER_NAMESPACE::logging::Level::kTrace,
167 USERVER_NAMESPACE::utils::impl::SourceLocation::Custom(0, {}, {}))
168 .AsLvalue()
169
170// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
171#define USERVER_IMPL_LOGS_TRACE_ERASER(X) USERVER_IMPL_ERASE_LOG
172
173#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 0
174// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
175#define USERVER_IMPL_LOGS_DEBUG_ERASER(X) USERVER_IMPL_ERASE_LOG
176#endif
177
178#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 1
179// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
180#define USERVER_IMPL_LOGS_INFO_ERASER(X) USERVER_IMPL_ERASE_LOG
181#endif
182
183#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 2
184// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
185#define USERVER_IMPL_LOGS_WARNING_ERASER(X) USERVER_IMPL_ERASE_LOG
186#endif
187
188#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 3
189// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
190#define USERVER_IMPL_LOGS_ERROR_ERASER(X) USERVER_IMPL_ERASE_LOG
191#endif
192
193#endif // #ifdef USERVER_FEATURE_ERASE_LOG_WITH_LEVEL
194
195#ifndef USERVER_IMPL_LOGS_TRACE_ERASER
196// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
197#define USERVER_IMPL_LOGS_TRACE_ERASER(X) X
198#endif
199
200#ifndef USERVER_IMPL_LOGS_DEBUG_ERASER
201// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
202#define USERVER_IMPL_LOGS_DEBUG_ERASER(X) X
203#endif
204
205#ifndef USERVER_IMPL_LOGS_INFO_ERASER
206// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
207#define USERVER_IMPL_LOGS_INFO_ERASER(X) X
208#endif
209
210#ifndef USERVER_IMPL_LOGS_WARNING_ERASER
211// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
212#define USERVER_IMPL_LOGS_WARNING_ERASER(X) X
213#endif
214
215#ifndef USERVER_IMPL_LOGS_ERROR_ERASER
216// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
217#define USERVER_IMPL_LOGS_ERROR_ERASER(X) X
218#endif
219
220// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
221#define USERVER_IMPL_LOG_TO(logger, level)
222 USERVER_NAMESPACE::logging::LogHelper(logger, level).AsLvalue()
223
224// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
225#define USERVER_IMPL_DYNAMIC_DEBUG_ENTRY
226 []() noexcept -> const USERVER_NAMESPACE::logging::impl::StaticLogEntry& {
227 struct NameHolder {
228 static constexpr const char* Get() noexcept {
229 return USERVER_FILEPATH.data();
230 }
231 };
232 const auto& entry =
233 USERVER_NAMESPACE::logging::impl::EntryStorage<NameHolder,
234 __LINE__>::entry;
235 return entry;
236 }
237/// @endcond
238
239/// @brief If lvl matches the verbosity then builds a stream and evaluates a
240/// message for the specified logger.
241/// @hideinitializer
242// static_cast<int> below are workarounds for -Wtautological-compare
243// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
244#define LOG_TO(logger, lvl)
245 __builtin_expect(
246 USERVER_IMPL_DYNAMIC_DEBUG_ENTRY().ShouldNotLog((logger), (lvl)),
247 static_cast<int>(lvl) <
248 static_cast<int>(USERVER_NAMESPACE::logging::Level::kInfo))
249 ? USERVER_NAMESPACE::logging::impl::Noop{}
250 : USERVER_IMPL_LOG_TO((logger), (lvl))
251
252/// @brief If lvl matches the verbosity then builds a stream and evaluates a
253/// message for the default logger.
254/// @hideinitializer
255// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
256#define LOG(lvl) LOG_TO(USERVER_NAMESPACE::logging::GetDefaultLogger(), (lvl))
257
258/// @brief Evaluates a message and logs it to the default logger if its level is
259/// below or equal to logging::Level::kTrace
260// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
261#define LOG_TRACE()
262 USERVER_IMPL_LOGS_TRACE_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kTrace))
263
264/// @brief Evaluates a message and logs it to the default logger if its level is
265/// below or equal to logging::Level::kDebug
266// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
267#define LOG_DEBUG()
268 USERVER_IMPL_LOGS_DEBUG_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kDebug))
269
270/// @brief Evaluates a message and logs it to the default logger if its level is
271/// below or equal to logging::Level::kInfo
272// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
273#define LOG_INFO()
274 USERVER_IMPL_LOGS_INFO_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kInfo))
275
276/// @brief Evaluates a message and logs it to the default logger if its level is
277/// below or equal to logging::Level::kWarning
278// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
279#define LOG_WARNING()
280 USERVER_IMPL_LOGS_WARNING_ERASER(
281 LOG(USERVER_NAMESPACE::logging::Level::kWarning))
282
283/// @brief Evaluates a message and logs it to the default logger if its level is
284/// below or equal to logging::Level::kError
285// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
286#define LOG_ERROR()
287 USERVER_IMPL_LOGS_ERROR_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kError))
288
289/// @brief Evaluates a message and logs it to the default logger if its level is
290/// below or equal to logging::Level::kCritical
291// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
292#define LOG_CRITICAL() LOG(USERVER_NAMESPACE::logging::Level::kCritical)
293
294///////////////////////////////////////////////////////////////////////////////
295
296/// @brief Evaluates a message and logs it to the `logger` if its level is below
297/// or equal to logging::Level::kTrace
298// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
299#define LOG_TRACE_TO(logger)
300 USERVER_IMPL_LOGS_TRACE_ERASER(
301 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kTrace))
302
303/// @brief Evaluates a message and logs it to the `logger` if its level is below
304/// or equal to logging::Level::kDebug
305// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
306#define LOG_DEBUG_TO(logger)
307 USERVER_IMPL_LOGS_DEBUG_ERASER(
308 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kDebug))
309
310/// @brief Evaluates a message and logs it to the `logger` if its level is below
311/// or equal to logging::Level::kInfo
312// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
313#define LOG_INFO_TO(logger)
314 USERVER_IMPL_LOGS_INFO_ERASER(
315 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kInfo))
316
317/// @brief Evaluates a message and logs it to the `logger` if its level is below
318/// or equal to logging::Level::kWarning
319// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
320#define LOG_WARNING_TO(logger)
321 USERVER_IMPL_LOGS_WARNING_ERASER(
322 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kWarning))
323
324/// @brief Evaluates a message and logs it to the `logger` if its level is below
325/// or equal to logging::Level::kError
326// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
327#define LOG_ERROR_TO(logger)
328 USERVER_IMPL_LOGS_ERROR_ERASER(
329 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kError))
330
331/// @brief Evaluates a message and logs it to the `logger` if its level is below
332/// or equal to logging::Level::kCritical
333// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
334#define LOG_CRITICAL_TO(logger)
335 LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kCritical)
336
337///////////////////////////////////////////////////////////////////////////////
338
339/// @brief If lvl matches the verbosity then builds a stream and evaluates a
340/// message for the logger. Ignores log messages that occur too often.
341/// @hideinitializer
342// Note: we have to jump through the hoops to keep lazy evaluation of the logged
343// data AND log the dropped logs count from the correct LogHelper in the face of
344// multithreading and coroutines.
345// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
346#define LOG_LIMITED_TO(logger, lvl)
347 for (USERVER_NAMESPACE::logging::impl::RateLimiter log_limited_to_rl{
348 []() -> USERVER_NAMESPACE::logging::impl::RateLimitData& {
349 thread_local USERVER_NAMESPACE::logging::impl::RateLimitData
350 rl_data;
351 return rl_data;
352 }(),
353 (lvl)};
354 log_limited_to_rl.ShouldLog(); log_limited_to_rl.SetShouldNotLog())
355 LOG_TO((logger), log_limited_to_rl.GetLevel()) << log_limited_to_rl
356
357/// @brief If lvl matches the verbosity then builds a stream and evaluates a
358/// message for the default logger. Ignores log messages that occur too often.
359// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
360#define LOG_LIMITED(lvl)
361 LOG_LIMITED_TO(USERVER_NAMESPACE::logging::GetDefaultLogger(), lvl)
362
363/// @brief Evaluates a message and logs it to the default logger if the log
364/// message does not occur too often and default logger level is below or equal
365/// to logging::Level::kTrace.
366// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
367#define LOG_LIMITED_TRACE()
368 USERVER_IMPL_LOGS_TRACE_ERASER(
369 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kTrace))
370
371/// @brief Evaluates a message and logs it to the default logger if the log
372/// message does not occur too often and default logger level is below or equal
373/// to logging::Level::kDebug.
374// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
375#define LOG_LIMITED_DEBUG()
376 USERVER_IMPL_LOGS_DEBUG_ERASER(
377 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kDebug))
378
379/// @brief Evaluates a message and logs it to the default logger if the log
380/// message does not occur too often and default logger level is below or equal
381/// to logging::Level::kInfo.
382// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
383#define LOG_LIMITED_INFO()
384 USERVER_IMPL_LOGS_INFO_ERASER(
385 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kInfo))
386
387/// @brief Evaluates a message and logs it to the default logger if the log
388/// message does not occur too often and default logger level is below or equal
389/// to logging::Level::kWarning.
390// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
391#define LOG_LIMITED_WARNING()
392 USERVER_IMPL_LOGS_WARNING_ERASER(
393 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kWarning))
394
395/// @brief Evaluates a message and logs it to the default logger if the log
396/// message does not occur too often and default logger level is below or equal
397/// to logging::Level::kError.
398// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
399#define LOG_LIMITED_ERROR()
400 USERVER_IMPL_LOGS_ERROR_ERASER(
401 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kError))
402
403/// @brief Evaluates a message and logs it to the default logger if the log
404/// message does not occur too often and default logger level is below or equal
405/// to logging::Level::kCritical.
406// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
407#define LOG_LIMITED_CRITICAL()
408 LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kCritical)
409
410///////////////////////////////////////////////////////////////////////////////
411
412/// @brief Evaluates a message and logs it to the `logger` if the log message
413/// does not occur too often and `logger` level is below or equal to
414/// logging::Level::kTrace.
415// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
416#define LOG_LIMITED_TRACE_TO(logger)
417 USERVER_IMPL_LOGS_TRACE_ERASER(
418 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kTrace))
419
420/// @brief Evaluates a message and logs it to the `logger` if the log message
421/// does not occur too often and `logger` level is below or equal to
422/// logging::Level::kDebug.
423// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
424#define LOG_LIMITED_DEBUG_TO(logger)
425 USERVER_IMPL_LOGS_DEBUG_ERASER(
426 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kDebug))
427
428/// @brief Evaluates a message and logs it to the `logger` if the log message
429/// does not occur too often and `logger` level is below or equal to
430/// logging::Level::kInfo.
431// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
432#define LOG_LIMITED_INFO_TO(logger)
433 USERVER_IMPL_LOGS_INFO_ERASER(
434 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kInfo))
435
436/// @brief Evaluates a message and logs it to the `logger` if the log message
437/// does not occur too often and `logger` level is below or equal to
438/// logging::Level::kWarning.
439// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
440#define LOG_LIMITED_WARNING_TO(logger)
441 USERVER_IMPL_LOGS_WARNING_ERASER(
442 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kWarning))
443
444/// @brief Evaluates a message and logs it to the `logger` if the log message
445/// does not occur too often and `logger` level is below or equal to
446/// logging::Level::kError.
447// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
448#define LOG_LIMITED_ERROR_TO(logger)
449 USERVER_IMPL_LOGS_ERROR_ERASER(
450 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kError))
451
452/// @brief Evaluates a message and logs it to the `logger` if the log message
453/// does not occur too often and `logger` level is below or equal to
454/// logging::Level::kCritical.
455// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
456#define LOG_LIMITED_CRITICAL_TO(logger)
457 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kCritical)
458
459USERVER_NAMESPACE_END