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>
38#include <boost/lexical_cast.hpp>
40#include <fmt/format.h>
48SEASTAR_MODULE_EXPORT_BEGIN
63std::ostream& operator<<(std::ostream& out,
log_level level);
64std::istream& operator>>(std::istream& in,
log_level& level);
66SEASTAR_MODULE_EXPORT_END
71 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
72 auto format(
seastar::log_level level, fmt::format_context& ctx)
const ->
decltype(ctx.out());
84SEASTAR_MODULE_EXPORT_BEGIN
101 std::atomic<log_level> _level = { log_level::info };
102 static std::ostream* _out;
103 static std::atomic<bool> _ostream;
104 static std::atomic<bool> _syslog;
105 static unsigned _shard_field_width;
106#ifdef SEASTAR_BUILD_SHARED_LIBS
107 static thread_local bool silent;
109 static inline thread_local bool silent =
false;
115 virtual ~log_writer() =
default;
116 virtual internal::log_buf::inserter_iterator operator()(internal::log_buf::inserter_iterator) = 0;
118 template <
typename Func>
119 requires requires (Func fn, internal::log_buf::inserter_iterator it) {
122 class lambda_log_writer :
public log_writer {
125 lambda_log_writer(Func&& func) : _func(
std::forward<Func>(func)) { }
126 virtual ~lambda_log_writer()
override =
default;
127 virtual internal::log_buf::inserter_iterator operator()(internal::log_buf::inserter_iterator it)
override {
return _func(it); }
132#ifdef SEASTAR_LOGGER_COMPILE_TIME_FMT
133 template<
typename... Args>
139 std::enable_if_t<std::is_convertible_v<const S&, std::string_view>,
int> = 0>
140 FMT_CONSTEVAL
inline format_info(
const S&
format,
141 compat::source_location loc = compat::source_location::current()) noexcept
149 inline format_info(fmt::format_string<Args...> s,
150 compat::source_location loc = compat::source_location::current()) noexcept
154#if FMT_VERSION >= 100000
155 using runtime_format_string_t = fmt::runtime_format_string<char>;
157 using runtime_format_string_t = fmt::basic_runtime<char>;
159 inline format_info(runtime_format_string_t s,
160 compat::source_location loc = compat::source_location::current()) noexcept
165 FMT_CONSTEVAL format_info() noexcept
168 fmt::format_string<Args...>
format;
169 compat::source_location loc;
171#ifdef __cpp_lib_type_identity
172 template <
typename T>
173 using type_identity_t =
typename std::type_identity<T>::type;
175 template <
typename T>
struct type_identity {
using type = T; };
176 template <
typename T>
using type_identity_t =
typename type_identity<T>::type;
178 template <
typename... Args>
179 using format_info_t = format_info<type_identity_t<Args>...>;
186 format_info(
const char*
format, compat::source_location loc = compat::source_location::current()) noexcept
192 format_info(std::string_view
format, compat::source_location loc = compat::source_location::current()) noexcept
197 format_info(compat::source_location loc = compat::source_location::current()) noexcept
202 compat::source_location loc;
206 template <
typename...>
207 using format_info_t = format_info;
213 void do_log(
log_level level, log_writer& writer);
214 void failed_to_log(std::exception_ptr ex,
215 fmt::string_view fmt,
216 compat::source_location loc)
noexcept;
220 silencer() noexcept {
254 using clock = lowres_clock;
257 clock::duration _interval;
258 clock::time_point _next;
259 uint64_t _dropped_messages = 0;
263 bool has_dropped_messages()
const {
return bool(_dropped_messages); }
264 uint64_t get_and_reset_dropped_messages() {
265 return std::exchange(_dropped_messages, 0);
269 explicit rate_limit(std::chrono::milliseconds interval);
273 explicit logger(sstring name);
277 bool is_shard_zero() noexcept;
283 bool is_enabled(
log_level level) const noexcept {
284 return __builtin_expect(level <= _level.load(std::memory_order_relaxed),
false) && !silent;
293 template <
typename... Args>
294 void log(
log_level level, format_info_t<Args...> fmt, Args&&... args)
noexcept {
295 if (is_enabled(level)) {
297 lambda_log_writer writer([&] (internal::log_buf::inserter_iterator it) {
298#ifdef SEASTAR_LOGGER_COMPILE_TIME_FMT
299 return fmt::format_to(it, fmt.format, std::forward<Args>(args)...);
301 return fmt::format_to(it, fmt::runtime(fmt.format), std::forward<Args>(args)...);
304 do_log(level, writer);
306 failed_to_log(std::current_exception(), fmt::string_view(fmt.format), fmt.loc);
325 template <
typename... Args>
326 void log(
log_level level, rate_limit& rl, format_info_t<Args...> fmt, Args&&... args)
noexcept {
327 if (is_enabled(level) && rl.check()) {
329 lambda_log_writer writer([&] (internal::log_buf::inserter_iterator it) {
330 if (rl.has_dropped_messages()) {
331 it = fmt::format_to(it,
"(rate limiting dropped {} similar messages) ", rl.get_and_reset_dropped_messages());
333 return fmt::format_to(it, fmt::runtime(fmt.format), std::forward<Args>(args)...);
335 do_log(level, writer);
337 failed_to_log(std::current_exception(), fmt::string_view(fmt.format), fmt.loc);
352 void log(
log_level level, rate_limit& rl, log_writer& writer, format_info_t<> fmt = {})
noexcept {
353 if (is_enabled(level) && rl.check()) {
355 lambda_log_writer writer_wrapper([&] (internal::log_buf::inserter_iterator it) {
356 if (rl.has_dropped_messages()) {
357 it = fmt::format_to(it,
"(rate limiting dropped {} similar messages) ", rl.get_and_reset_dropped_messages());
361 do_log(level, writer_wrapper);
363 failed_to_log(std::current_exception(),
"", fmt.loc);
376 template <
typename... Args>
377 void error(format_info_t<Args...> fmt, Args&&... args)
noexcept {
378 log(log_level::error, std::move(fmt), std::forward<Args>(args)...);
387 template <
typename... Args>
388 void warn(format_info_t<Args...> fmt, Args&&... args)
noexcept {
389 log(log_level::warn, std::move(fmt), std::forward<Args>(args)...);
398 template <
typename... Args>
399 void info(format_info_t<Args...> fmt, Args&&... args)
noexcept {
400 log(log_level::info, std::move(fmt), std::forward<Args>(args)...);
409 template <
typename... Args>
410 void info0(format_info_t<Args...> fmt, Args&&... args)
noexcept {
411 if (is_shard_zero()) {
412 log(log_level::info, std::move(fmt), std::forward<Args>(args)...);
422 template <
typename... Args>
423 void debug(format_info_t<Args...> fmt, Args&&... args)
noexcept {
424 log(log_level::debug, std::move(fmt), std::forward<Args>(args)...);
433 template <
typename... Args>
434 void trace(format_info_t<Args...> fmt, Args&&... args)
noexcept {
435 log(log_level::trace, std::move(fmt), std::forward<Args>(args)...);
440 const sstring& name() const noexcept {
447 return _level.load(std::memory_order_relaxed);
452 void set_level(
log_level level)
noexcept {
453 _level.store(level, std::memory_order_relaxed);
457 static void set_ostream(std::ostream& out)
noexcept;
460 static void set_ostream_enabled(
bool enabled)
noexcept;
463 [[deprecated(
"Use set_ostream_enabled instead")]]
464 static void set_stdout_enabled(
bool enabled)
noexcept;
471 static void set_syslog_enabled(
bool enabled)
noexcept;
480 static void set_shard_field_width(
unsigned width)
noexcept;
485 static void set_with_color(
bool enabled)
noexcept;
496class logger_registry {
497 mutable std::mutex _mutex;
498 std::unordered_map<sstring, logger*> _loggers;
504 void set_all_loggers_level(
log_level level);
510 log_level get_logger_level(sstring name)
const;
517 void set_logger_level(sstring name,
log_level level);
523 std::vector<sstring> get_all_logger_names();
528 void register_logger(logger* l);
532 void unregister_logger(logger* l);
536 void moved(logger* from, logger* to);
539logger_registry& global_logger_registry();
542enum class logger_timestamp_style {
549enum class logger_ostream_type {
551#ifdef SEASTAR_LOGGER_TYPE_STDOUT
552 stdout __attribute__ ((deprecated (
"use cout instead"))) = 1,
553 stderr __attribute__ ((deprecated (
"use cerr instead"))) = 2,
559struct logging_settings final {
560 std::unordered_map<sstring, log_level> logger_levels;
565 logger_timestamp_style stdout_timestamp_style = logger_timestamp_style::real;
566 logger_ostream_type logger_ostream = logger_ostream_type::cerr;
571void apply_logging_settings(
const logging_settings&);
573SEASTAR_MODULE_EXPORT_END
577extern thread_local uint64_t logging_failures;
579sstring pretty_type_name(
const std::type_info&);
584class logger_for :
public logger {
586 logger_for() : logger(pretty_type_name(typeid(T))) {}
594std::ostream&
operator<<(std::ostream&,
const std::exception_ptr&);
595std::ostream&
operator<<(std::ostream&,
const std::exception&);
596std::ostream&
operator<<(std::ostream&,
const std::system_error&);
599#if FMT_VERSION >= 90000
600template <>
struct fmt::formatter<
std::exception_ptr> : fmt::ostream_formatter {};
601template <>
struct fmt::formatter<
std::exception> : fmt::ostream_formatter {};
602template <>
struct fmt::formatter<
std::system_error> : fmt::ostream_formatter {};
log_level
log level used with
Definition: log.hh:55
@ 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