10#include <MPMCQueue.hpp>
21inline constexpr auto kReset =
"\033[0m";
22inline constexpr auto kRed =
"\033[31m";
23inline constexpr auto kGreen =
"\033[32m";
24inline constexpr auto kYellow =
"\033[33m";
25inline constexpr auto kCyan =
"\033[36m";
38 static_cast<Level>(SIMPLEKERNEL_MIN_LOG_LEVEL);
67static_assert(
sizeof(LogEntry) == 256,
"LogEntry must be 256 bytes");
70inline mpmc_queue::MPMCQueue<LogEntry, 256>
log_queue;
82__always_inline
auto PutStr(
const char* s) ->
void {
100 if (
drain_flag.test_and_set(std::memory_order_acquire)) {
105 auto dropped =
dropped_count.exchange(0, std::memory_order_relaxed);
108 auto*
end = etl::format_to_n(drop_buf,
sizeof(drop_buf) - 1,
109 "\033[31m[LOG] dropped {} entries\033[0m\n",
110 static_cast<uint64_t
>(dropped));
122 etl::format_to_n(hdr_buf,
sizeof(hdr_buf) - 1,
"[{}][{} {} {}]",
123 entry.seq, entry.core_id, printer_core,
142template <
Level Lvl,
typename... Args>
143__always_inline
auto Log(etl::format_string<Args...> fmt, Args&&... args)
150 entry.
seq =
log_seq.fetch_add(1, std::memory_order_relaxed);
153 auto*
end = etl::format_to_n(entry.msg,
sizeof(entry.msg) - 1, fmt,
154 static_cast<Args&&
>(args)...);
172template <
typename... Args>
173inline auto Debug(etl::format_string<Args...> fmt, Args&&... args) ->
void {
177 detail::Log<detail::Level::kDebug>(fmt,
static_cast<Args&&
>(args)...);
181template <
typename... Args>
182inline auto Info(etl::format_string<Args...> fmt, Args&&... args) ->
void {
186 detail::Log<detail::Level::kInfo>(fmt,
static_cast<Args&&
>(args)...);
190template <
typename... Args>
191inline auto Warn(etl::format_string<Args...> fmt, Args&&... args) ->
void {
195 detail::Log<detail::Level::kWarn>(fmt,
static_cast<Args&&
>(args)...);
199template <
typename... Args>
200inline auto Err(etl::format_string<Args...> fmt, Args&&... args) ->
void {
204 detail::Log<detail::Level::kErr>(fmt,
static_cast<Args&&
>(args)...);
auto etl_putchar(int c) -> void
早期控制台字符输出
auto GetCurrentCoreId() -> size_t
std::atomic_flag drain_flag
单消费者排空保护(非阻塞 try-lock)
__always_inline auto Log(etl::format_string< Args... > fmt, Args &&... args) -> void
核心实现:格式化消息并入队,随后尝试排空
std::atomic< uint64_t > log_seq
用于跨核心排序的单调递增序列计数器
constexpr const char * kLevelLabel[]
日志级别标签(定宽,对齐输出)
mpmc_queue::MPMCQueue< LogEntry, 256 > log_queue
全局日志队列(64 KB 静态内存,constexpr 构造)
constexpr auto kMinLevel
编译期最低日志级别
__always_inline auto PutStr(const char *s) -> void
通过 etl_putchar 输出字符串(空指针安全)
auto TryDrain() -> void
将队列中所有条目输出至串口
constexpr const char * kLevelColor[]
日志级别对应的颜色(按 Level 枚举索引)
std::atomic< uint64_t > dropped_count
队列满时丢弃的条目计数
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
__always_inline auto RawPut(const char *msg) -> void
绕过队列直接输出至串口(用于 panic 路径)
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
__always_inline auto Flush() -> void
强制将队列中所有日志条目输出至串口
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志