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