move logging to base layer

This commit is contained in:
jacob 2025-11-02 19:31:49 -06:00
parent 597d069c58
commit 9fc7445e6b
26 changed files with 660 additions and 637 deletions

View File

@ -201,14 +201,14 @@ void Startup(void)
String logfile_path = CatString(temp.arena, logfile_dir, logfile_name); String logfile_path = CatString(temp.arena, logfile_dir, logfile_name);
P_MkDir(logfile_dir); P_MkDir(logfile_dir);
P_LogStartup(logfile_path); LogStartup(logfile_path);
P_LogInfoF("Start of logs"); LogInfoF("Start of logs");
EndTempArena(temp); EndTempArena(temp);
} }
P_LogInfoF("App started with args \"%F\" (%F parsed)", FmtString(args_str), FmtUint(args.count)); LogInfoF("App started with args \"%F\" (%F parsed)", FmtString(args_str), FmtUint(args.count));
for (AppArg *arg = args.first; arg; arg = arg->next) for (AppArg *arg = args.first; arg; arg = arg->next)
{ {
P_LogInfoF("Parsed arg: key = \"%F\", value = \"%F\"", FmtString(arg->key), FmtString(arg->value)); LogInfoF("Parsed arg: key = \"%F\", value = \"%F\"", FmtString(arg->key), FmtString(arg->value));
} }
#endif #endif
@ -219,19 +219,19 @@ void Startup(void)
P_WindowSettings window_settings = ZI; P_WindowSettings window_settings = ZI;
String settings_path = CatAppWritePath(temp.arena, settings_file_name); String settings_path = CatAppWritePath(temp.arena, settings_file_name);
P_LogInfoF("Looking for settings file \"%F\"", FmtString(settings_path)); LogInfoF("Looking for settings file \"%F\"", FmtString(settings_path));
if (P_IsFile(settings_path)) if (P_IsFile(settings_path))
{ {
P_LogInfoF("Settings file found"); LogInfoF("Settings file found");
P_File settings_file = P_OpenFileRead(settings_path); P_File settings_file = P_OpenFileRead(settings_path);
String file_data = P_ReadFile(temp.arena, settings_file); String file_data = P_ReadFile(temp.arena, settings_file);
P_CloseFile(settings_file); P_CloseFile(settings_file);
P_LogInfoF("Deserializing settings file data: %F", FmtString(file_data)); LogInfoF("Deserializing settings file data: %F", FmtString(file_data));
String error = ZI; String error = ZI;
P_WindowSettings *deser = SETTINGS_WindowSettingsFromString(temp.arena, file_data, &error); P_WindowSettings *deser = SETTINGS_WindowSettingsFromString(temp.arena, file_data, &error);
if (error.len > 0) if (error.len > 0)
{ {
P_LogInfoF("Failed to load settings file with error - %F", FmtString(error)); LogInfoF("Failed to load settings file with error - %F", FmtString(error));
String msg = StringF(temp.arena, String msg = StringF(temp.arena,
"Failed to loading settings file \"%F\":\n" "Failed to loading settings file \"%F\":\n"
"------------\n" "------------\n"
@ -242,12 +242,12 @@ void Startup(void)
FmtString(error)); FmtString(error));
Panic(msg); Panic(msg);
} }
P_LogInfoF("Settings file loaded successfully"); LogInfoF("Settings file loaded successfully");
window_settings = *deser; window_settings = *deser;
} }
else else
{ {
P_LogInfoF("Settings file not found, loading default"); LogInfoF("Settings file not found, loading default");
window_settings = GetDefaultAppWindowSettings(window); window_settings = GetDefaultAppWindowSettings(window);
} }
PushStringToBuff(StringFromArray(window_settings.title), Lit(WINDOW_TITLE)); PushStringToBuff(StringFromArray(window_settings.title), Lit(WINDOW_TITLE));
@ -287,13 +287,13 @@ void Startup(void)
P_WindowSettings settings = P_GetWindowSettings(window); P_WindowSettings settings = P_GetWindowSettings(window);
String str = SETTINGS_StringFromWindowSettings(temp.arena, &settings); String str = SETTINGS_StringFromWindowSettings(temp.arena, &settings);
P_LogInfoF("Serialized window settings: %F", FmtString(str)); LogInfoF("Serialized window settings: %F", FmtString(str));
P_LogInfoF("Writing settings file to path \"%F\"", FmtString(window_settings_path)); LogInfoF("Writing settings file to path \"%F\"", FmtString(window_settings_path));
P_File settings_file = P_OpenFileWrite(window_settings_path); P_File settings_file = P_OpenFileWrite(window_settings_path);
P_WriteFile(settings_file, str); P_WriteFile(settings_file, str);
P_CloseFile(settings_file); P_CloseFile(settings_file);
P_LogInfoF("Finished writing settings file"); LogInfoF("Finished writing settings file");
EndTempArena(temp); EndTempArena(temp);
} }
@ -303,6 +303,6 @@ void Startup(void)
P_ReleaseWindow(window); P_ReleaseWindow(window);
#endif #endif
//P_LogInfoF("Program exited normally"); //LogInfoF("Program exited normally");
EndScratch(scratch); EndScratch(scratch);
} }

View File

@ -129,7 +129,7 @@ AC_Asset *AC_TouchCache(String key, u64 hash, b32 *is_first_touch)
AC_CloseStore(&store); AC_CloseStore(&store);
} }
/* Initialize asset data */ /* Initialize asset data */
P_LogInfoF("Inserting asset cache entry for \"%F\"", FmtString(key)); LogInfoF("Inserting asset cache entry for \"%F\"", FmtString(key));
*asset = (AC_Asset) { *asset = (AC_Asset) {
.status = ASSET_STATUS_UNINITIALIZED, .status = ASSET_STATUS_UNINITIALIZED,
.hash = hash, .hash = hash,

35
src/base/base_file.h Normal file
View File

@ -0,0 +1,35 @@
////////////////////////////////////////////////////////////
//~ File types
Enum(OS_FileFlag)
{
OS_FileFlag_None = 0,
OS_FileFlag_Read = (1 << 0),
OS_FileFlag_Write = (1 << 1),
OS_FileFlag_Create = (1 << 2),
};
Struct(OS_File)
{
u64 handle;
};
////////////////////////////////////////////////////////////
//~ @hookdecl File system operations
OS_File OS_OpenFile(String path, OS_FileFlag flags, i64 timeout_ns);
void OS_CloseFile(OS_File file);
String OS_ReadEntireFile(Arena *arena, OS_File file);
void OS_ClearWriteFile(OS_File file, String data);
void OS_DirContentsFromFullPath(Arena *arena, StringList *list, String path);
String OS_GetFullPath(Arena *arena, String path);
u64 OS_LastWriteTimestampFromPath(String path);
////////////////////////////////////////////////////////////
//~ @hookdecl Directory helpers
b32 OS_FileOrDirExists(String path);
b32 OS_FileExists(String path);
b32 OS_DirExists(String path);
void OS_Mkdir(String path);
void OS_Rm(String path);

View File

@ -11,6 +11,8 @@
# include "base_futex.h" # include "base_futex.h"
# include "base_snc.h" # include "base_snc.h"
# include "base_job.h" # include "base_job.h"
# include "base_time.h"
# include "base_log.h"
# include "base_uid.h" # include "base_uid.h"
# include "base_string.h" # include "base_string.h"
# include "base_uni.h" # include "base_uni.h"

145
src/base/base_log.h Normal file
View File

@ -0,0 +1,145 @@
////////////////////////////////////////////////////////////
//~ Log event types
Struct(LogEvent)
{
u64 id;
u64 level_id;
DateTime datetime;
i64 time_ns;
String msg;
i32 level;
i32 thread_id;
i32 fiber_id;
};
Struct(LogEventsArray)
{
u64 count;
LogEvent *logs;
};
////////////////////////////////////////////////////////////
//~ Logging levels
#define LogLevel(l) (l <= LogLevel_CompTime)
/* Log level configuration */
#ifndef LogLevel_CompTime
# if RtcIsEnabled || ProfilingIsEnabled
# define LogLevel_CompTime LogLevel_Debug
# else
# define LogLevel_CompTime LogLevel_Info
# endif
#endif
#define LogLevel_None -1
#define LogLevel_Critical 0
#define LogLevel_Error 1
#define LogLevel_Warning 2
#define LogLevel_Success 3
#define LogLevel_Info 4
#define LogLevel_Debug 5
#define LogLevel_Count 6
////////////////////////////////////////////////////////////
//~ Log level types
Struct(LogLevelSettings)
{
String shorthand;
};
Global Readonly LogLevelSettings log_settings[LogLevel_Count] = {
[LogLevel_Critical] = {
LitNoCast("CRITICAL"),
},
[LogLevel_Error] = {
LitNoCast("ERROR"),
},
[LogLevel_Warning] = {
LitNoCast("WARNING"),
},
[LogLevel_Success] = {
LitNoCast("SUCCESS"),
},
[LogLevel_Info] = {
LitNoCast("INFO"),
},
[LogLevel_Debug] = {
LitNoCast("DEBUG"),
}
};
////////////////////////////////////////////////////////////
//~ Compile-time logging macros
#if LogLevel(LogLevel_Critical)
# define LogCritical(msg) Log_(LogLevel_Critical, msg)
# define LogCriticalF(fmt_lit, ...) LogF_(LogLevel_Critical, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
#else
# define LogCritical(msg)
# define LogCriticalF(...)
#endif
#if LogLevel(LogLevel_Error)
# define LogError(msg) Log_(LogLevel_Error, msg)
# define LogErrorF(fmt_lit, ...) LogF_(LogLevel_Error, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
#else
# define LogError(msg)
# define LogErrorF(...)
#endif
#if LogLevel(LogLevel_Warning)
# define LogWarning(msg) Log_(LogLevel_Warning, msg)
# define LogWarningF(fmt_lit, ...) LogF_(LogLevel_Warning, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
#else
# define LogWarning(msg)
# define LogWarningF(...)
#endif
#if LogLevel(LogLevel_Success)
# define LogSuccess(msg) Log_(LogLevel_Success, msg)
# define LogSuccessF(fmt_lit, ...) LogF_(LogLevel_Success, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
#else
# define LogSuccess(msg)
# define LogSuccessF(...)
#endif
#if LogLevel(LogLevel_Info)
# define LogInfo(msg) Log_(LogLevel_Info, msg)
# define LogInfoF(fmt_lit, ...) LogF_(LogLevel_Info, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
#else
# define LogInfo(msg)
# define LogInfoF(...)
#endif
#if LogLevel(LogLevel_Debug)
# define LogDebug(msg) Log_(LogLevel_Debug, msg)
# define LogDebugF(fmt_lit, ...) LogF_(LogLevel_Debug, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
#else
# define LogDebug(msg)
# define LogDebugF(...)
#endif
////////////////////////////////////////////////////////////
//~ @hookdecl Init hooks
void InitLogSystem(String logfile_path);
////////////////////////////////////////////////////////////
//~ @hookdecl Log hooks
/* NOTE: Calling these functions rather than using the logging macros may result in logs that are compiled regardless of log level. */
void LogPanic(String msg);
void LogF_(i32 level, String fmt, ...);
LogEventsArray GetLogEvents(void);

19
src/base/base_time.h Normal file
View File

@ -0,0 +1,19 @@
////////////////////////////////////////////////////////////
//~ Datetime types
Struct(DateTime)
{
u32 year;
u32 month;
u32 day_of_week;
u32 day;
u32 hour;
u32 minute;
u32 second;
u32 milliseconds;
};
////////////////////////////////////////////////////////////
//~ @hookdecl DateTime hooks
DateTime LocalDateTime(void);

View File

@ -63,6 +63,7 @@ void Echo(String msg)
b32 Panic(String msg) b32 Panic(String msg)
{ {
LogPanic(msg);
char msg_cstr[4096]; char msg_cstr[4096];
CstrFromStringToBuff(StringFromArray(msg_cstr), msg); CstrFromStringToBuff(StringFromArray(msg_cstr), msg);
{ {
@ -110,7 +111,7 @@ void TrueRand(String buffer)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Swap hooks //~ @hookdef Swap hooks
b32 IsSwappedIn(void) b32 IsSwappedIn(void)
{ {
@ -335,6 +336,10 @@ i32 W32_Main(void)
/* Init futex system */ /* Init futex system */
InitFutexSystem(); InitFutexSystem();
/* Init log system */
/* FIXME: Remove hardcoded log path */
InitLogSystem(Lit("log.log"));
/* Init resources */ /* Init resources */
{ {
W32_FindEmbeddedDataCtx ctx = ZI; W32_FindEmbeddedDataCtx ctx = ZI;

View File

@ -0,0 +1,163 @@
////////////////////////////////////////////////////////////
//~ @hookdef File system hooks
OS_File OS_OpenFile(String path, OS_FileFlag flags, i64 timeout_ns)
{
TempArena scratch = BeginScratchNoConflict();
OS_File result = ZI;
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
u32 share_mode = FILE_SHARE_READ;
u32 create_mode = OPEN_EXISTING;
u32 access_flags = 0;
if (flags & OS_FileFlag_Read) access_flags |= GENERIC_READ;
if (flags & OS_FileFlag_Write) access_flags |= GENERIC_WRITE;
if (flags & OS_FileFlag_Create) create_mode = OPEN_ALWAYS;
i32 timeout_ms = timeout_ns / 1000000;
i32 elapsed_ms = 0;
i32 delay_ms = 1;
HANDLE handle = INVALID_HANDLE_VALUE;
for (;;)
{
handle = CreateFileW(path_wstr, access_flags, share_mode, 0, create_mode, FILE_ATTRIBUTE_NORMAL, 0);
if (handle == INVALID_HANDLE_VALUE && elapsed_ms < timeout_ms && GetLastError() == ERROR_SHARING_VIOLATION)
{
Sleep(delay_ms);
elapsed_ms += delay_ms;
delay_ms = MinI32(delay_ms * 2, 1024);
}
else
{
break;
}
}
EndScratch(scratch);
result.handle = (u64)handle;
return result;
}
void OS_CloseFile(OS_File file)
{
HANDLE handle = (HANDLE)file.handle;
CloseHandle(handle);
}
String OS_ReadEntireFile(Arena *arena, OS_File file)
{
String result = ZI;
HANDLE handle = (HANDLE)file.handle;
u32 chunk_size = Kibi(64);
result.text = PushDry(arena, u8);
for (;;)
{
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
u32 chunk_bytes_read = 0;
ReadFile(handle, chunk, chunk_size, &chunk_bytes_read, 0);
result.len += chunk_bytes_read;
if (chunk_bytes_read < chunk_size)
{
PopStructsNoCopy(arena, u8, chunk_size - chunk_bytes_read);
break;
}
}
return result;
}
void OS_ClearWriteFile(OS_File file, String data)
{
HANDLE handle = (HANDLE)file.handle;
SetFilePointer(handle, 0, 0, FILE_BEGIN);
SetEndOfFile(handle);
WriteFile(handle, data.text, data.len, 0, 0);
}
void OS_DirContentsFromFullPath(Arena *arena, StringList *list, String path)
{
TempArena scratch = BeginScratch(arena);
WIN32_FIND_DATAW find_data = ZI;
String filter = StringF(scratch.arena, "%F\\*", FmtString(path));
wchar_t *filter_wstr = WstrFromString(scratch.arena, filter);
HANDLE find_handle = FindFirstFileExW(filter_wstr, FindExInfoStandard, &find_data, FindExSearchNameMatch, 0, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
b32 found = find_handle && find_handle != INVALID_HANDLE_VALUE;
while (found)
{
String file_name = StringFromWstrNoLimit(arena, find_data.cFileName);
if (!EqString(file_name, Lit(".")) && !EqString(file_name, Lit("..")))
{
PushStringToList(arena, list, file_name);
}
found = FindNextFileW(find_handle, &find_data);
}
EndScratch(scratch);
}
String OS_GetFullPath(Arena *arena, String path)
{
TempArena scratch = BeginScratch(arena);
wchar_t *rel_path_wstr = WstrFromString(scratch.arena, path);
wchar_t full_path_wstr_buff[4096];
GetFullPathNameW(rel_path_wstr, countof(full_path_wstr_buff), full_path_wstr_buff, 0);
String res = StringFromWstr(arena, full_path_wstr_buff, countof(full_path_wstr_buff));
EndScratch(scratch);
return res;
}
u64 OS_LastWriteTimestampFromPath(String path)
{
TempArena scratch = BeginScratchNoConflict();
u64 result = 0;
WIN32_FILE_ATTRIBUTE_DATA a = ZI;
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
if (GetFileAttributesExW(path_wstr, GetFileExInfoStandard, &a))
{
result = ((ULONGLONG)a.ftLastWriteTime.dwHighDateTime << 32) |
(ULONGLONG)a.ftLastWriteTime.dwLowDateTime;
}
EndScratch(scratch);
return result;
}
////////////////////////////////////////////////////////////
//~ @hookdef Directory helper hooks
b32 OS_FileOrDirExists(String path)
{
TempArena scratch = BeginScratchNoConflict();
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
DWORD attributes = GetFileAttributesW(path_wstr);
EndScratch(scratch);
return attributes != INVALID_FILE_ATTRIBUTES;
}
b32 OS_FileExists(String path)
{
TempArena scratch = BeginScratchNoConflict();
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
DWORD attributes = GetFileAttributesW(path_wstr);
EndScratch(scratch);
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
}
b32 OS_DirExists(String path)
{
TempArena scratch = BeginScratchNoConflict();
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
DWORD attributes = GetFileAttributesW(path_wstr);
EndScratch(scratch);
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
}
void OS_Mkdir(String path)
{
TempArena scratch = BeginScratchNoConflict();
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
CreateDirectoryW(path_wstr, 0);
EndScratch(scratch);
}
void OS_Rm(String path)
{
TempArena scratch = BeginScratchNoConflict();
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
DeleteFile(path_wstr);
EndScratch(scratch);
}

View File

@ -1,7 +1,10 @@
//- Api //- Api
#include "base_win32.h" #include "base_win32.h"
#include "base_win32_job.h" #include "base_win32_job.h"
#include "base_win32_log.h"
//- Impl //- Impl
#include "base_win32.c" #include "base_win32.c"
#include "base_win32_job.c" #include "base_win32_job.c"
#include "base_win32_time.c"
#include "base_win32_log.c"

View File

@ -47,7 +47,7 @@ DWORD WINAPI W32_Win32ThreadProc(LPVOID vt)
/* Set thread name */ /* Set thread name */
SetThreadDescription(GetCurrentThread(), thread_name_desc_wstr); SetThreadDescription(GetCurrentThread(), thread_name_desc_wstr);
//P_LogInfoF("New thread \"%F\" created with ID %F", FmtString(StringFromCstrNoLimit(t->thread_name_cstr)), FmtUint(ThreadId())); //LogInfoF("New thread \"%F\" created with ID %F", FmtString(StringFromCstrNoLimit(t->thread_name_cstr)), FmtUint(ThreadId()));
/* Enter thread entry point */ /* Enter thread entry point */
t->entry_point(t->thread_udata); t->entry_point(t->thread_udata);
@ -65,7 +65,7 @@ W32_Thread *W32_StartThread(W32_ThreadFunc *entry_point, void *thread_udata, Str
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
Arena *perm = PermArena(); Arena *perm = PermArena();
Assert(entry_point != 0); Assert(entry_point != 0);
//P_LogInfoF("Creating thread \"%F\"", FmtString(thread_name)); //LogInfoF("Creating thread \"%F\"", FmtString(thread_name));
W32_Thread *t = PushStruct(perm, W32_Thread); W32_Thread *t = PushStruct(perm, W32_Thread);
t->thread_name = PushString(perm, thread_name); t->thread_name = PushString(perm, thread_name);

View File

@ -0,0 +1,151 @@
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 = PushDry(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);
/* FIXME: Log actual thread & fiber id */
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, 5),
/* 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 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;
}

View File

@ -0,0 +1,21 @@
////////////////////////////////////////////////////////////
//~ State types
Struct(W32_SharedLogState)
{
HANDLE logfile;
Atomic32 initialized;
TicketMutex logs_tm;
Arena *log_msgs_arena;
Arena *logs_arena;
u64 logs_count;
u64 log_level_counts[LogLevel_Count];
LogEvent *readable_log_events;
Atomic64 readable_logs_count;
} extern W32_shared_log_state;
////////////////////////////////////////////////////////////
//~ Log
void W32_Log(i32 level, String msg);

View File

@ -0,0 +1,20 @@
////////////////////////////////////////////////////////////
//~ @hookdef DateTime hooks
DateTime LocalDateTime(void)
{
DateTime result = ZI;
{
SYSTEMTIME lt;
GetLocalTime(&lt);
result.year = lt.wYear;
result.month = lt.wMonth;
result.day_of_week = lt.wDayOfWeek;
result.day = lt.wDay;
result.hour = lt.wHour;
result.minute = lt.wMinute;
result.second = lt.wSecond;
result.milliseconds = lt.wMilliseconds;
}
return result;
}

View File

@ -30,7 +30,7 @@ JobDef(F_Load, sig, _)
f32 point_size = sig->point_size; f32 point_size = sig->point_size;
AC_Asset *asset = sig->asset; AC_Asset *asset = sig->asset;
P_LogInfoF("Loading font \"%F\" (point size %F)", FmtString(name), FmtFloat((f64)point_size)); LogInfoF("Loading font \"%F\" (point size %F)", FmtString(name), FmtFloat((f64)point_size));
i64 start_ns = TimeNs(); i64 start_ns = TimeNs();
Assert(StringEndsWith(name, Lit(".ttf"))); Assert(StringEndsWith(name, Lit(".ttf")));
@ -153,7 +153,7 @@ JobDef(F_Load, sig, _)
font->lookup[codepoint] = decoded.cache_indices[i]; font->lookup[codepoint] = decoded.cache_indices[i];
} }
P_LogSuccessF("Loaded font \"%F\" (point size %F) in %F seconds", FmtString(name), FmtFloat((f64)point_size), FmtFloat(SecondsFromNs(TimeNs() - start_ns))); LogSuccessF("Loaded font \"%F\" (point size %F) in %F seconds", FmtString(name), FmtFloat((f64)point_size), FmtFloat(SecondsFromNs(TimeNs() - start_ns)));
AC_MarkReady(asset, font); AC_MarkReady(asset, font);
EndScratch(scratch); EndScratch(scratch);

View File

@ -632,7 +632,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host)
/* A foreign host is trying to connect to us */ /* A foreign host is trying to connect to us */
if (!channel->valid) if (!channel->valid)
{ {
P_LogInfoF("Host received conection attempt from %F", FmtString(P_StringFromAddress(scratch.arena, address))); LogInfoF("Host received conection attempt from %F", FmtString(P_StringFromAddress(scratch.arena, address)));
/* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */ /* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */
channel = N_AcquireChannel(host, address); channel = N_AcquireChannel(host, address);
} }
@ -646,7 +646,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host)
/* We successfully connected to a foreign host and they are ready to receive messages */ /* We successfully connected to a foreign host and they are ready to receive messages */
if (channel->valid && !channel->connected) if (channel->valid && !channel->connected)
{ {
P_LogInfoF("Host received connection from %F", FmtString(P_StringFromAddress(scratch.arena, address))); LogInfoF("Host received connection from %F", FmtString(P_StringFromAddress(scratch.arena, address)));
N_Event *event = N_PushEvent(arena, &events); N_Event *event = N_PushEvent(arena, &events);
event->kind = N_EventKind_ChannelOpened; event->kind = N_EventKind_ChannelOpened;
event->channel_id = channel->id; event->channel_id = channel->id;
@ -659,7 +659,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host)
/* A foreign host disconnected from us */ /* A foreign host disconnected from us */
if (channel->valid) if (channel->valid)
{ {
P_LogInfoF("Host received disconnection from %F", FmtString(P_StringFromAddress(scratch.arena, address))); LogInfoF("Host received disconnection from %F", FmtString(P_StringFromAddress(scratch.arena, address)));
N_Event *event = N_PushEvent(arena, &events); N_Event *event = N_PushEvent(arena, &events);
event->kind = N_EventKind_ChannelClosed; event->kind = N_EventKind_ChannelClosed;
event->channel_id = channel->id; event->channel_id = channel->id;

View File

@ -5,21 +5,6 @@ Struct(P_Watch);
Struct(P_Window); Struct(P_Window);
Struct(P_Sock); Struct(P_Sock);
////////////////////////////////////////////////////////////
//~ Time types
Struct(P_DateTime)
{
u32 year;
u32 month;
u32 day_of_week;
u32 day;
u32 hour;
u32 minute;
u32 second;
u32 milliseconds;
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ File system types //~ File system types
@ -31,9 +16,9 @@ Struct(P_File)
Struct(P_FileTime) Struct(P_FileTime)
{ {
P_DateTime created; DateTime created;
P_DateTime accessed; DateTime accessed;
P_DateTime modified; DateTime modified;
}; };
Struct(P_FileMap) Struct(P_FileMap)
@ -278,11 +263,6 @@ Enum(P_MessageBoxKind)
void P_Startup(void); void P_Startup(void);
////////////////////////////////////////////////////////////
//~ @hookdecl Time helper hooks
P_DateTime P_LocalTime(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ @hookdecl File system hooks //~ @hookdecl File system hooks

View File

@ -2,14 +2,9 @@
//- Api //- Api
@IncludeC platform.h @IncludeC platform.h
@IncludeC platform_log.h
//- Impl
@IncludeC platform_log.c
//- Win32 impl //- Win32 impl
@DefaultWindowsImpl platform_win32 @DefaultWindowsImpl platform_win32
//- Startup //- Startup
@Startup P_Startup @Startup P_Startup
@Startup P_StartupLog

View File

@ -1,232 +0,0 @@
P_SharedLogState P_shared_log_state = ZI;
////////////////////////////////////////////////////////////
//~ Startup
void P_StartupLog(void)
{
__prof;
/* FIXME: Remove hardcode */
String logfile_path = Lit("log.log");
P_SharedLogState *ctx = &P_shared_log_state;
ctx->callbacks_arena = AcquireArena(Mebi(8));
if (logfile_path.len > 0)
{
/* Create / wipe log file */
P_CloseFile(P_OpenFileWrite(logfile_path));
/* Keep log file open for appending */
if (P_IsFile(logfile_path))
{
ctx->file = P_OpenFileAppend(logfile_path);
ctx->file_valid = 1;
}
}
Atomic32Set(&ctx->initialized, 1);
}
////////////////////////////////////////////////////////////
//~ Callback registration
void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level)
{
P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; }
Lock lock = LockE(&ctx->callbacks_mutex);
{
LogEventCallback *callback = PushStruct(ctx->callbacks_arena, LogEventCallback);
callback->func = func;
callback->level = level;
if (ctx->last_callback)
{
ctx->last_callback->next = callback;
}
else
{
ctx->first_callback = callback;
}
ctx->last_callback = callback;
}
Unlock(&lock);
}
////////////////////////////////////////////////////////////
//~ Append
void P_LogAppend_(String msg)
{
__prof;
P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; }
if (ctx->file_valid)
{
TempArena scratch = BeginScratchNoConflict();
String msg_line = CatString(scratch.arena, msg, Lit("\n"));
P_WriteFile(ctx->file, msg_line);
EndScratch(scratch);
}
}
////////////////////////////////////////////////////////////
//~ Panic
/* Panic log function is separate to enforce zero side effects other than
* writing to log file. */
void P_LogPanic_(String msg)
{
P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; }
if (ctx->file_valid)
{
P_WriteFile(ctx->file, Lit("******** PANICKING ********\n"));
P_WriteFile(ctx->file, msg);
P_WriteFile(ctx->file, Lit("\n***************************\n"));
}
}
////////////////////////////////////////////////////////////
//~ Logfv
#if P_IncludeLogSourceLocation
void P_LogFV_(i32 level, String file, u32 line, String fmt, va_list args)
#else
void P_LogFV_(i32 level, String fmt, va_list args)
#endif
{
P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; }
TempArena scratch = BeginScratchNoConflict();
String msg = FormatStringV(scratch.arena, fmt, args);
#if P_IncludeLogSourceLocation
P_Log_(level, file, line, msg);
#else
P_Log_(level, msg);
#endif
EndScratch(scratch);
}
////////////////////////////////////////////////////////////
//~ Logf
#if P_IncludeLogSourceLocation
void P_LogF_(i32 level, String file, u32 line, String fmt, ...)
#else
void P_LogF_(i32 level, String fmt, ...)
#endif
{
P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; }
va_list args;
va_start(args, fmt);
#if P_IncludeLogSourceLocation
P_LogFV_(level, file, line, fmt, args);
#else
P_LogFV_(level, fmt, args);
#endif
va_end(args);
}
////////////////////////////////////////////////////////////
//~ Log
#if P_IncludeLogSourceLocation
void P_Log_(i32 level, String file, u32 line, String msg)
#else
void P_Log_(i32 level, String msg)
#endif
{
__prof;
P_SharedLogState *ctx = &P_shared_log_state;
if (!Atomic32Fetch(&ctx->initialized)) { return; }
TempArena scratch = BeginScratchNoConflict();
P_LogLevelSettings settings = P_log_settings[level];
if (level < 0 || level >= P_LogLevel_Count)
{
Panic(Lit("Invalid log level"));
}
/* FIXME: Log actual thread & fiber id */
// u32 tid = ThreadId();
u32 tid = 0;
//- Format message
P_DateTime datetime = P_LocalTime();
i64 time_ns = TimeNs();
String shorthand = settings.shorthand;
#if P_IncludeLogSourceLocation
String msg_formatted = StringF(
scratch.arena,
"[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F",
/* Time */
FmtUintZ(datetime.hour, 2),
FmtUintZ(datetime.minute, 2),
FmtUintZ(datetime.second, 2),
FmtUintZ(datetime.milliseconds, 3),
/* TID */
FmtUintZ(tid, 5),
/* Level */
FmtString(shorthand),
/* Source location */
FmtString(file),
FmtSint(line),
/* Message */
FmtString(msg)
);
#else
String msg_formatted = StringF(
scratch.arena,
"[%F:%F:%F.%F] |%F| [%F] %F",
/* Time */
FmtUintZ(datetime.hour, 2),
FmtUintZ(datetime.minute, 2),
FmtUintZ(datetime.second, 2),
FmtUintZ(datetime.milliseconds, 3),
/* TID */
FmtUintZ(tid, 5),
/* Level */
FmtString(shorthand),
/* Message */
FmtString(msg)
);
#endif
__profmsg((char *)msg.text, msg.len, settings.color);
P_LogAppend_(msg_formatted);
//- Run callbacks
P_LogEvent event = ZI;
event.level = level;
event.msg = msg;
event.datetime = datetime;
event.time_ns = time_ns;
#if P_IncludeLogSourceLocation
event.file = file;
event.line = line;
#endif
{
Lock lock = LockS(&ctx->callbacks_mutex);
for (LogEventCallback *callback = ctx->first_callback; callback; callback = callback->next)
{
if (level <= callback->level)
{
__profn("Run log callback");
callback->func(event);
}
}
Unlock(&lock);
}
EndScratch(scratch);
}

View File

@ -1,230 +0,0 @@
////////////////////////////////////////////////////////////
//~ Log event types
//- Event
Struct(P_LogEvent)
{
/* Msg lifetime is only as long as callback duration */
String msg;
i32 level;
P_DateTime datetime;
i64 time_ns;
/* These will be zeroed if P_IncludeLogSourceLocation is disabled */
String file;
i32 line;
};
//- Callback
#define P_LogEventCallbackFuncDef(name, log_event_arg) void name(P_LogEvent log_event_arg)
typedef P_LogEventCallbackFuncDef(P_LogEventCallbackFunc, log_event);
Struct(LogEventCallback)
{
P_LogEventCallbackFunc *func;
LogEventCallback *next;
i32 level;
};
////////////////////////////////////////////////////////////
//~ Logging levels
#define P_LogLevel(l) (l <= P_LogLevel_CompTime)
/* Log level configuration */
#ifndef P_LogLevel_CompTime
# if RtcIsEnabled || ProfilingIsEnabled
# define P_LogLevel_CompTime P_LogLevel_Debug
# else
# define P_LogLevel_CompTime P_LogLevel_Info
# endif
#endif
/* Source location configuration */
#ifndef P_IncludeLogSourceLocation
# define P_IncludeLogSourceLocation (DebinfoEnabled)
#endif
#define P_LogLevel_None -1
#define P_LogLevel_Critical 0
#define P_LogLevel_Error 1
#define P_LogLevel_Warning 2
#define P_LogLevel_Success 3
#define P_LogLevel_Info 4
#define P_LogLevel_Debug 5
#define P_LogLevel_Count 6
////////////////////////////////////////////////////////////
//~ State types
Struct(P_SharedLogState)
{
Atomic32 initialized;
Mutex callbacks_mutex;
Arena *callbacks_arena;
LogEventCallback *first_callback;
LogEventCallback *last_callback;
P_File file;
b32 file_valid;
} P_shared_log_state;
////////////////////////////////////////////////////////////
//~ Log level types
Struct(P_LogLevelSettings)
{
String shorthand;
u32 color;
};
Global Readonly P_LogLevelSettings P_log_settings[P_LogLevel_Count] = {
[P_LogLevel_Critical] = {
LitNoCast("CRITICAL"),
Color_Purple
},
[P_LogLevel_Error] = {
LitNoCast("ERROR"),
Color_Red
},
[P_LogLevel_Warning] = {
LitNoCast("WARNING"),
Color_Yellow
},
[P_LogLevel_Success] = {
LitNoCast("SUCCESS"),
Color_Green
},
[P_LogLevel_Info] = {
LitNoCast("INFO"),
Color_White
},
[P_LogLevel_Debug] = {
LitNoCast("DEBUG"),
Color_Blue
}
};
////////////////////////////////////////////////////////////
//~ Startup
void P_StartupLog(void);
////////////////////////////////////////////////////////////
//~ Logging macros
#if P_LogLevel(P_LogLevel_Critical)
# if P_IncludeLogSourceLocation
# define P_LogCritical(msg) P_Log_(P_LogLevel_Critical, Lit(__FILE__), __LINE__, msg)
# define P_LogCriticalF(fmt_lit, ...) P_LogF_(P_LogLevel_Critical, Lit(__FILE__), __LINE__, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# else
# define P_LogCritical(msg) P_Log_(P_LogLevel_Critical, msg)
# define P_LogCriticalF(fmt_lit, ...) P_LogF_(P_LogLevel_Critical, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# endif
#else
# define P_LogCritical(msg)
# define P_LogCriticalF(...)
#endif
#if P_LogLevel(P_LogLevel_Error)
# if P_IncludeLogSourceLocation
# define P_LogError(msg) P_Log_(P_LogLevel_Error, Lit(__FILE__), __LINE__, msg)
# define P_LogErrorF(fmt_lit, ...) P_LogF_(P_LogLevel_Error, Lit(__FILE__), __LINE__, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# else
# define P_LogError(msg) P_Log_(P_LogLevel_Error, msg)
# define P_LogErrorF(fmt_lit, ...) P_LogF_(P_LogLevel_Error, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# endif
#else
# define P_LogError(msg)
# define P_LogErrorF(...)
#endif
#if P_LogLevel(P_LogLevel_Warning)
# if P_IncludeLogSourceLocation
# define P_LogWarning(msg) P_Log_(P_LogLevel_Warning, Lit(__FILE__), __LINE__, msg)
# define P_LogWarningF(fmt_lit, ...) P_LogF_(P_LogLevel_Warning, Lit(__FILE__), __LINE__, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# else
# define P_LogWarning(msg) P_Log_(P_LogLevel_Warning, msg)
# define P_LogWarningF(fmt_lit, ...) P_LogF_(P_LogLevel_Warning, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# endif
#else
# define P_LogWarning(msg)
# define P_LogWarningF(...)
#endif
#if P_LogLevel(P_LogLevel_Success)
# if P_IncludeLogSourceLocation
# define P_LogSuccess(msg) P_Log_(P_LogLevel_Success, Lit(__FILE__), __LINE__, msg)
# define P_LogSuccessF(fmt_lit, ...) P_LogF_(P_LogLevel_Success, Lit(__FILE__), __LINE__, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# else
# define P_LogSuccess(msg) P_Log_(P_LogLevel_Success, msg)
# define P_LogSuccessF(fmt_lit, ...) P_LogF_(P_LogLevel_Success, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# endif
#else
# define P_LogSuccess(msg)
# define P_LogSuccessF(...)
#endif
#if P_LogLevel(P_LogLevel_Info)
# if P_IncludeLogSourceLocation
# define P_LogInfo(msg) P_Log_(P_LogLevel_Info, Lit(__FILE__), __LINE__, msg)
# define P_LogInfoF(fmt_lit, ...) P_LogF_(P_LogLevel_Info, Lit(__FILE__), __LINE__, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# else
# define P_LogInfo(msg) P_Log_(P_LogLevel_Info, msg)
# define P_LogInfoF(fmt_lit, ...) P_LogF_(P_LogLevel_Info, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# endif
#else
# define P_LogInfo(msg)
# define P_LogInfoF(...)
#endif
#if P_LogLevel(P_LogLevel_Debug)
# if P_IncludeLogSourceLocation
# define P_LogDebug(msg) P_Log_(P_LogLevel_Debug, Lit(__FILE__), __LINE__, msg)
# define P_LogDebugF(fmt_lit, ...) P_LogF_(P_LogLevel_Debug, Lit(__FILE__), __LINE__, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# else
# define P_LogDebug(msg) P_Log_(P_LogLevel_Debug, msg)
# define P_LogDebugF(fmt_lit, ...) P_LogF_(P_LogLevel_Debug, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
# endif
#else
# define P_LogDebug(msg)
# define P_LogDebugF(...)
#endif
////////////////////////////////////////////////////////////
//~ Callback registration
void P_RegisterLogCallback(P_LogEventCallbackFunc *func, i32 level);
////////////////////////////////////////////////////////////
//~ Raw log operations
/* NOTE: Calling these functions rather than using the logging macros may result in logs that are compiled regardless of log level. */
void P_LogAppend_(String msg);
void P_LogPanic_(String msg);
#if P_IncludeLogSourceLocation
void P_LogFV_(i32 level, String file, u32 line, String fmt, va_list args);
#else
void P_LogFV_(i32 level, String fmt, va_list args);
#endif
#if P_IncludeLogSourceLocation
void P_LogF_(i32 level, String file, u32 line, String fmt, ...);
#else
void P_LogF_(i32 level, String fmt, ...);
#endif
#if P_IncludeLogSourceLocation
void P_Log_(i32 level, String file, u32 line, String msg);
#else
void P_Log_(i32 level, String msg);
#endif

View File

@ -22,18 +22,18 @@ void P_Startup(void)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Win32 time //~ Win32 time
P_DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st) DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st)
{ {
return (P_DateTime) return (DateTime)
{ {
.year = st.wYear, .year = st.wYear,
.month = st.wMonth, .month = st.wMonth,
.day_of_week = st.wDayOfWeek, .day_of_week = st.wDayOfWeek,
.day = st.wDay, .day = st.wDay,
.hour = st.wHour, .hour = st.wHour,
.minute = st.wMinute, .minute = st.wMinute,
.second = st.wSecond, .second = st.wSecond,
.milliseconds = st.wMilliseconds .milliseconds = st.wMilliseconds
}; };
} }
@ -219,16 +219,6 @@ JobDef(P_W32_StartTimerSync, _, __)
} }
} }
////////////////////////////////////////////////////////////
//~ @hookdef Time hooks
P_DateTime P_LocalTime(void)
{
SYSTEMTIME lt;
GetLocalTime(&lt);
return P_W32_DateTimeFromWin32SystemTime(lt);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ @hookdef File system hooks //~ @hookdef File system hooks
@ -513,8 +503,8 @@ P_FileTime P_GetFileTime(P_File file)
return (P_FileTime) return (P_FileTime)
{ {
.created = P_W32_DateTimeFromWin32SystemTime(st_created), .created = P_W32_DateTimeFromWin32SystemTime(st_created),
.accessed = P_W32_DateTimeFromWin32SystemTime(st_accessed), .accessed = P_W32_DateTimeFromWin32SystemTime(st_accessed),
.modified = P_W32_DateTimeFromWin32SystemTime(st_modified) .modified = P_W32_DateTimeFromWin32SystemTime(st_modified)
}; };
} }
else else
@ -942,7 +932,7 @@ void P_MessageBox(P_MessageBoxKind kind, String message)
} break; } break;
} }
P_LogDebugF("Showing message box kind %F with text \"%F\"", FmtSint(kind), FmtString(message)); LogDebugF("Showing message box kind %F with text \"%F\"", FmtSint(kind), FmtString(message));
MessageBoxExW(0, message_wstr, title, mbox_type, 0); MessageBoxExW(0, message_wstr, title, mbox_type, 0);
EndScratch(scratch); EndScratch(scratch);

View File

@ -86,7 +86,7 @@ Struct(P_W32_SharedState)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Time operations //~ Time operations
P_DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st); DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ File system operations //~ File system operations

View File

@ -53,10 +53,6 @@ void PP_StartupUser(void)
EndScratch(scratch); EndScratch(scratch);
} }
g->console_logs_arena = AcquireArena(Gibi(64));
//P_RegisterLogCallback(PP_ConsoleLogCallback, P_LogLevel_Success);
P_RegisterLogCallback(PP_ConsoleLogCallback, P_LogLevel_Debug);
/* Create job pools */ /* Create job pools */
JobPoolId user_pool = InitJobPool(1, Lit("User"), JobPoolPriority_Graphics); JobPoolId user_pool = InitJobPool(1, Lit("User"), JobPoolPriority_Graphics);
JobPoolId sim_pool = InitJobPool(1, Lit("Simulation"), JobPoolPriority_Simulation); JobPoolId sim_pool = InitJobPool(1, Lit("Simulation"), JobPoolPriority_Simulation);
@ -106,7 +102,7 @@ void PP_PushGameUiStyle(void)
// UI_Push(FontSize, 24); // UI_Push(FontSize, 24);
// UI_Push(Font, ResourceKeyFromStore(&PP_Resources, Lit("font/roboto-med.ttf"))); // UI_Push(Font, ResourceKeyFromStore(&PP_Resources, Lit("font/roboto-med.ttf")));
// UI_Push(Font, ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf"))); UI_Push(Font, ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf")));
UI_Push(FontSize, 12); UI_Push(FontSize, 12);
UI_Push(Rounding, 0); UI_Push(Rounding, 0);
@ -298,37 +294,6 @@ String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Console //~ Console
//- Console log callback
P_LogEventCallbackFuncDef(PP_ConsoleLogCallback, log)
{
__prof;
PP_SharedUserState *g = &PP_shared_user_state;
Lock lock = LockE(&g->console_logs_mutex);
{
PP_ConsoleLog *clog = PushStruct(g->console_logs_arena, PP_ConsoleLog);
clog->level = log.level;
clog->msg = PushString(g->console_logs_arena, log.msg);
clog->datetime = log.datetime;
clog->time_ns = log.time_ns;
if (g->last_console_log)
{
g->last_console_log->next = clog;
clog->prev = g->last_console_log;
/* Alternating color index between logs of same level */
i32 *color_index = &g->console_log_color_indices[log.level];
clog->color_index = *color_index;
*color_index = 1 - *color_index;
}
else
{
g->first_console_log = clog;
}
g->last_console_log = clog;
}
Unlock(&lock);
}
//- Draw console //- Draw console
void PP_DrawDebugConsole(b32 minimized) void PP_DrawDebugConsole(b32 minimized)
{ {
@ -337,16 +302,26 @@ void PP_DrawDebugConsole(b32 minimized)
PP_SharedUserState *g = &PP_shared_user_state; PP_SharedUserState *g = &PP_shared_user_state;
TempArena scratch = BeginScratchNoConflict(); TempArena scratch = BeginScratchNoConflict();
// i32 console_level = minimized ? P_LogLevel_Success : P_LogLevel_Debug; // i32 console_level = minimized ? LogLevel_Success : LogLevel_Debug;
i32 console_level = P_LogLevel_Debug; i32 console_level = LogLevel_Debug;
u32 colors[P_LogLevel_Count][2] = ZI; u32 colors[LogLevel_Count][2] = ZI;
SetBytes(colors, 0xFF, sizeof(colors)); SetBytes(colors, 0xFF, sizeof(colors));
colors[P_LogLevel_Debug][0] = Rgb32F(0.4, 0.1, 0.4); colors[P_LogLevel_Debug][1] = Rgb32F(0.5, 0.2, 0.5); /* Debug colors */
colors[P_LogLevel_Info][0] = Rgb32F(0.4, 0.4, 0.4); colors[P_LogLevel_Info][1] = Rgb32F(0.5, 0.5, 0.5); colors[LogLevel_Debug][0] = Rgb32F(0.4, 0.1, 0.4);
colors[P_LogLevel_Success][0] = Rgb32F(0.1, 0.3, 0.1); colors[P_LogLevel_Success][1] = Rgb32F(0.2, 0.4, 0.2); colors[LogLevel_Debug][1] = Rgb32F(0.5, 0.2, 0.5);
colors[P_LogLevel_Warning][0] = Rgb32F(0.4, 0.4, 0.1); colors[P_LogLevel_Warning][1] = Rgb32F(0.5, 0.5, 0.2); /* Info colors */
colors[P_LogLevel_Error][0] = Rgb32F(0.4, 0.1, 0.1); colors[P_LogLevel_Error][1] = Rgb32F(0.5, 0.2, 0.2); colors[LogLevel_Info][0] = Rgb32F(0.4, 0.4, 0.4);
colors[LogLevel_Info][1] = Rgb32F(0.5, 0.5, 0.5);
/* Success colors */
colors[LogLevel_Success][0] = Rgb32F(0.1, 0.3, 0.1);
colors[LogLevel_Success][1] = Rgb32F(0.2, 0.4, 0.2);
/* Warning colors */
colors[LogLevel_Warning][0] = Rgb32F(0.4, 0.4, 0.1);
colors[LogLevel_Warning][1] = Rgb32F(0.5, 0.5, 0.2);
/* Error colors */
colors[LogLevel_Error][0] = Rgb32F(0.4, 0.1, 0.1);
colors[LogLevel_Error][1] = Rgb32F(0.5, 0.2, 0.2);
i64 max_time_ns = I64Max; i64 max_time_ns = I64Max;
i64 fade_time_ns = max_time_ns; i64 fade_time_ns = max_time_ns;
@ -364,11 +339,7 @@ void PP_DrawDebugConsole(b32 minimized)
{ {
{ {
UI_SetNext(LayoutAxis, Axis_Y); UI_SetNext(LayoutAxis, Axis_Y);
// UI_SetNext(Tint, 0);
// UI_SetNext(BorderColor, Rgba32F(1, 1, 1, 0.25));
UI_SetNext(Border, 0); UI_SetNext(Border, 0);
// UI_SetNext(Width, UI_FIT(1));
// UI_ForceNext(BackgroundColor, Color_Purple);
if (minimized) if (minimized)
{ {
UI_SetNext(BackgroundColor, 0); UI_SetNext(BackgroundColor, 0);
@ -385,30 +356,26 @@ void PP_DrawDebugConsole(b32 minimized)
UI_Box *console_box = UI_BuildBox(0, UI_NilKey); UI_Box *console_box = UI_BuildBox(0, UI_NilKey);
UI_Push(Parent, console_box); UI_Push(Parent, console_box);
} }
// UI_Push(Width, UI_TXT(0));
// UI_Push(Width, UI_FIT(1));
// UI_Push(Height, UI_FIT(1));
// UI_Push(BorderColor, Rgba32F(0.25, 0.25, 0.25, 1));
// UI_Push(Rounding, 0);
Lock lock = LockE(&g->console_logs_mutex);
{ {
/* Gather display logs */ /* Gather display logs */
u64 max = 20; u64 max = 20;
u64 display_count = 0; u64 display_count = 0;
PP_ConsoleLog **display_logs = PushStructs(scratch.arena, PP_ConsoleLog *, max); LogEvent *display_logs = PushStructs(scratch.arena, LogEvent, max);
{ {
b32 done = 0; b32 done = 0;
if (minimized) if (minimized)
{ {
max = 5; max = 5;
} }
for (PP_ConsoleLog *log = g->last_console_log; log && display_count < max && !done; log = log->prev) LogEventsArray logs = GetLogEvents();
for (u64 i = logs.count; i-- > 0 && display_count < max && !done;)
{ {
if (log->time_ns > (now_ns - max_time_ns)) LogEvent ev = logs.logs[i];
if (ev.time_ns > (now_ns - max_time_ns))
{ {
if (log->level <= console_level) if (ev.level <= console_level)
{ {
display_logs[display_count] = log; display_logs[display_count] = ev;
++display_count; ++display_count;
} }
} }
@ -418,18 +385,17 @@ void PP_DrawDebugConsole(b32 minimized)
} }
} }
} }
/* Display logs in reverse */ /* Display logs in reverse */
for (u64 i = display_count; i-- > 0;) for (u64 i = display_count; i-- > 0;)
{ {
PP_ConsoleLog *log = display_logs[i]; LogEvent log = display_logs[i];
f32 opacity = 0.75; f32 opacity = 0.75;
f32 lin = 1.0 - ClampF64((f64)(now_ns - log->time_ns) / (f64)fade_time_ns, 0, 1); f32 lin = 1.0 - ClampF64((f64)(now_ns - log.time_ns) / (f64)fade_time_ns, 0, 1);
opacity *= PowF32(lin, fade_curve); opacity *= PowF32(lin, fade_curve);
String text = log->msg; String text = log.msg;
if (!minimized) if (!minimized)
{ {
P_DateTime datetime = log->datetime; DateTime datetime = log.datetime;
text = StringF( text = StringF(
scratch.arena, scratch.arena,
"[%F:%F:%F.%F] %F", "[%F:%F:%F.%F] %F",
@ -443,7 +409,7 @@ void PP_DrawDebugConsole(b32 minimized)
{ {
UI_Push(Tint, Alpha32F(0xFFFFFFFF, opacity)); UI_Push(Tint, Alpha32F(0xFFFFFFFF, opacity));
{ {
u32 color = colors[log->level][log->color_index]; u32 color = colors[log.level][log.level_id % 2];
UI_SetNext(BackgroundColor, color); UI_SetNext(BackgroundColor, color);
UI_SetNext(LayoutAxis, Axis_X); UI_SetNext(LayoutAxis, Axis_X);
UI_SetNext(Width, UI_FILL(1, 0)); UI_SetNext(Width, UI_FILL(1, 0));
@ -467,7 +433,6 @@ void PP_DrawDebugConsole(b32 minimized)
UI_PopCheckpoint(); UI_PopCheckpoint();
} }
} }
Unlock(&lock);
} }
UI_PopCheckpoint(); UI_PopCheckpoint();
EndScratch(scratch); EndScratch(scratch);
@ -847,7 +812,7 @@ void PP_UpdateUser(void)
if (g->bind_states[PP_BindKind_DebugToggleTopmost].num_presses > 0) if (g->bind_states[PP_BindKind_DebugToggleTopmost].num_presses > 0)
{ {
WND_PushCmd(window_frame, .kind = WND_CmdKind_SetForcedTop, .v = !window_frame.forced_top); WND_PushCmd(window_frame, .kind = WND_CmdKind_SetForcedTop, .v = !window_frame.forced_top);
P_LogSuccessF("Toggle topmost"); LogSuccessF("Toggle topmost");
} }
if (g->bind_states[PP_BindKind_DebugConsole].num_presses > 0) if (g->bind_states[PP_BindKind_DebugConsole].num_presses > 0)
@ -2996,20 +2961,20 @@ JobDef(PP_UpdateSim, UNUSED sig, UNUSED key)
#if 0 #if 0
DEBUGBREAKABLE; DEBUGBREAKABLE;
P_LogDebugF("*************************************************"); LogDebugF("*************************************************");
P_LogDebugF("local_client->last_tick: %F", FmtUint(local_client->last_tick)); LogDebugF("local_client->last_tick: %F", FmtUint(local_client->last_tick));
P_LogDebugF("master_sim_predicted_time_ns: %F", FmtSint(master_sim_predicted_time_ns)); LogDebugF("master_sim_predicted_time_ns: %F", FmtSint(master_sim_predicted_time_ns));
P_LogDebugF("tick_progress: %F", FmtFloat(tick_progress)); LogDebugF("tick_progress: %F", FmtFloat(tick_progress));
P_LogDebugF("sim_publish_timescale: %F", FmtFloat(sim_publish_timescale)); LogDebugF("sim_publish_timescale: %F", FmtFloat(sim_publish_timescale));
P_LogDebugF("last_tick_from_master_received_at_ns: %F", FmtSint(last_tick_from_master_received_at_ns)); LogDebugF("last_tick_from_master_received_at_ns: %F", FmtSint(last_tick_from_master_received_at_ns));
P_LogDebugF("average_master_receive_dt_ns: %F", FmtSint(average_master_receive_dt_ns)); LogDebugF("average_master_receive_dt_ns: %F", FmtSint(average_master_receive_dt_ns));
P_LogDebugF("next_tick_expected_ns: %F", FmtSint(next_tick_expected_ns)); LogDebugF("next_tick_expected_ns: %F", FmtSint(next_tick_expected_ns));
P_LogDebugF("master_blend_time_target_ns: %F", FmtSint(master_blend_time_target_ns)); LogDebugF("master_blend_time_target_ns: %F", FmtSint(master_blend_time_target_ns));
P_LogDebugF("blend_time_target_diff_ns: %F", FmtSint(blend_time_target_diff_ns)); LogDebugF("blend_time_target_diff_ns: %F", FmtSint(blend_time_target_diff_ns));
P_LogDebugF("master_blend_time_ns: %F", FmtSint(master_blend_time_ns)); LogDebugF("master_blend_time_ns: %F", FmtSint(master_blend_time_ns));
P_LogDebugF("left_snapshot->tick: %F", FmtUint(left_snapshot->tick)); LogDebugF("left_snapshot->tick: %F", FmtUint(left_snapshot->tick));
P_LogDebugF("right_snapshot->tick: %F", FmtUint(right_snapshot->tick)); LogDebugF("right_snapshot->tick: %F", FmtUint(right_snapshot->tick));
P_LogDebugF("master_ss->tick: %F", FmtUint(master_ss->tick)); LogDebugF("master_ss->tick: %F", FmtUint(master_ss->tick));
#endif #endif
} }

View File

@ -113,8 +113,7 @@ Struct(PP_ConsoleLog)
String msg; String msg;
i32 level; i32 level;
i32 color_index; i32 color_index;
P_DateTime datetime; DateTime datetime;
i64 time_ns;
PP_ConsoleLog *prev; PP_ConsoleLog *prev;
PP_ConsoleLog *next; PP_ConsoleLog *next;
}; };
@ -197,13 +196,6 @@ Struct(PP_SharedUserState)
//- Bind state //- Bind state
PP_BindState bind_states[PP_BindKind_Count]; PP_BindState bind_states[PP_BindKind_Count];
//- Debug console
Mutex console_logs_mutex;
Arena *console_logs_arena;
PP_ConsoleLog *first_console_log;
PP_ConsoleLog *last_console_log;
i32 console_log_color_indices[P_LogLevel_Count];
//- Window -> user //- Window -> user
Mutex sys_window_events_mutex; Mutex sys_window_events_mutex;
Arena *sys_window_events_arena; Arena *sys_window_events_arena;
@ -313,7 +305,6 @@ String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Console draw operations //~ Console draw operations
P_LogEventCallbackFuncDef(PP_ConsoleLogCallback, log);
void PP_DrawDebugConsole(b32 minimized); void PP_DrawDebugConsole(b32 minimized);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -929,7 +929,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
player->owner = player->key; player->owner = player->key;
PP_EnableProp(player, PP_Prop_IsMaster); PP_EnableProp(player, PP_Prop_IsMaster);
} }
P_LogInfoF("Created player with key %F for sim client %F. is_master: %F", FmtUid(player->key.uid), FmtHandle(client->key), FmtUint(PP_HasProp(player, PP_Prop_IsMaster))); LogInfoF("Created player with key %F for sim client %F. is_master: %F", FmtUid(player->key.uid), FmtHandle(client->key), FmtUint(PP_HasProp(player, PP_Prop_IsMaster)));
} }
/* Update rtt */ /* Update rtt */
@ -1096,7 +1096,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
} }
if (flags & PP_ControlFlag_SpawnTest1) if (flags & PP_ControlFlag_SpawnTest1)
{ {
P_LogDebugF("Spawn test 1"); LogDebugF("Spawn test 1");
u32 count = 1; u32 count = 1;
f32 spread = 0; f32 spread = 0;
for (u32 j = 0; j < count; ++j) for (u32 j = 0; j < count; ++j)
@ -1108,7 +1108,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
} }
if (flags & PP_ControlFlag_SpawnTest2) if (flags & PP_ControlFlag_SpawnTest2)
{ {
P_LogDebugF("Spawn test 2"); LogDebugF("Spawn test 2");
u32 count = 1; u32 count = 1;
f32 spread = 0; f32 spread = 0;
for (u32 j = 0; j < count; ++j) for (u32 j = 0; j < count; ++j)
@ -1120,7 +1120,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
} }
if (flags & PP_ControlFlag_SpawnTest3) if (flags & PP_ControlFlag_SpawnTest3)
{ {
P_LogDebugF("Spawn test 3"); LogDebugF("Spawn test 3");
u32 count = 1; u32 count = 1;
f32 spread = 0; f32 spread = 0;
for (u32 j = 0; j < count; ++j) for (u32 j = 0; j < count; ++j)
@ -1132,7 +1132,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
} }
if (flags & PP_ControlFlag_SpawnTest4) if (flags & PP_ControlFlag_SpawnTest4)
{ {
P_LogDebugF("Spawn test 4"); LogDebugF("Spawn test 4");
u32 count = 1; u32 count = 1;
f32 spread = 0; f32 spread = 0;
for (u32 j = 0; j < count; ++j) for (u32 j = 0; j < count; ++j)
@ -1148,7 +1148,7 @@ void PP_StepSim(PP_SimStepCtx *ctx)
} }
if (flags & PP_ControlFlag_TestExplode) if (flags & PP_ControlFlag_TestExplode)
{ {
P_LogDebugF("Explosion test"); LogDebugF("Explosion test");
PP_SpawnTestExplosion(root, player->player_cursor_pos, 100, 2); PP_SpawnTestExplosion(root, player->player_cursor_pos, 100, 2);
} }
} }

View File

@ -10,7 +10,7 @@ JobDef(SND_Load, sig, UNUSED id)
AC_Asset *asset = sig->asset; AC_Asset *asset = sig->asset;
SND_SoundFlag flags = sig->flags; SND_SoundFlag flags = sig->flags;
P_LogInfoF("Loading sound \"%F\"", FmtString(name)); LogInfoF("Loading sound \"%F\"", FmtString(name));
i64 start_ns = TimeNs(); i64 start_ns = TimeNs();
String error_msg = Lit("Unknown error"); String error_msg = Lit("Unknown error");
@ -56,12 +56,12 @@ JobDef(SND_Load, sig, UNUSED id)
sound->samples = samples; sound->samples = samples;
CopyBytes(sound->samples, decoded.samples, decoded.samples_count * sizeof(*decoded.samples)); CopyBytes(sound->samples, decoded.samples, decoded.samples_count * sizeof(*decoded.samples));
P_LogSuccessF("Loaded sound \"%F\" in %F seconds", FmtString(name), FmtFloat(SecondsFromNs(TimeNs() - start_ns))); LogSuccessF("Loaded sound \"%F\" in %F seconds", FmtString(name), FmtFloat(SecondsFromNs(TimeNs() - start_ns)));
AC_MarkReady(asset, sound); AC_MarkReady(asset, sound);
} }
else else
{ {
P_LogErrorF("Error loading sound \"%F\": %F", FmtString(name), FmtString(error_msg)); LogErrorF("Error loading sound \"%F\": %F", FmtString(name), FmtString(error_msg));
/* Store */ /* Store */
SND_Sound *sound = 0; SND_Sound *sound = 0;

View File

@ -360,7 +360,7 @@ LRESULT CALLBACK WND_W32_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l
u8 *buff = PushStructs(scratch.arena, u8, buff_size); u8 *buff = PushStructs(scratch.arena, u8, buff_size);
if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buff, &buff_size, sizeof(RAWINPUTHEADER)) != buff_size) if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buff, &buff_size, sizeof(RAWINPUTHEADER)) != buff_size)
{ {
P_LogErrorF("GetRawInputData did not return correct size"); LogErrorF("GetRawInputData did not return correct size");
break; break;
} }
RAWINPUT raw = ZI; RAWINPUT raw = ZI;