23#include <seastar/core/sstring.hh>
24#include <seastar/util/backtrace.hh>
25#include <seastar/util/log-impl.hh>
26#include <seastar/core/lowres_clock.hh>
27#include <seastar/util/std-compat.hh>
28#include <seastar/util/modules.hh>
32#include <unordered_map>
39#include <fmt/format.h>
47SEASTAR_MODULE_EXPORT_BEGIN
62std::ostream& operator<<(std::ostream& out,
log_level level);
63std::istream& operator>>(std::istream& in,
log_level& level);
65SEASTAR_MODULE_EXPORT_END
70 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
71 auto format(
seastar::log_level level, fmt::format_context& ctx)
const ->
decltype(ctx.out());
75SEASTAR_MODULE_EXPORT_BEGIN
92 std::atomic<log_level> _level = { log_level::info };
93 static std::ostream* _out;
94 static std::atomic<bool> _ostream;
95 static std::atomic<bool> _syslog;
96 static unsigned _shard_field_width;
97#ifdef SEASTAR_BUILD_SHARED_LIBS
98 static thread_local bool silent;
100 static inline thread_local bool silent =
false;
106 virtual ~log_writer() =
default;
107 virtual internal::log_buf::inserter_iterator operator()(internal::log_buf::inserter_iterator) = 0;
109 template <
typename Func>
110 requires requires (Func fn, internal::log_buf::inserter_iterator it) {
113 class lambda_log_writer :
public log_writer {
116 lambda_log_writer(Func&& func) : _func(
std::forward<Func>(func)) { }
117 virtual ~lambda_log_writer()
override =
default;
118 virtual internal::log_buf::inserter_iterator operator()(internal::log_buf::inserter_iterator it)
override {
return _func(it); }
123#ifdef SEASTAR_LOGGER_COMPILE_TIME_FMT
124 template<
typename... Args>
130 std::enable_if_t<std::is_convertible_v<const S&, std::string_view>,
int> = 0>
131 FMT_CONSTEVAL
inline format_info(
const S&
format,
132 compat::source_location loc = compat::source_location::current()) noexcept
140 inline format_info(fmt::format_string<Args...> s,
141 compat::source_location loc = compat::source_location::current()) noexcept
145#if FMT_VERSION >= 100000
146 using runtime_format_string_t = fmt::runtime_format_string<char>;
148 using runtime_format_string_t = fmt::basic_runtime<char>;
150 inline format_info(runtime_format_string_t s,
151 compat::source_location loc = compat::source_location::current()) noexcept
156 FMT_CONSTEVAL format_info() noexcept
159 fmt::format_string<Args...>
format;
160 compat::source_location loc;
162#ifdef __cpp_lib_type_identity
163 template <
typename T>
164 using type_identity_t =
typename std::type_identity<T>::type;
166 template <
typename T>
struct type_identity {
using type = T; };
167 template <
typename T>
using type_identity_t =
typename type_identity<T>::type;
169 template <
typename... Args>
170 using format_info_t = format_info<type_identity_t<Args>...>;
177 format_info(
const char*
format, compat::source_location loc = compat::source_location::current()) noexcept
183 format_info(std::string_view
format, compat::source_location loc = compat::source_location::current()) noexcept
188 format_info(compat::source_location loc = compat::source_location::current()) noexcept
193 compat::source_location loc;
197 template <
typename...>
198 using format_info_t = format_info;
204 void do_log(
log_level level, log_writer& writer);
205 void failed_to_log(std::exception_ptr ex,
206 fmt::string_view fmt,
207 compat::source_location loc)
noexcept;
211 silencer() noexcept {
245 using clock = lowres_clock;
248 clock::duration _interval;
249 clock::time_point _next;
250 uint64_t _dropped_messages = 0;
254 bool has_dropped_messages()
const {
return bool(_dropped_messages); }
255 uint64_t get_and_reset_dropped_messages() {
256 return std::exchange(_dropped_messages, 0);
260 explicit rate_limit(std::chrono::milliseconds interval);
264 explicit logger(sstring name);
268 bool is_shard_zero() noexcept;
274 bool is_enabled(
log_level level) const noexcept {
275 return __builtin_expect(level <= _level.load(std::memory_order_relaxed),
false) && !silent;
284 template <
typename... Args>
285 void log(
log_level level, format_info_t<Args...> fmt, Args&&... args)
noexcept {
286 if (is_enabled(level)) {
288 lambda_log_writer writer([&] (internal::log_buf::inserter_iterator it) {
289#ifdef SEASTAR_LOGGER_COMPILE_TIME_FMT
290 return fmt::format_to(it, fmt.format, std::forward<Args>(args)...);
292 return fmt::format_to(it, fmt::runtime(fmt.format), std::forward<Args>(args)...);
295 do_log(level, writer);
297 failed_to_log(std::current_exception(), fmt::string_view(fmt.format), fmt.loc);
316 template <
typename... Args>
317 void log(
log_level level, rate_limit& rl, format_info_t<Args...> fmt, Args&&... args)
noexcept {
318 if (is_enabled(level) && rl.check()) {
320 lambda_log_writer writer([&] (internal::log_buf::inserter_iterator it) {
321 if (rl.has_dropped_messages()) {
322 it = fmt::format_to(it,
"(rate limiting dropped {} similar messages) ", rl.get_and_reset_dropped_messages());
324 return fmt::format_to(it, fmt::runtime(fmt.format), std::forward<Args>(args)...);
326 do_log(level, writer);
328 failed_to_log(std::current_exception(), fmt::string_view(fmt.format), fmt.loc);
343 void log(
log_level level, rate_limit& rl, log_writer& writer, format_info_t<> fmt = {})
noexcept {
344 if (is_enabled(level) && rl.check()) {
346 lambda_log_writer writer_wrapper([&] (internal::log_buf::inserter_iterator it) {
347 if (rl.has_dropped_messages()) {
348 it = fmt::format_to(it,
"(rate limiting dropped {} similar messages) ", rl.get_and_reset_dropped_messages());
352 do_log(level, writer_wrapper);
354 failed_to_log(std::current_exception(),
"", fmt.loc);
367 template <
typename... Args>
368 void error(format_info_t<Args...> fmt, Args&&... args)
noexcept {
369 log(log_level::error, std::move(fmt), std::forward<Args>(args)...);
378 template <
typename... Args>
379 void warn(format_info_t<Args...> fmt, Args&&... args)
noexcept {
380 log(log_level::warn, std::move(fmt), std::forward<Args>(args)...);
389 template <
typename... Args>
390 void info(format_info_t<Args...> fmt, Args&&... args)
noexcept {
391 log(log_level::info, std::move(fmt), std::forward<Args>(args)...);
400 template <
typename... Args>
401 void info0(format_info_t<Args...> fmt, Args&&... args)
noexcept {
402 if (is_shard_zero()) {
403 log(log_level::info, std::move(fmt), std::forward<Args>(args)...);
413 template <
typename... Args>
414 void debug(format_info_t<Args...> fmt, Args&&... args)
noexcept {
415 log(log_level::debug, std::move(fmt), std::forward<Args>(args)...);
424 template <
typename... Args>
425 void trace(format_info_t<Args...> fmt, Args&&... args)
noexcept {
426 log(log_level::trace, std::move(fmt), std::forward<Args>(args)...);
431 const sstring& name() const noexcept {
438 return _level.load(std::memory_order_relaxed);
443 void set_level(
log_level level)
noexcept {
444 _level.store(level, std::memory_order_relaxed);
448 static void set_ostream(std::ostream& out)
noexcept;
451 static void set_ostream_enabled(
bool enabled)
noexcept;
458 static void set_syslog_enabled(
bool enabled)
noexcept;
467 static void set_shard_field_width(
unsigned width)
noexcept;
472 static void set_with_color(
bool enabled)
noexcept;
483class logger_registry {
484 mutable std::mutex _mutex;
485 std::unordered_map<sstring, logger*> _loggers;
491 void set_all_loggers_level(
log_level level);
497 log_level get_logger_level(sstring name)
const;
504 void set_logger_level(sstring name,
log_level level);
510 std::vector<sstring> get_all_logger_names();
515 void register_logger(logger* l);
519 void unregister_logger(logger* l);
523 void moved(logger* from, logger* to);
526logger_registry& global_logger_registry();
529enum class logger_timestamp_style {
536enum class logger_ostream_type {
542struct logging_settings final {
543 std::unordered_map<sstring, log_level> logger_levels;
548 logger_timestamp_style stdout_timestamp_style = logger_timestamp_style::real;
549 logger_ostream_type logger_ostream = logger_ostream_type::cerr;
554void apply_logging_settings(
const logging_settings&);
556SEASTAR_MODULE_EXPORT_END
560extern thread_local uint64_t logging_failures;
562sstring pretty_type_name(
const std::type_info&);
567class logger_for :
public logger {
569 logger_for() : logger(pretty_type_name(typeid(T))) {}
577std::ostream&
operator<<(std::ostream&,
const std::exception_ptr&);
578std::ostream&
operator<<(std::ostream&,
const std::exception&);
579std::ostream&
operator<<(std::ostream&,
const std::system_error&);
582#if FMT_VERSION >= 90000
583template <>
struct fmt::formatter<
std::exception_ptr> : fmt::ostream_formatter {};
584template <>
struct fmt::formatter<
std::exception> : fmt::ostream_formatter {};
585template <>
struct fmt::formatter<
std::system_error> : fmt::ostream_formatter {};
log_level
log level used with
Definition: log.hh:54
@ none
Dump diagnostic error report for none of the allocation failures.
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
sstring format(fmt::format_string< A... > fmt, A &&... a)
Definition: format.hh:42
ostream & operator<<(ostream &os, const seastar::lazy_eval< Func > &lf)
Definition: lazy.hh:131