more progress on code 2
This commit is contained in:
160
code2/grime/logger.odin
Normal file
160
code2/grime/logger.odin
Normal file
@@ -0,0 +1,160 @@
|
||||
package grime
|
||||
|
||||
import core_log "core:log"
|
||||
|
||||
Max_Logger_Message_Width :: 160
|
||||
|
||||
LoggerEntry :: struct {
|
||||
text : string,
|
||||
timestamp : string,
|
||||
level : string,
|
||||
location : string,
|
||||
}
|
||||
|
||||
Logger :: struct {
|
||||
file_path : string,
|
||||
file : OS_Handle,
|
||||
id : string,
|
||||
|
||||
// varena : VArena,
|
||||
// entries : Array(LoggerEntry),
|
||||
}
|
||||
|
||||
to_odin_logger :: proc( logger : ^ Logger ) -> Odin_Logger {
|
||||
return { logger_interface, logger, LoggerLevel.Debug, Default_File_Logger_Opts }
|
||||
}
|
||||
|
||||
logger_init :: proc( logger : ^ Logger, id : string, file_path : string, file := OS_INVALID_HANDLE )
|
||||
{
|
||||
if file == OS_INVALID_HANDLE
|
||||
{
|
||||
logger_file, result_code := file_open( file_path, FS_Open_Readonly | FS_Open_Create )
|
||||
assert( result_code == OS_ERROR_NONE, "Log failures are fatal and must never occur at runtime (there is no logging)" )
|
||||
logger.file = logger_file
|
||||
file_truncate( file_path, 0 )
|
||||
}
|
||||
else {
|
||||
logger.file = file
|
||||
}
|
||||
logger.file_path = file_path
|
||||
logger.id = id
|
||||
|
||||
LOGGER_VARENA_BASE_ADDRESS : uintptr = 2 * Tera
|
||||
@static vmem_init_counter : uintptr = 0
|
||||
|
||||
// alloc_error : AllocatorError
|
||||
// logger.varena, alloc_error = varena_init(
|
||||
// LOGGER_VARENA_BASE_ADDRESS + vmem_init_counter * 250 * Megabyte,
|
||||
// 1 * Megabyte,
|
||||
// 128 * Kilobyte,
|
||||
// growth_policy = nil,
|
||||
// allow_any_resize = true,
|
||||
// dbg_name = "logger varena",
|
||||
// enable_mem_tracking = false )
|
||||
// verify( alloc_error == .None, "Failed to allocate logger's virtual arena")
|
||||
vmem_init_counter += 1
|
||||
|
||||
// TODO(Ed): Figure out another solution here...
|
||||
// logger.entries, alloc_error = array_init(Array(LoggerEntry), 8192, runtime.heap_allocator())
|
||||
// verify( alloc_error == .None, "Failed to allocate logger's entries array")
|
||||
|
||||
context.logger = { logger_interface, logger, LoggerLevel.Debug, Default_File_Logger_Opts }
|
||||
log("Initialized Logger")
|
||||
when false {
|
||||
log("This sentence is over 80 characters long on purpose to test the ability of this logger to properfly wrap long as logs with a new line and then at the end of that pad it with the appropraite signature.")
|
||||
}
|
||||
}
|
||||
|
||||
logger_interface :: proc(
|
||||
logger_data : rawptr,
|
||||
level : LoggerLevel,
|
||||
text : string,
|
||||
options : LoggerOptions,
|
||||
location := #caller_location )
|
||||
{
|
||||
logger := cast(^ Logger) logger_data
|
||||
|
||||
@static builder_backing : [16 * Kilo] byte; {
|
||||
mem_zero( cursor(builder_backing[:]), len(builder_backing) )
|
||||
}
|
||||
builder := strbuilder_from_bytes( builder_backing[:] )
|
||||
|
||||
first_line_length := len(text) > Max_Logger_Message_Width ? Max_Logger_Message_Width : len(text)
|
||||
first_line := transmute(string) text[ 0 : first_line_length ]
|
||||
|
||||
str_pfmt_builder( & builder, "%s ", first_line )
|
||||
|
||||
// str_pfmt_builder( & builder, "%-s ", first_line )
|
||||
|
||||
// Signature
|
||||
{
|
||||
when TIME_IS_SUPPORTED
|
||||
{
|
||||
if Logger_Full_Timestamp_Opts & options != nil {
|
||||
str_pfmt_builder( & builder, "[")
|
||||
|
||||
t := time_now()
|
||||
year, month, day := time_date(t)
|
||||
hour, minute, second := time_clock(t)
|
||||
|
||||
if .Date in options {
|
||||
str_pfmt_builder( & builder, "%d-%02d-%02d ", year, month, day )
|
||||
}
|
||||
if .Time in options {
|
||||
str_pfmt_builder( & builder, "%02d:%02d:%02d", hour, minute, second)
|
||||
}
|
||||
|
||||
str_pfmt_builder( & builder, "] ")
|
||||
}
|
||||
}
|
||||
|
||||
core_log.do_level_header( options, & builder, level )
|
||||
|
||||
if logger.id != "" {
|
||||
str_pfmt_builder( & builder, "[%s] ", logger.id )
|
||||
}
|
||||
core_log.do_location_header( options, & builder, location )
|
||||
}
|
||||
|
||||
// Oversized message handling
|
||||
if len(text) > Max_Logger_Message_Width
|
||||
{
|
||||
offset := Max_Logger_Message_Width
|
||||
bytes := transmute( []u8 ) text
|
||||
for left := len(bytes) - Max_Logger_Message_Width; left > 0; left -= Max_Logger_Message_Width
|
||||
{
|
||||
str_pfmt_builder( & builder, "\n" )
|
||||
subset_length := len(text) - offset
|
||||
if subset_length > Max_Logger_Message_Width {
|
||||
subset_length = Max_Logger_Message_Width
|
||||
}
|
||||
subset := slice( cursor(bytes)[offset:], subset_length )
|
||||
str_pfmt_builder( & builder, "%s", transmute(string) subset )
|
||||
offset += Max_Logger_Message_Width
|
||||
}
|
||||
}
|
||||
|
||||
str_pfmt_file_ln( logger.file, to_string(builder) )
|
||||
}
|
||||
|
||||
// This buffer is used below excluisvely to prevent any allocator recusion when verbose logging from allocators.
|
||||
// This means a single line is limited to 32k buffer (increase naturally if this SOMEHOW becomes a bottleneck...)
|
||||
Logger_Allocator_Buffer : [32 * Kilo]u8
|
||||
|
||||
log :: proc( msg : string, level := LoggerLevel.Info, loc := #caller_location ) {
|
||||
// TODO(Ed): Finish this
|
||||
// temp_arena : Arena; arena_init(& temp_arena, Logger_Allocator_Buffer[:])
|
||||
// context.allocator = arena_allocator(& temp_arena)
|
||||
// context.temp_allocator = arena_allocator(& temp_arena)
|
||||
|
||||
// core_log.log( level, msg, location = loc )
|
||||
}
|
||||
|
||||
log_fmt :: proc( fmt : string, args : ..any, level := LoggerLevel.Info, loc := #caller_location ) {
|
||||
// TODO(Ed): Finish this
|
||||
// temp_arena : Arena; arena_init(& temp_arena, Logger_Allocator_Buffer[:])
|
||||
// context.allocator = arena_allocator(& temp_arena)
|
||||
// context.temp_allocator = arena_allocator(& temp_arena)
|
||||
|
||||
// core_log.logf( level, fmt, ..args, location = loc )
|
||||
}
|
Reference in New Issue
Block a user