166#ifdef VLINK_LOG_LEVEL
167 static constexpr uint8_t kMinimumLevel = VLINK_LOG_LEVEL;
180#ifdef VLINK_LOG_DETAIL_LEVEL
181 static constexpr uint8_t
kDetailLevel = VLINK_LOG_DETAIL_LEVEL;
232 static void init(
const std::string& app_name =
"",
const std::string& log_path =
"") noexcept;
243 static Logger&
get() noexcept;
444 template <
Level LevelT, typename DetailT, typename... ArgsT>
461 template <
Level LevelT, typename DetailT, typename... ArgsT>
479 template <Logger::
Level LevelT, typename DetailT, typename FormatT, typename... ArgsT>
492 template <
Level LevelT, typename... ArgsT>
493 static
void print(ArgsT&&... args);
507 template <Logger::
Level LevelT>
520 if (should_log<LevelT>()) {
522 stream_ = &Logger::get_local_stream();
529 if (should_log<LevelT>()) {
531 stream_ = &Logger::get_local_stream();
533 push_detail_to_stream(detail, *stream_);
539 other.stream_ =
nullptr;
540 other.enabled_ =
false;
548 finalize_log<LevelT>(stream_->take_view());
553 template <
typename T>
557 *stream_ << std::forward<T>(t);
568 bool enabled_{
false};
576 template <Level LevelT>
577 static
bool should_log() noexcept;
579 template <Level LevelT>
580 static
void finalize_log(std::string_view log_view);
582 template <typename DetailT>
583 static
void push_detail_to_stream(DetailT&& detail, FastStream& stream) noexcept;
585 template <typename DetailT>
586 static std::string_view format_with_detail(DetailT&& detail, const
char* msg,
int len) noexcept;
588 static
char* get_local_buffer() noexcept;
590 static FastStream& get_local_stream() noexcept;
592 void write_to_console(Level level, std::string_view log) noexcept;
594 void write_to_file(Level level, std::string_view log) noexcept;
596 std::unique_ptr<struct LoggerImpl> impl_;
598 template <Logger::Level LevelT>
611 auto pos = path.find_last_of(
"/\\");
612 return (pos == std::string_view::npos) ? path : path.substr(pos + 1);
615template <
Logger::Level LevelT,
typename DetailT,
typename... ArgsT>
617 if (!should_log<LevelT>()) {
621 auto& stream = get_local_stream();
623 if constexpr (std::is_same_v<std::decay_t<DetailT>,
DetailInfo>) {
624 push_detail_to_stream(detail, stream);
627 (void)(stream << ... << args);
629 finalize_log<LevelT>(stream.take_view());
632template <
Logger::Level LevelT,
typename DetailT,
typename... ArgsT>
635 [[maybe_unused]] ArgsT&&... args) {
636 if (!should_log<LevelT>()) {
640 std::string_view log_view;
642 auto* local_buffer = get_local_buffer();
644 auto written =
static_cast<int>(result.out - local_buffer);
646 local_buffer[written] =
'\0';
648 log_view = format_with_detail(detail, local_buffer, written);
650 finalize_log<LevelT>(log_view);
653template <
Logger::Level LevelT,
typename DetailT,
typename FormatT,
typename... ArgsT>
655 [[maybe_unused]] ArgsT&&... args) {
656 if (!should_log<LevelT>()) {
660 std::string_view log_view;
662 if constexpr (
sizeof...(ArgsT) == 0) {
665 auto& stream = get_local_stream();
667 if constexpr (std::is_same_v<std::decay_t<DetailT>,
DetailInfo>) {
668 push_detail_to_stream(detail, stream);
672 log_view = stream.take_view();
674 auto* local_buffer = get_local_buffer();
683 log_view = format_with_detail(detail, local_buffer, written);
686 finalize_log<LevelT>(log_view);
694template <Logger::Level LevelT>
695inline bool Logger::should_log() noexcept {
696 if constexpr (LevelT < Logger::kMinimumLevel || LevelT >=
Logger::kOff) {
698 }
else if constexpr (LevelT == Logger::kFatal) {
701 return Logger::is_writable(LevelT);
705template <Logger::Level LevelT>
706inline void Logger::finalize_log(std::string_view log_view) {
707 Logger& instance = Logger::get();
709 instance.write_to_console(LevelT, log_view);
710 instance.write_to_file(LevelT, log_view);
712 if constexpr (LevelT == Logger::kFatal) {
714 throw Exception::RuntimeError(std::string(log_view));
718template <
typename DetailT>
719inline void Logger::push_detail_to_stream(DetailT&& detail, FastStream& stream)
noexcept {
720 auto& [file, line] = detail;
721 stream <<
"{" << file <<
":" << line <<
"} ";
724template <
typename DetailT>
725inline std::string_view Logger::format_with_detail(DetailT&& detail,
const char* msg,
int len)
noexcept {
726 if constexpr (std::is_same_v<std::decay_t<DetailT>, Logger::DetailInfo>) {
727 auto& stream = Logger::get_local_stream();
729 push_detail_to_stream(detail, stream);
732 stream.write_raw(msg,
static_cast<size_t>(len));
735 return stream.take_view();
738 return std::string_view(msg,
static_cast<size_t>(len));
753#define VLINK_LOG_GET_DETAIL(level) \
755 if constexpr ((level) >= VLinkLogger::kDetailLevel) { \
756 return VLinkLogger::DetailInfo{VLinkLogger::extract_filename(__FILE__), __LINE__}; \
758 return VLinkLogger::NoDetail{}; \
762#define VLINK_LOG_HEX(offset) std::hex, std::uppercase, std::setw(offset), std::setfill('0')
764#define VLINK_LOG_HEXSS(offset) std::hex << std::uppercase << std::setw(offset) << std::setfill('0')
766#define VLINK_LOG_IF_T VLinkLogger::is_writable(VLinkLogger::kTrace)
768#define VLINK_LOG_IF_D VLinkLogger::is_writable(VLinkLogger::kDebug)
770#define VLINK_LOG_IF_I VLinkLogger::is_writable(VLinkLogger::kInfo)
772#define VLINK_LOG_IF_W VLinkLogger::is_writable(VLinkLogger::kWarn)
774#define VLINK_LOG_IF_E VLinkLogger::is_writable(VLinkLogger::kError)
776#define VLINK_LOG_IF_F VLinkLogger::is_writable(VLinkLogger::kFatal)
778#define VLINK_LOG_T(...) \
779 VLinkLogger::print_stream_style<VLinkLogger::kTrace>(VLINK_LOG_GET_DETAIL(VLinkLogger::kTrace), __VA_ARGS__)
781#define VLINK_LOG_D(...) \
782 VLinkLogger::print_stream_style<VLinkLogger::kDebug>(VLINK_LOG_GET_DETAIL(VLinkLogger::kDebug), __VA_ARGS__)
784#define VLINK_LOG_I(...) \
785 VLinkLogger::print_stream_style<VLinkLogger::kInfo>(VLINK_LOG_GET_DETAIL(VLinkLogger::kInfo), __VA_ARGS__)
787#define VLINK_LOG_W(...) \
788 VLinkLogger::print_stream_style<VLinkLogger::kWarn>(VLINK_LOG_GET_DETAIL(VLinkLogger::kWarn), __VA_ARGS__)
790#define VLINK_LOG_E(...) \
791 VLinkLogger::print_stream_style<VLinkLogger::kError>(VLINK_LOG_GET_DETAIL(VLinkLogger::kError), __VA_ARGS__)
793#define VLINK_LOG_F(...) \
794 VLinkLogger::print_stream_style<VLinkLogger::kFatal>(VLINK_LOG_GET_DETAIL(VLinkLogger::kFatal), __VA_ARGS__)
796#define VLINK_MLOG_T(...) \
797 VLinkLogger::print_format_style<VLinkLogger::kTrace>(VLINK_LOG_GET_DETAIL(VLinkLogger::kTrace), __VA_ARGS__)
799#define VLINK_MLOG_D(...) \
800 VLinkLogger::print_format_style<VLinkLogger::kDebug>(VLINK_LOG_GET_DETAIL(VLinkLogger::kDebug), __VA_ARGS__)
802#define VLINK_MLOG_I(...) \
803 VLinkLogger::print_format_style<VLinkLogger::kInfo>(VLINK_LOG_GET_DETAIL(VLinkLogger::kInfo), __VA_ARGS__)
805#define VLINK_MLOG_W(...) \
806 VLinkLogger::print_format_style<VLinkLogger::kWarn>(VLINK_LOG_GET_DETAIL(VLinkLogger::kWarn), __VA_ARGS__)
808#define VLINK_MLOG_E(...) \
809 VLinkLogger::print_format_style<VLinkLogger::kError>(VLINK_LOG_GET_DETAIL(VLinkLogger::kError), __VA_ARGS__)
811#define VLINK_MLOG_F(...) \
812 VLinkLogger::print_format_style<VLinkLogger::kFatal>(VLINK_LOG_GET_DETAIL(VLinkLogger::kFatal), __VA_ARGS__)
814#define VLINK_CLOG_T(...) \
815 VLinkLogger::print_c_style<VLinkLogger::kTrace>(VLINK_LOG_GET_DETAIL(VLinkLogger::kTrace), __VA_ARGS__)
817#define VLINK_CLOG_D(...) \
818 VLinkLogger::print_c_style<VLinkLogger::kDebug>(VLINK_LOG_GET_DETAIL(VLinkLogger::kDebug), __VA_ARGS__)
820#define VLINK_CLOG_I(...) \
821 VLinkLogger::print_c_style<VLinkLogger::kInfo>(VLINK_LOG_GET_DETAIL(VLinkLogger::kInfo), __VA_ARGS__)
823#define VLINK_CLOG_W(...) \
824 VLinkLogger::print_c_style<VLinkLogger::kWarn>(VLINK_LOG_GET_DETAIL(VLinkLogger::kWarn), __VA_ARGS__)
826#define VLINK_CLOG_E(...) \
827 VLinkLogger::print_c_style<VLinkLogger::kError>(VLINK_LOG_GET_DETAIL(VLinkLogger::kError), __VA_ARGS__)
829#define VLINK_CLOG_F(...) \
830 VLinkLogger::print_c_style<VLinkLogger::kFatal>(VLINK_LOG_GET_DETAIL(VLinkLogger::kFatal), __VA_ARGS__)
832#define VLINK_SLOG_T VLinkLogger::WrapperStream<VLinkLogger::kTrace>(VLINK_LOG_GET_DETAIL(VLinkLogger::kTrace))
834#define VLINK_SLOG_D VLinkLogger::WrapperStream<VLinkLogger::kDebug>(VLINK_LOG_GET_DETAIL(VLinkLogger::kDebug))
836#define VLINK_SLOG_I VLinkLogger::WrapperStream<VLinkLogger::kInfo>(VLINK_LOG_GET_DETAIL(VLinkLogger::kInfo))
838#define VLINK_SLOG_W VLinkLogger::WrapperStream<VLinkLogger::kWarn>(VLINK_LOG_GET_DETAIL(VLinkLogger::kWarn))
840#define VLINK_SLOG_E VLinkLogger::WrapperStream<VLinkLogger::kError>(VLINK_LOG_GET_DETAIL(VLinkLogger::kError))
842#define VLINK_SLOG_F VLinkLogger::WrapperStream<VLinkLogger::kFatal>(VLINK_LOG_GET_DETAIL(VLinkLogger::kFatal))
844#ifndef VLINK_LOG_DISABLE_SHORT
846#define VLOG_T(...) VLINK_LOG_T(__VA_ARGS__)
848#define VLOG_D(...) VLINK_LOG_D(__VA_ARGS__)
850#define VLOG_I(...) VLINK_LOG_I(__VA_ARGS__)
852#define VLOG_W(...) VLINK_LOG_W(__VA_ARGS__)
854#define VLOG_E(...) VLINK_LOG_E(__VA_ARGS__)
856#define VLOG_F(...) VLINK_LOG_F(__VA_ARGS__)
858#define CLOG_T(...) VLINK_CLOG_T(__VA_ARGS__)
860#define CLOG_D(...) VLINK_CLOG_D(__VA_ARGS__)
862#define CLOG_I(...) VLINK_CLOG_I(__VA_ARGS__)
864#define CLOG_W(...) VLINK_CLOG_W(__VA_ARGS__)
866#define CLOG_E(...) VLINK_CLOG_E(__VA_ARGS__)
868#define CLOG_F(...) VLINK_CLOG_F(__VA_ARGS__)
870#define MLOG_T(...) VLINK_MLOG_T(__VA_ARGS__)
872#define MLOG_D(...) VLINK_MLOG_D(__VA_ARGS__)
874#define MLOG_I(...) VLINK_MLOG_I(__VA_ARGS__)
876#define MLOG_W(...) VLINK_MLOG_W(__VA_ARGS__)
878#define MLOG_E(...) VLINK_MLOG_E(__VA_ARGS__)
880#define MLOG_F(...) VLINK_MLOG_F(__VA_ARGS__)
882#define SLOG_T VLINK_SLOG_T
884#define SLOG_D VLINK_SLOG_D
886#define SLOG_I VLINK_SLOG_I
888#define SLOG_W VLINK_SLOG_W
890#define SLOG_E VLINK_SLOG_E
892#define SLOG_F VLINK_SLOG_F
High-performance std::ostream with an embedded resizable string buffer.
定义 fast_stream.h:78
RAII stream wrapper that accumulates tokens and flushes on destruction.
定义 logger.h:508
static constexpr bool kIsEnabled
Indicates whether this level is enabled at compile time.
定义 logger.h:516
WrapperStream & operator<<(T &&t) noexcept
定义 logger.h:554
WrapperStream & operator=(WrapperStream &&)=delete
WrapperStream(WrapperStream &&other) noexcept
定义 logger.h:538
WrapperStream(Logger::NoDetail) noexcept
定义 logger.h:518
WrapperStream(DetailInfo &&detail) noexcept
定义 logger.h:527
~WrapperStream()
定义 logger.h:545
Global singleton logger supporting three output styles and configurable log levels.
定义 logger.h:116
static constexpr uint8_t kDetailLevel
Threshold above which file and line information is appended to messages.
定义 logger.h:183
static int get_stream_width() noexcept
Returns the field width currently used for stream output.
static void register_file_handler(Callback &&callback) noexcept
Registers a custom handler for file log output.
static void print_stream_style(DetailT &&detail, ArgsT &&... args)
Logs using stream-style composition (operator<<).
定义 logger.h:616
static bool get_console_fmt_enable() noexcept
Returns whether ANSI colour/format codes are enabled for console output.
std::function< void(Level, std::string_view)> Callback
Callback type for custom console or file log handlers.
定义 logger.h:202
static void set_stream_width(int width) noexcept
Sets the output field width for stream-style messages.
static void register_console_handler(Callback &&callback) noexcept
Registers a custom handler for console log output.
static void set_file_level(Level level) noexcept
Sets the minimum level for the file sink.
static Logger & get() noexcept
Returns the logger singleton instance.
static void set_stream_precision(int precision) noexcept
Sets the floating-point precision for stream-style messages.
static void set_console_level(Level level) noexcept
Sets the minimum level for the console sink.
static constexpr std::string_view extract_filename(std::string_view path) noexcept
Extracts the file name component from a full path at compile time.
定义 logger.h:610
Level
Severity level for log messages.
定义 logger.h:148
static void set_console_fmt_enable(bool enable) noexcept
Enables or disables ANSI colour/format codes in console output.
static Level get_console_level() noexcept
Returns the current minimum level for the console sink.
static bool is_busy() noexcept
Returns true if the logger is currently busy writing a message.
static bool is_writable(Level level) noexcept
Returns true if a message at level would be written to at least one sink.
static constexpr int kLocalBufferSize
Size of the thread-local C-style format buffer in bytes.
定义 logger.h:193
static Level get_file_level() noexcept
Returns the current minimum level for the file sink.
static constexpr uint8_t kMinimumLevel
Compile-time minimum log level.
定义 logger.h:169
static std::ios_base::fmtflags get_stream_flag() noexcept
Returns the std::ios_base format flags currently applied to stream output.
static void set_stream_flag(std::ios_base::fmtflags flags) noexcept
Sets std::ios_base format flags applied to stream-style messages.
static void dump_backtrace() noexcept
Flushes the backtrace ring buffer to the active sinks.
Style
Output style selector (used internally by the print_* family).
定义 logger.h:125
@ kStreamStyle
operator<< stream composition via FastStream
定义 logger.h:126
@ kFormatStyle
Python-style {} placeholders via vlink::format
定义 logger.h:127
@ kCStyle
printf-style d/s via std::snprintf
定义 logger.h:128
static void flush() noexcept
Flushes all buffered log messages to the active sinks.
std::pair< std::string_view, int > DetailInfo
Carries the source file name and line number for detail annotation.
定义 logger.h:211
static void print_format_style(DetailT &&detail, format::format_string< ArgsT... > format, ArgsT &&... args)
Logs using {} placeholder format style.
定义 logger.h:633
static void enable_backtrace(size_t size) noexcept
Enables a ring-buffer backtrace of the last size log messages.
static void print_c_style(DetailT &&detail, FormatT &&format, ArgsT &&... args)
Logs using C-style printf format string.
定义 logger.h:654
static void disable_backtrace() noexcept
Disables backtrace collection and clears the ring buffer.
static void init(const std::string &app_name="", const std::string &log_path="") noexcept
Initialises the logger singleton.
static int get_stream_precision() noexcept
Returns the floating-point precision currently used for stream output.
static void print(ArgsT &&... args)
Logs using stream style without file/line detail.
定义 logger.h:690
VLink-specific exception types wrapping the C++ standard exception hierarchy.
A high-performance std::ostream backed by a resizable std::string buffer.
vlink::Logger VLinkLogger
定义 logger.h:747
Platform-independent macro definitions for the VLink library.
#define VUNLIKELY(...)
Shorthand alias for VLINK_UNLIKELY. Hints that the expression is unlikely true.
定义 macros.h:302
#define VLINK_SINGLETON_CHECK(classname)
Injects a compile-time and run-time singleton enforcement guard.
定义 macros.h:203
#define VLINK_EXPORT
定义 macros.h:85
#define VLIKELY(...)
Shorthand alias for VLINK_LIKELY. Hints that the expression is likely true.
定义 macros.h:297
#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
Deletes the copy constructor and copy-assignment operator of classname.
定义 macros.h:184
Sentinel type indicating that no file/line detail is attached.
定义 logger.h:219