154 lines
4.5 KiB
C
154 lines
4.5 KiB
C
W32_SharedLogState W32_shared_log_state = ZI;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ @hookdef Init hooks
|
|
|
|
void InitLogSystem(String logfile_path)
|
|
{
|
|
__prof;
|
|
W32_SharedLogState *g = &W32_shared_log_state;
|
|
g->logs_arena = AcquireArena(Gibi(64));
|
|
g->log_msgs_arena = AcquireArena(Gibi(64));
|
|
g->readable_log_events = ArenaNext(g->logs_arena, LogEvent);
|
|
if (logfile_path.len > 0)
|
|
{
|
|
TempArena scratch = BeginScratchNoConflict();
|
|
{
|
|
wchar_t *path_wstr = WstrFromString(scratch.arena, logfile_path);
|
|
g->logfile = CreateFileW(path_wstr,
|
|
FILE_APPEND_DATA,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0);
|
|
}
|
|
EndScratch(scratch);
|
|
}
|
|
Atomic32Set(&g->initialized, 1);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ Log
|
|
|
|
void W32_Log(i32 level, String msg)
|
|
{
|
|
__prof;
|
|
W32_SharedLogState *g = &W32_shared_log_state;
|
|
TempArena scratch = BeginScratchNoConflict();
|
|
if (Atomic32Fetch(&g->initialized))
|
|
{
|
|
LogLevelSettings settings = log_settings[level];
|
|
if (level < 0 || level >= LogLevel_Count)
|
|
{
|
|
Panic(Lit("Invalid log level"));
|
|
}
|
|
__profmsg((char *)msg.text, msg.len, settings.color);
|
|
|
|
DateTime datetime = LocalDateTime();
|
|
i64 now_ns = TimeNs();
|
|
i32 thread_id = GetCurrentThreadId();
|
|
i32 fiber_id = FiberId();
|
|
|
|
//- Log message to file
|
|
/* TODO: Log asynchronously */
|
|
{
|
|
String shorthand = settings.shorthand;
|
|
String msg_formatted = StringF(
|
|
scratch.arena,
|
|
"[%F:%F:%F.%F] |%F| <%F> [%F] %F\n",
|
|
|
|
/* Time */
|
|
FmtUintZ(datetime.hour, 2),
|
|
FmtUintZ(datetime.minute, 2),
|
|
FmtUintZ(datetime.second, 2),
|
|
FmtUintZ(datetime.milliseconds, 3),
|
|
|
|
/* Thread id */
|
|
FmtUintZ(thread_id, 5),
|
|
|
|
/* Fiber id */
|
|
FmtUintZ(fiber_id, 4),
|
|
|
|
/* Level */
|
|
FmtString(shorthand),
|
|
|
|
/* Message */
|
|
FmtString(msg)
|
|
);
|
|
WriteFile(g->logfile, msg_formatted.text, msg_formatted.len, 0, 0);
|
|
}
|
|
|
|
//- Log message to queue
|
|
/* TODO: Log asynchronously */
|
|
LockTicketMutex(&g->logs_tm);
|
|
{
|
|
/* Get staged data */
|
|
LogEvent *ev = PushStruct(g->logs_arena, LogEvent);
|
|
ev->msg = PushString(g->log_msgs_arena, msg);
|
|
ev->datetime = datetime;
|
|
ev->time_ns = now_ns;
|
|
ev->level = level;
|
|
ev->thread_id = thread_id;
|
|
ev->fiber_id = fiber_id;
|
|
ev->id = g->logs_count++;
|
|
ev->level_id = g->log_level_counts[level]++;
|
|
Atomic64Set(&g->readable_logs_count, g->logs_count);
|
|
}
|
|
UnlockTicketMutex(&g->logs_tm);
|
|
}
|
|
EndScratch(scratch);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//~ @hookdef Log hooks
|
|
|
|
/* Panic log function is separate to enforce zero side effects other than
|
|
* immediately writing to log file. */
|
|
void LogPanic(String msg)
|
|
{
|
|
W32_SharedLogState *g = &W32_shared_log_state;
|
|
if (Atomic32Fetch(&g->initialized))
|
|
{
|
|
String beg = Lit("******** PANICKING ********\n");
|
|
String end = Lit("\n***************************\n");
|
|
WriteFile(g->logfile, beg.text, beg.len, 0, 0);
|
|
WriteFile(g->logfile, msg.text, msg.len, 0, 0);
|
|
WriteFile(g->logfile, end.text, end.len, 0, 0);
|
|
}
|
|
}
|
|
|
|
void Log_(i32 level, String msg)
|
|
{
|
|
W32_Log(level, msg);
|
|
}
|
|
|
|
void LogF_(i32 level, String fmt, ...)
|
|
{
|
|
W32_SharedLogState *g = &W32_shared_log_state;
|
|
if (Atomic32Fetch(&g->initialized))
|
|
{
|
|
TempArena scratch = BeginScratchNoConflict();
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
{
|
|
String msg = FormatStringV(scratch.arena, fmt, args);
|
|
W32_Log(level, msg);
|
|
}
|
|
va_end(args);
|
|
EndScratch(scratch);
|
|
}
|
|
}
|
|
|
|
LogEventsArray GetLogEvents(void)
|
|
{
|
|
W32_SharedLogState *g = &W32_shared_log_state;
|
|
LogEventsArray result = ZI;
|
|
result.count = Atomic64Fetch(&g->readable_logs_count);
|
|
if (result.count > 0)
|
|
{
|
|
result.logs = g->readable_log_events;
|
|
}
|
|
return result;
|
|
}
|