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 {
39public:
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
52private:
53 LoggerRef logger_prev_;
54 const Level level_prev_;
55 LoggerPtr logger_new_;
56};
57
58/// @brief Allows to override global log level for the whole service within a scope. Primarily for use in tests.
59///
60/// @warning This is NOT the right tool to toggle writing of certain logs within a scope.
61/// This scope class changes log level GLOBALLY as-if using @ref logging::SetLoggerLevel.
62///
63/// @note To affect what logs are written within a scope, use @ref tracing::Span::SetLogLevel and
64/// @ref tracing::Span::SetLocalLogLevel (read their docs first!).
65class DefaultLoggerLevelScope final {
66public:
67 explicit DefaultLoggerLevelScope(logging::Level level);
68
69 DefaultLoggerLevelScope(DefaultLoggerLevelScope&&) = delete;
70 DefaultLoggerLevelScope& operator=(DefaultLoggerLevelScope&&) = delete;
71
72 ~DefaultLoggerLevelScope();
73
74private:
75 impl::LoggerBase& logger_;
76 const Level level_initial_;
77};
78
79/// @brief Sets new log level for the default logger
80/// @note Prefer using logging::DefaultLoggerLevelScope if possible
82
83/// Returns log level for the default logger
85
86/// Returns true if the provided log level is greater or equal to
87/// the current log level and to the tracing::Span (if any) local log level.
88bool ShouldLog(Level level) noexcept;
89
90/// Sets new log level for a logger
91void SetLoggerLevel(LoggerRef, Level);
92
93bool LoggerShouldLog(LoggerRef logger, Level level) noexcept;
94
95bool LoggerShouldLog(const LoggerPtr& logger, Level level) noexcept;
96
97Level GetLoggerLevel(LoggerRef logger) noexcept;
98
99/// Forces flush of default logger message queue
100void LogFlush();
101
102/// Forces flush of `logger` message queue
103void LogFlush(LoggerRef logger);
104
105namespace impl {
106
107// Not thread-safe, static lifetime data
108class RateLimitData {
109public:
110 uint64_t count_since_reset = 0;
111 uint64_t dropped_count = 0;
112 std::chrono::steady_clock::time_point last_reset_time{};
113};
114
115// Represents a single rate limit usage
116class RateLimiter {
117public:
118 RateLimiter(RateLimitData& data, Level level) noexcept;
119 bool ShouldLog() const { return should_log_; }
120 void SetShouldNotLog() { should_log_ = false; }
121 Level GetLevel() const { return level_; }
122 friend LogHelper& operator<<(LogHelper& lh, const RateLimiter& rl) noexcept;
123
124private:
125 const Level level_;
126 bool should_log_{true};
127 uint64_t dropped_count_{0};
128};
129
130// Register location during static initialization for dynamic debug logs.
131class StaticLogEntry final {
132public:
133 StaticLogEntry(const char* path, int line) noexcept;
134
135 StaticLogEntry(StaticLogEntry&&) = delete;
136 StaticLogEntry& operator=(StaticLogEntry&&) = delete;
137
138 bool ShouldNotLog(LoggerRef logger, Level level) const noexcept;
139 bool ShouldNotLog(const LoggerPtr& logger, Level level) const noexcept;
140
141private:
142 static constexpr std::size_t kContentSize = compiler::SelectSize().For64Bit(40).For32Bit(24);
143
144 alignas(void*) std::byte content_[kContentSize];
145};
146
147template <class NameHolder, int Line>
148struct EntryStorage final {
149 static inline StaticLogEntry entry{NameHolder::Get(), Line};
150};
151
152} // namespace impl
153
154} // namespace logging
155
156/// @cond
157
158#ifdef USERVER_FEATURE_ERASE_LOG_WITH_LEVEL
159
160// Helper macro to erase the logging related code from binary. Erases the
161// * logging registration via EntryStorage
162// * ShouldLog() calls and related `if` statements and runtime checks
163// * SourceLocation info
164// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
165#define USERVER_IMPL_ERASE_LOG
166 true
167 ? logging::impl::Noop{}
168 : USERVER_NAMESPACE::logging::LogHelper(
169 USERVER_NAMESPACE::logging::GetDefaultLogger(),
170 USERVER_NAMESPACE::logging::Level::kTrace,
171 USERVER_NAMESPACE::utils::impl::SourceLocation::Custom(0, {}, {})
172 )
173 .AsLvalue()
174
175// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
176#define USERVER_IMPL_LOGS_TRACE_ERASER(X) USERVER_IMPL_ERASE_LOG
177
178#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 0
179// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
180#define USERVER_IMPL_LOGS_DEBUG_ERASER(X) USERVER_IMPL_ERASE_LOG
181#endif
182
183#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 1
184// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
185#define USERVER_IMPL_LOGS_INFO_ERASER(X) USERVER_IMPL_ERASE_LOG
186#endif
187
188#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 2
189// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
190#define USERVER_IMPL_LOGS_WARNING_ERASER(X) USERVER_IMPL_ERASE_LOG
191#endif
192
193#if USERVER_FEATURE_ERASE_LOG_WITH_LEVEL > 3
194// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
195#define USERVER_IMPL_LOGS_ERROR_ERASER(X) USERVER_IMPL_ERASE_LOG
196#endif
197
198#endif // #ifdef USERVER_FEATURE_ERASE_LOG_WITH_LEVEL
199
200#ifndef USERVER_IMPL_LOGS_TRACE_ERASER
201// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
202#define USERVER_IMPL_LOGS_TRACE_ERASER(X) X
203#endif
204
205#ifndef USERVER_IMPL_LOGS_DEBUG_ERASER
206// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
207#define USERVER_IMPL_LOGS_DEBUG_ERASER(X) X
208#endif
209
210#ifndef USERVER_IMPL_LOGS_INFO_ERASER
211// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
212#define USERVER_IMPL_LOGS_INFO_ERASER(X) X
213#endif
214
215#ifndef USERVER_IMPL_LOGS_WARNING_ERASER
216// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
217#define USERVER_IMPL_LOGS_WARNING_ERASER(X) X
218#endif
219
220#ifndef USERVER_IMPL_LOGS_ERROR_ERASER
221// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
222#define USERVER_IMPL_LOGS_ERROR_ERASER(X) X
223#endif
224
225// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
226#define USERVER_IMPL_LOG_TO(logger, level, ...)
227 USERVER_NAMESPACE::logging::LogHelper(logger, level, USERVER_NAMESPACE::logging::LogClass::kLog)
228 .AsLvalue(__VA_ARGS__)
229
230// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
231#define USERVER_IMPL_DYNAMIC_DEBUG_ENTRY
232 []() noexcept -> const USERVER_NAMESPACE::logging::impl::StaticLogEntry& {
233 struct NameHolder {
234 static constexpr const char* Get() noexcept { return USERVER_FILEPATH.data(); }
235 };
236 const auto& entry = USERVER_NAMESPACE::logging::impl::EntryStorage<NameHolder, __LINE__>::entry;
237 return entry;
238 }
239 /// @endcond
240
241/// @brief If lvl matches the verbosity then builds a stream and evaluates a
242/// message for the specified logger.
243/// @hideinitializer
244// static_cast<int> below are workarounds for -Wtautological-compare
245// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
246#define LOG_TO(logger, lvl, ...)
247 __builtin_expect(
248 USERVER_IMPL_DYNAMIC_DEBUG_ENTRY().ShouldNotLog((logger), (lvl)),
249 static_cast<int>(lvl) < static_cast<int>(USERVER_NAMESPACE::logging::Level::kInfo)
250 )
251 ? USERVER_NAMESPACE::logging::impl::Noop{}
252 : USERVER_IMPL_LOG_TO((logger), (lvl), __VA_ARGS__)
253
254/// @brief If lvl matches the verbosity then builds a stream and evaluates a
255/// message for the default logger.
256/// @hideinitializer
257// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
258#define LOG(lvl, ...) LOG_TO(USERVER_NAMESPACE::logging::GetDefaultLogger(), (lvl), __VA_ARGS__)
259
260/// @brief Evaluates a message and logs it to the default logger if its level is
261/// below or equal to logging::Level::kTrace
262// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
263#define LOG_TRACE(...) USERVER_IMPL_LOGS_TRACE_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kTrace, __VA_ARGS__))
264
265/// @brief Evaluates a message and logs it to the default logger if its level is
266/// below or equal to logging::Level::kDebug
267// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
268#define LOG_DEBUG(...) USERVER_IMPL_LOGS_DEBUG_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kDebug, __VA_ARGS__))
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(...) USERVER_IMPL_LOGS_INFO_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kInfo, __VA_ARGS__))
274
275/// @brief Evaluates a message and logs it to the default logger if its level is
276/// below or equal to logging::Level::kWarning
277// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
278#define LOG_WARNING(...) USERVER_IMPL_LOGS_WARNING_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kWarning, __VA_ARGS__))
279
280/// @brief Evaluates a message and logs it to the default logger if its level is
281/// below or equal to logging::Level::kError
282// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
283#define LOG_ERROR(...) USERVER_IMPL_LOGS_ERROR_ERASER(LOG(USERVER_NAMESPACE::logging::Level::kError, __VA_ARGS__))
284
285/// @brief Evaluates a message and logs it to the default logger if its level is
286/// below or equal to logging::Level::kCritical
287// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
288#define LOG_CRITICAL(...) LOG(USERVER_NAMESPACE::logging::Level::kCritical, __VA_ARGS__)
289
290///////////////////////////////////////////////////////////////////////////////
291
292/// @brief Evaluates a message and logs it to the `logger` if its level is below
293/// or equal to logging::Level::kTrace
294// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
295#define LOG_TRACE_TO(logger, ...)
296 USERVER_IMPL_LOGS_TRACE_ERASER(LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kTrace, __VA_ARGS__))
297
298/// @brief Evaluates a message and logs it to the `logger` if its level is below
299/// or equal to logging::Level::kDebug
300// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
301#define LOG_DEBUG_TO(logger, ...)
302 USERVER_IMPL_LOGS_DEBUG_ERASER(LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kDebug, __VA_ARGS__))
303
304/// @brief Evaluates a message and logs it to the `logger` if its level is below
305/// or equal to logging::Level::kInfo
306// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
307#define LOG_INFO_TO(logger, ...)
308 USERVER_IMPL_LOGS_INFO_ERASER(LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kInfo, __VA_ARGS__))
309
310/// @brief Evaluates a message and logs it to the `logger` if its level is below
311/// or equal to logging::Level::kWarning
312// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
313#define LOG_WARNING_TO(logger, ...)
314 USERVER_IMPL_LOGS_WARNING_ERASER(LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kWarning, __VA_ARGS__))
315
316/// @brief Evaluates a message and logs it to the `logger` if its level is below
317/// or equal to logging::Level::kError
318// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
319#define LOG_ERROR_TO(logger, ...)
320 USERVER_IMPL_LOGS_ERROR_ERASER(LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kError, __VA_ARGS__))
321
322/// @brief Evaluates a message and logs it to the `logger` if its level is below
323/// or equal to logging::Level::kCritical
324// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
325#define LOG_CRITICAL_TO(logger, ...) LOG_TO(logger, USERVER_NAMESPACE::logging::Level::kCritical, __VA_ARGS__)
326
327///////////////////////////////////////////////////////////////////////////////
328
329/// @brief If lvl matches the verbosity then builds a stream and evaluates a
330/// message for the logger. Ignores log messages that occur too often.
331/// @hideinitializer
332// Note: we have to jump through the hoops to keep lazy evaluation of the logged
333// data AND log the dropped logs count from the correct LogHelper in the face of
334// multithreading and coroutines.
335// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
336#define LOG_LIMITED_TO(logger, lvl, ...)
337 for (USERVER_NAMESPACE::logging::impl::RateLimiter log_limited_to_rl{
338 []() -> USERVER_NAMESPACE::logging::impl::RateLimitData& {
339 thread_local USERVER_NAMESPACE::logging::impl::RateLimitData rl_data;
340 return rl_data;
341 }(),
342 (lvl)
343 };
344 log_limited_to_rl.ShouldLog();
345 log_limited_to_rl.SetShouldNotLog())
346 LOG_TO((logger), log_limited_to_rl.GetLevel(), __VA_ARGS__) << log_limited_to_rl
347
348/// @brief If lvl matches the verbosity then builds a stream and evaluates a
349/// message for the default logger. Ignores log messages that occur too often.
350// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
351#define LOG_LIMITED(lvl, ...) LOG_LIMITED_TO(USERVER_NAMESPACE::logging::GetDefaultLogger(), (lvl), __VA_ARGS__)
352
353/// @brief Evaluates a message and logs it to the default logger if the log
354/// message does not occur too often and default logger level is below or equal
355/// to logging::Level::kTrace.
356// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
357#define LOG_LIMITED_TRACE(...)
358 USERVER_IMPL_LOGS_TRACE_ERASER(LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kTrace, __VA_ARGS__))
359
360/// @brief Evaluates a message and logs it to the default logger if the log
361/// message does not occur too often and default logger level is below or equal
362/// to logging::Level::kDebug.
363// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
364#define LOG_LIMITED_DEBUG(...)
365 USERVER_IMPL_LOGS_DEBUG_ERASER(LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kDebug, __VA_ARGS__))
366
367/// @brief Evaluates a message and logs it to the default logger if the log
368/// message does not occur too often and default logger level is below or equal
369/// to logging::Level::kInfo.
370// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
371#define LOG_LIMITED_INFO(...)
372 USERVER_IMPL_LOGS_INFO_ERASER(LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kInfo, __VA_ARGS__))
373
374/// @brief Evaluates a message and logs it to the default logger if the log
375/// message does not occur too often and default logger level is below or equal
376/// to logging::Level::kWarning.
377// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
378#define LOG_LIMITED_WARNING(...)
379 USERVER_IMPL_LOGS_WARNING_ERASER(LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kWarning, __VA_ARGS__))
380
381/// @brief Evaluates a message and logs it to the default logger if the log
382/// message does not occur too often and default logger level is below or equal
383/// to logging::Level::kError.
384// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
385#define LOG_LIMITED_ERROR(...)
386 USERVER_IMPL_LOGS_ERROR_ERASER(LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kError, __VA_ARGS__))
387
388/// @brief Evaluates a message and logs it to the default logger if the log
389/// message does not occur too often and default logger level is below or equal
390/// to logging::Level::kCritical.
391// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
392#define LOG_LIMITED_CRITICAL(...) LOG_LIMITED(USERVER_NAMESPACE::logging::Level::kCritical, __VA_ARGS__)
393
394///////////////////////////////////////////////////////////////////////////////
395
396/// @brief Evaluates a message and logs it to the `logger` if the log message
397/// does not occur too often and `logger` level is below or equal to
398/// logging::Level::kTrace.
399// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
400#define LOG_LIMITED_TRACE_TO(logger, ...)
401 USERVER_IMPL_LOGS_TRACE_ERASER(LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kTrace, __VA_ARGS__))
402
403/// @brief Evaluates a message and logs it to the `logger` if the log message
404/// does not occur too often and `logger` level is below or equal to
405/// logging::Level::kDebug.
406// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
407#define LOG_LIMITED_DEBUG_TO(logger, ...)
408 USERVER_IMPL_LOGS_DEBUG_ERASER(LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kDebug, __VA_ARGS__))
409
410/// @brief Evaluates a message and logs it to the `logger` if the log message
411/// does not occur too often and `logger` level is below or equal to
412/// logging::Level::kInfo.
413// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
414#define LOG_LIMITED_INFO_TO(logger, ...)
415 USERVER_IMPL_LOGS_INFO_ERASER(LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kInfo, __VA_ARGS__))
416
417/// @brief Evaluates a message and logs it to the `logger` if the log message
418/// does not occur too often and `logger` level is below or equal to
419/// logging::Level::kWarning.
420// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
421#define LOG_LIMITED_WARNING_TO(logger, ...)
422 USERVER_IMPL_LOGS_WARNING_ERASER(LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kWarning, __VA_ARGS__))
423
424/// @brief Evaluates a message and logs it to the `logger` if the log message
425/// does not occur too often and `logger` level is below or equal to
426/// logging::Level::kError.
427// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
428#define LOG_LIMITED_ERROR_TO(logger, ...)
429 USERVER_IMPL_LOGS_ERROR_ERASER(LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kError, __VA_ARGS__))
430
431/// @brief Evaluates a message and logs it to the `logger` if the log message
432/// does not occur too often and `logger` level is below or equal to
433/// logging::Level::kCritical.
434// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
435#define LOG_LIMITED_CRITICAL_TO(logger, ...)
436 LOG_LIMITED_TO(logger, USERVER_NAMESPACE::logging::Level::kCritical, __VA_ARGS__)
437
438USERVER_NAMESPACE_END