userver: userver/logging/log.hpp Source File
Loading...
Searching...
No Matches
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