2#include "gaia/config/config_core.h"
8#include "gaia/cnt/darray_ext.h"
11#ifndef GAIA_LOG_BUFFER_SIZE
12 #define GAIA_LOG_BUFFER_SIZE 32 * 1024
15#ifndef GAIA_LOG_BUFFER_ENTRIES
16 #define GAIA_LOG_BUFFER_ENTRIES 2048
21 using LogLevelType = uint8_t;
23 enum class LogLevel : LogLevelType { Debug = 0x1, Info = 0x2, Warning = 0x4, Error = 0x8 };
24 inline LogLevelType g_logLevelMask = (LogLevelType)LogLevel::Debug | (LogLevelType)LogLevel::Info |
25 (LogLevelType)LogLevel::Warning | (LogLevelType)LogLevel::Error;
30 inline void log_enable(LogLevel level,
bool value) {
32 gaia::util::g_logLevelMask |= ((LogLevelType)level);
34 gaia::util::g_logLevelMask &= ~((LogLevelType)level);
38 inline bool is_logging_enabled(LogLevel level) {
39 return ((LogLevelType)level & g_logLevelMask) != 0;
42 using LogLineFunc = void (*)(LogLevel,
const char*);
43 using LogFunc = void (*)(LogLevel,
const char*, va_list);
44 using LogFlushFunc = void (*)();
47 inline constexpr uint32_t LOG_BUFFER_SIZE = GAIA_LOG_BUFFER_SIZE;
48 inline constexpr uint32_t LOG_RECORD_LIMIT = GAIA_LOG_BUFFER_ENTRIES;
50 inline FILE* get_log_out(LogLevel level) {
51 const auto mask = (LogLevelType)level & ((LogLevelType)LogLevel::Error | (LogLevelType)LogLevel::Warning);
53 return mask != 0 ? stderr : stdout;
59 inline void log_line(LogLevel level,
const char* msg) {
60 FILE* out = get_log_out(level);
62 static constexpr const char* colors[] = {
69 const auto lvl = (uint32_t)level;
70 const auto idx = GAIA_CLZ(lvl);
71 fprintf(out,
"%s%s\033[0m\n", colors[idx], msg);
73 inline LogLineFunc g_log_line_func = log_line;
83 char m_buffer[LOG_BUFFER_SIZE];
85 uint32_t m_buffer_pos = 0;
86 uint32_t m_recs_pos = 0;
94 void log(LogLevel level, uint32_t len,
const char* msg) {
95 FILE* out = get_log_out(level);
96 const bool is_assert = out == stderr;
99 if (is_assert || len >= detail::LOG_BUFFER_SIZE) {
104 g_log_line_func(level, msg);
110 if (m_buffer_pos + len > detail::LOG_BUFFER_SIZE || m_recs_pos >= detail::LOG_RECORD_LIMIT)
114 auto& rec = m_recs[m_recs_pos];
115 rec.offset = m_buffer_pos;
116 rec.level = (LogLevelType)level;
117 memcpy(m_buffer + m_buffer_pos, msg, len);
127 for (
size_t i = 0; i < m_recs_pos; ++i) {
128 const auto& rec = m_recs[i];
129 g_log_line_func((LogLevel)rec.level, &m_buffer[rec.offset]);
140 setvbuf(stdout,
nullptr, _IOFBF, 4096);
141 setvbuf(stderr,
nullptr, _IOFBF, 4096);
148 LogBuffer(
const LogBuffer&) =
delete;
149 LogBuffer(LogBuffer&&) =
delete;
150 LogBuffer& operator=(
const LogBuffer&) =
delete;
151 LogBuffer& operator=(LogBuffer&&) =
delete;
154 inline LogBuffer* g_log() {
155 static LogBuffer* s_log =
nullptr;
156 if (s_log ==
nullptr) {
157 s_log =
new LogBuffer();
159 static struct LogAtExit {
160 LogAtExit() =
default;
162 if (s_log !=
nullptr) {
169 LogAtExit(
const LogAtExit&) =
delete;
170 LogAtExit(LogAtExit&&) =
delete;
171 LogAtExit& operator=(
const LogAtExit&) =
delete;
172 LogAtExit& operator=(LogAtExit&&) =
delete;
179 inline void log_cached(LogLevel level,
const char* fmt, va_list args) {
182 GAIA_CLANG_WARNING_PUSH()
183 GAIA_GCC_WARNING_PUSH()
184 GAIA_CLANG_WARNING_DISABLE("-Wformat-nonliteral")
185 GAIA_GCC_WARNING_DISABLE("-Wformat-nonliteral")
187 va_copy(args_copy, args);
188 int l = vsnprintf(
nullptr, 0, fmt, args_copy);
193 const auto len = (uint32_t)l;
194 cnt::darray_ext<
char, 1024> msg(len + 1);
196 va_copy(args_copy, args);
197 vsnprintf(msg.data(), msg.size(), fmt, args_copy);
199 GAIA_GCC_WARNING_POP()
200 GAIA_CLANG_WARNING_POP()
208 g_log()->log(level, msg.size(), msg.data());
212 inline
void log_flush_cached() {
219 inline void log_default(LogLevel level,
const char* fmt, va_list args) {
222 GAIA_CLANG_WARNING_PUSH()
223 GAIA_GCC_WARNING_PUSH()
224 GAIA_CLANG_WARNING_DISABLE("-Wformat-nonliteral")
225 GAIA_GCC_WARNING_DISABLE("-Wformat-nonliteral")
227 va_copy(args_copy, args);
228 int l = vsnprintf(
nullptr, 0, fmt, args_copy);
233 const auto len = (uint32_t)l;
234 cnt::darray_ext<
char, 1024> msg(len + 1);
236 va_copy(args_copy, args);
237 vsnprintf(msg.data(), msg.size(), fmt, args_copy);
239 GAIA_GCC_WARNING_POP()
240 GAIA_CLANG_WARNING_POP()
245 g_log_line_func(level, msg.data());
251 inline
void log_flush_default() {}
253 inline LogFunc g_log_func = log_default;
254 inline LogFlushFunc g_log_flush_func = log_flush_default;
260 inline void set_log_func(LogFunc func) {
261 detail::g_log_func = func !=
nullptr ? func : detail::log_default;
266 inline void set_log_line_func(LogLineFunc func) {
267 detail::g_log_line_func = func !=
nullptr ? func : detail::log_line;
272 inline void set_log_flush_func(LogFlushFunc func) {
273 detail::g_log_flush_func = func !=
nullptr ? func : detail::log_flush_default;
279 inline void log(LogLevel level,
const char* fmt, ...) {
280 if (!is_logging_enabled(level))
285 detail::g_log_func(level, fmt, args);
289 inline void log_flush() {
290 detail::g_log_flush_func();
298typedef void (*gaia_log_line_func_t)(gaia::util::LogLevelType level,
const char* msg);
299inline void gaia_set_log_func(gaia_log_line_func_t func) {
300 gaia::util::set_log_line_func((gaia::util::LogLineFunc)func);
303inline void gaia_log(uint8_t level,
const char* msg) {
304 gaia::util::log((gaia::util::LogLevel)level,
"%s", msg);
307typedef void (*gaia_log_flush_func_t)();
308inline void gaia_set_flush_func(gaia_log_flush_func_t func) {
309 gaia::util::set_log_flush_func((gaia::util::LogFlushFunc)func);
312inline void gaia_flush_logs() {
313 gaia::util::log_flush();
316inline void gaia_log_enable(gaia::util::LogLevelType level,
bool value) {
317 gaia::util::log_enable((gaia::util::LogLevel)level, value);
320inline bool gaia_is_logging_enabled(gaia::util::LogLevelType level) {
321 return gaia::util::is_logging_enabled((gaia::util::LogLevel)level);
326#define GAIA_LOG_D(...) gaia::util::log(gaia::util::LogLevel::Debug, __VA_ARGS__)
327#define GAIA_LOG_N(...) gaia::util::log(gaia::util::LogLevel::Info, __VA_ARGS__)
328#define GAIA_LOG_W(...) gaia::util::log(gaia::util::LogLevel::Warning, __VA_ARGS__)
329#define GAIA_LOG_E(...) gaia::util::log(gaia::util::LogLevel::Error, __VA_ARGS__)
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
void log(LogLevel level, uint32_t len, const char *msg)
Logs a message. We implement a buffering strategy. Warnings and errors flush immediately....
Definition logging.h:94