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// 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