package core:log

⌘K
Ctrl+K
or
/

    Overview

    Implementation of logging facilities.

    Odin has builtin support for logging using procedure context. After a logger is created it can then be assigned to context.logger and used implicitly in future log calls.

    While it is ok for simple apps to use the core:fmt package, libraries and complex apps should prefer the core:log package. By using the implicit logger library and application authors allow the caller to decide how to process log messages.

    When starting out you can easily just init the logger with a single line.

    Example:
    package main
    
    import "core:log"
    
    main :: proc() {
    	context.logger = log.create_console_logger()
    	log.info("Hello World!")
    }
    

    However when the application gets more involved you might want to try a more complex setup.

    Example:
    package main
    
    import "core:log"
    import "core:os"
    
    main :: proc() {
    	handle, err := os.open("logs.txt", os.O_RDWR | os.O_APPEND | os.O_CREATE, 0o666)
    	assert(err == nil, "Cannot open log file")
    
    	file_logger := log.create_file_logger(handle)
    	// This closes the file handle
    	defer log.destroy_file_logger(file_logger)
    
    	console_logger := log.create_console_logger()
    	defer log.destroy_console_logger(console_logger)
    
    	multi_logger := log.create_multi_logger(console_logger, file_logger)
    	defer log.destroy_multi_logger(multi_logger)
    
    	context.logger = multi_logger
    
    	log.info("Application started!")
    }
    

    It is also possible to create an allocator that logs all allocations.

    Example:
    package main
    
    import "core:log"
    
    main :: proc() {
    	context.logger = log.create_console_logger()
    
    	alloc: log.Log_Allocator
    	log.log_allocator_init(&alloc, .Debug)
    	context.allocator = log.log_allocator(&alloc)
    
    	a := new(i32)
    	free(a)
    }
    

    Types

    File_Console_Logger_Data ¶

    File_Console_Logger_Data :: struct {
    	file_handle: ^os.File,
    	ident:       string,
    }
     

    Data backing a file or console logger.

    Level ¶

    Level :: runtime.Logger_Level
     

    Logger_Level :: enum {

    Debug   = 0,
    Info    = 10,
    Warning = 20,
    Error   = 30,
    Fatal   = 40,
    

    }

    Related Procedures With Parameters

    Log_Allocator ¶

    Log_Allocator :: struct {
    	allocator: runtime.Allocator,
    	// Wrapped allocator
    	level:     runtime.Logger_Level,
    	// Log Level used for allocations
    	prefix:    string,
    	// Prefix to use in log messages
    	lock:      sync.Mutex,
    	size_fmt:  Log_Allocator_Format,
    }
     

    Log_Allocator is an allocator which calls context.logger on each of its allocations operations. The format can be changed by setting the size_fmt: Log_Allocator_Format field to either Bytes or Human.

    Related Procedures With Parameters

    Log_Allocator_Format ¶

    Log_Allocator_Format :: enum int {
    	Bytes, // Actual number of bytes.
    	Human, // Bytes in human units like bytes, kibibytes, etc. as appropriate.
    }
     

    Format to use when logging allocations.

    Related Procedures With Parameters

    Logger ¶

    Logger :: runtime.Logger
     

    Data backing the logger.

    Defined in package runtime as it is used in the context. This is to prevent an import definition cycle.

    Logger :: struct {
    	// Implementation
    	procedure:    Logger_Proc,
    	// Configuration data passed to the implementation
    	data:         rawptr,
    	// Minimum level for messages passed to the implementation
    	lowest_level: Level,
    	// Additional data present in the log output
    	options:      Logger_Options,
    }
    
    Related Procedures With Parameters
    Related Procedures With Returns

    Logger_Proc ¶

    Logger_Proc :: runtime.Logger_Proc
     

    Implementation of the logger.

    Defined in package runtime as it is used in the context. This is to prevent an import definition cycle.

    Logger_Proc :: #type proc(data: rawptr, level: Level, text: string, options: Options, location := #caller_location);
    

    Multi_Logger_Data ¶

    Multi_Logger_Data :: struct {
    	loggers: []runtime.Logger,
    }
     

    A container backing for multiple loggers.

    Option ¶

    Option :: runtime.Logger_Option
     

    Specifies additional data present in the log output.

    Defined in package runtime as it is used in the context. This is to prevent an import definition cycle.

    Option :: enum {
    	// The log level, e.g. "[DEBUG] ---"
    	Level,
    	// The date, e.g. [2025-01-02]
    	Date,
    	// The time, e.g. [12:34:56]
    	Time,
    	// Just the filename, e.g. [main.odin]
    	Short_File_Path,
    	// Full file path, e.g. [/tmp/project/main.odin]
    	Long_File_Path,
    	// File line of the log statement, e.g. [8]
    	Line,
    	// Calling procedure, e.g. [main()]
    	Procedure,
    	// Enables colored output
    	Terminal_Color
    }
    

    Options ¶

    Options :: bit_set[runtime.Logger_Option]
     

    Specifies additional data present in the log output.

    Defined in package runtime as it is used in the context. This is to prevent an import definition cycle.

    Options :: bit_set[Option];
    
    Related Procedures With Parameters
    Related Constants

    Constants

    Default_Console_Logger_Opts ¶

    Default_Console_Logger_Opts: bit_set[runtime.Logger_Option] : Options{.Level, .Terminal_Color, .Short_File_Path, .Line, .Procedure} + Full_Timestamp_Opts
     

    The default option set for a console logger.

    It is similar to the file logger default option set, but the output includes colors.

    When you use this set of options you can expect the following output:

    [LEVEL] --- [YYYY-MM-DD HH:MM:SS] [file.odin:L:proc()] Message
    
    

    For example:

    [INFO ] --- [2025-01-02 12:34:56] [main.odin:8:main()] Hello World!
    

    Default_File_Logger_Opts ¶

    Default_File_Logger_Opts: bit_set[runtime.Logger_Option] : Options{.Level, .Short_File_Path, .Line, .Procedure} + Full_Timestamp_Opts
     

    The default option set for a file logger.

    It is similar to the console logger default option set, but the output is not colored.

    When you use this set of options you can expect the following output:

    [LEVEL] --- [YYYY-MM-DD HH:MM:SS] [file.odin:L:proc()] Message
    
    

    For example:

    [INFO ] --- [2025-01-02 12:34:56] [main.odin:8:main()] Hello World!
    

    Full_Timestamp_Opts ¶

    Full_Timestamp_Opts: bit_set[runtime.Logger_Option] : Options{.Date, .Time}
     

    A preset option set for a logger.

    When you use this set of options you can expect the following output:

    [YYYY-MM-DD HH:MM:SS] Message
    
    

    For example:

    [2025-01-02 12:34:56] Hello World!
    

    Location_File_Opts ¶

    Location_File_Opts: bit_set[runtime.Logger_Option] : Options{.Short_File_Path, .Long_File_Path}
     

    A preset option set for a logger.

    When you use this set of options you can expect the following output:

    [file.odin] Message
    
    

    For example:

    [main.odin] Hello World!
    

    Location_Header_Opts ¶

    Location_Header_Opts: bit_set[runtime.Logger_Option] : Options{.Short_File_Path, .Long_File_Path, .Line, .Procedure}
     

    A preset option set for a logger.

    When you use this set of options you can expect the following output:

    [file.odin:L:proc()] Message
    
    

    For example:

    [main.odin:8:main()] Hello World!
    

    Variables

    Level_Headers ¶

    Level_Headers: [50]string = …
     

    Strings to output when .Level is included in the logger options.

    Procedures

    assert ¶

    assert :: proc(condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
     

    When condition is false log a message at the Fatal level and abort the program.

    Can be disabled using ODIN_DISABLE_ASSERT.

    Inputs:
    condition: A boolean to check message: Message to log when condition is false (a default is provided) loc: Location of the caller (default is #caller_location)

    assertf ¶

    assertf :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_location) {…}
     

    When condition is false log a formatted message at the Fatal level and abort the program.

    Can be disabled using ODIN_DISABLE_ASSERT.

    Inputs:
    condition: A boolean to check fmt_str: A format string to use when condition is false, e.g. `"a: %v, b: %v" args: Arguments for the format string loc: Location of the caller (default is #caller_location)

    console_logger_proc ¶

    console_logger_proc :: proc(logger_data: rawptr, level: runtime.Logger_Level, text: string, options: bit_set[runtime.Logger_Option], location := #caller_location) {…}

    create_console_logger ¶

    create_console_logger :: proc(lowest: runtime.Logger_Level = Level.Debug, opt: bit_set[runtime.Logger_Option] = Default_Console_Logger_Opts, ident: string = "", allocator := context.allocator) -> runtime.Logger {…}
     

    Create a logger that outputs to the terminal.

    Allocates Using Provided Allocator

    When no longer needed can be destroyed with destroy_console_logger.

    Inputs:
    lowest: Log level to use (default is .Debug) opt: Specifies additional data present in the log output (default is log.Default_Console_Logger_Opts) ident: Identifier to include in the output (default is "") allocator: Allocator to use for data backing the logger (default is context.allocator)

    create_file_logger ¶

    create_file_logger :: proc(f: ^os.File, lowest: runtime.Logger_Level = Level.Debug, opt: bit_set[runtime.Logger_Option] = Default_File_Logger_Opts, ident: string = "", allocator := context.allocator) -> runtime.Logger {…}
     

    Create a logger that outputs to a file.

    Allocates Using Provided Allocator

    When no longer needed can be destroyed with destroy_file_logger.

    Inputs:
    h: A handle to the output file lowest: Log level to use (default is .Debug) opt: Specifies additional data present in the log output (default is log.Default_File_Logger_Opts) ident: Identifier to include in the output (default is "") allocator: Allocator to use for data backing the logger (default is context.allocator)

    create_multi_logger ¶

    create_multi_logger :: proc(logs: ..runtime.Logger, allocator := context.allocator) -> runtime.Logger {…}
     

    Create a logger that logs to all backing loggers.

    Allocates Using Provided Allocator

    When no longer needed can be destroyed with destroy_multi_logger.

    Note: Logs using a multi logger take both the multi logger and the backing loggers' log levels into account.

    Inputs:
    logs - Backing loggers passed as multiple arguments allocator - An allocator used to allocate data to store backing loggers (default is context.allocator)

    Returns:
    A multi logger

    debug ¶

    debug :: proc(args: ..any, sep: string = " ", location := #caller_location) {…}
     

    Log a message at the Debug level.

    Inputs:
    args: values to be concatenated into the output sep: separator to use when concatenating (default is " ") location: Location of the caller (default is #caller_location)

    debugf ¶

    debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {…}
     

    Log a formatted message at the Debug level.

    Inputs:
    fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    destroy_console_logger ¶

    destroy_console_logger :: proc(log: runtime.Logger, allocator := context.allocator) {…}
     

    Free the state allocated with create_console_logger.

    Inputs:
    log: Logger created with create_console_logger allocator: Allocator passed to create_console_logger (default is context.allocator)

    destroy_file_logger ¶

    destroy_file_logger :: proc(log: runtime.Logger, allocator := context.allocator) {…}
     

    Free the state allocated with create_file_logger and close the file handle.

    Inputs:
    log: Logger created with create_file_logger allocator: Allocator passed to create_file_logger (default is context.allocator)

    destroy_multi_logger ¶

    destroy_multi_logger :: proc(log: runtime.Logger, allocator := context.allocator) {…}
     

    Free the state allocated with create_multi_logger.

    Inputs:
    log: Logger created with create_multi_logger allocator: Allocator passed to create_multi_logger (default is context.allocator)

    do_level_header ¶

    do_level_header :: proc(opts: bit_set[runtime.Logger_Option], str: ^strings.Builder, level: runtime.Logger_Level) {…}
     

    Helper used to build the part of the message including the log level.

    do_location_header ¶

    do_location_header :: proc(opts: bit_set[runtime.Logger_Option], buf: ^strings.Builder, location := #caller_location) {…}
     

    Helper used to build the part of the message including the file location.

    do_time_header ¶

    do_time_header :: proc(opts: bit_set[runtime.Logger_Option], buf: ^strings.Builder, t: time.Time) {…}
     

    Helper used to build the part of the message including the data and time.

    ensure ¶

    ensure :: proc(condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
     

    When condition is false log a message at the Fatal level and abort the program.

    Unlike assert this procedure cannot be disabled with ODIN_DISABLE_ASSERT and will always execute.

    Inputs:
    condition: A boolean to check message: Message to log when condition is false (a default is provided) loc: Location of the caller (default is #caller_location)

    ensuref ¶

    ensuref :: proc(condition: bool, fmt_str: string, args: ..any, loc := #caller_location) {…}
     

    When condition is false log a formatted message at the Fatal level and abort the program.

    Unlike assertf this procedure cannot be disabled with ODIN_DISABLE_ASSERT and will always execute.

    Inputs:
    condition: A boolean to check fmt_str: A format string to use when condition is false, e.g. `"a: %v, b: %v" args: Arguments for the format string loc: Location of the caller (default is #caller_location)

    error ¶

    error :: proc(args: ..any, sep: string = " ", location := #caller_location) {…}
     

    Log a message at the Error level.

    Inputs:
    args: values to be concatenated into the output sep: separator to use when concatenating (default is " ") location: Location of the caller (default is #caller_location)

    errorf ¶

    errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {…}
     

    Log a formatted message at the Error level.

    Inputs:
    fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    fatal ¶

    fatal :: proc(args: ..any, sep: string = " ", location := #caller_location) {…}
     

    Log a message at the Fatal level.

    Inputs:
    args: values to be concatenated into the output sep: separator to use when concatenating (default is " ") location: Location of the caller (default is #caller_location)

    fatalf ¶

    fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {…}
     

    Log a formatted message at the Fatal level.

    Inputs:
    fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    file_logger_proc ¶

    file_logger_proc :: proc(logger_data: rawptr, level: runtime.Logger_Level, text: string, options: bit_set[runtime.Logger_Option], location := #caller_location) {…}

    info ¶

    info :: proc(args: ..any, sep: string = " ", location := #caller_location) {…}
     

    Log a message at the Info level.

    Inputs:
    args: values to be concatenated into the output sep: separator to use when concatenating (default is " ") location: Location of the caller (default is #caller_location)

    infof ¶

    infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {…}
     

    Log a formatted message at the Info level.

    Inputs:
    fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    log ¶

    log :: proc(level: runtime.Logger_Level, args: ..any, sep: string = " ", location := #caller_location) {…}
     

    Log a message at the desired level.

    Inputs:
    level: The level of the message args: values to be concatenated into the output sep: separator to use when concatenating (default is " ") location: Location of the caller (default is #caller_location)

    log_allocator ¶

    log_allocator :: proc(la: ^Log_Allocator) -> runtime.Allocator {…}
     

    Create an allocator that logs all allocations.

    Inputs:
    la: Pointer to the data structure backing the allocator

    Returns:
    An allocator that logs all allocations

    log_allocator_init ¶

    log_allocator_init :: proc(la: ^Log_Allocator, level: runtime.Logger_Level, size_fmt: Log_Allocator_Format = Log_Allocator_Format.Bytes, allocator := context.allocator, prefix: string = "") {…}
     

    Initialize the backing data for the allocator that logs all allocations.

    Inputs:
    la: Pointer to the data structure to initialize level: Log level to use for allocations size_fmt: Format to use when logging allocations (default is .Bytes) allocator: Wrapped allocator (default is context.allocator) prefix: Prefix to use in log messages (default is "")

    log_allocator_proc ¶

    log_allocator_proc :: proc(
    	allocator_data:  rawptr, 
    	mode:            runtime.Allocator_Mode, 
    	size, alignment: int, 
    	old_memory:      rawptr, 
    	old_size:        int, 
    	location := #caller_location, 
    ) -> ([]u8, runtime.Allocator_Error) {…}
     

    Backing procedure for allocator that logs all allocations.

    logf ¶

    logf :: proc(level: runtime.Logger_Level, fmt_str: string, args: ..any, location := #caller_location) {…}
     

    Log a formatted message at the desired level.

    Inputs:
    level: The level of the message fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    multi_logger_proc ¶

    multi_logger_proc :: proc(logger_data: rawptr, level: runtime.Logger_Level, text: string, options: bit_set[runtime.Logger_Option], location := #caller_location) {…}
     

    Backing procedure for the multi logger.

    nil_logger ¶

    nil_logger :: proc() -> runtime.Logger {…}
     

    Create a logger that does nothing.

    Returns:
    A logger that does nothing

    panic ¶

    panic :: proc(args: ..any, location := #caller_location) -> ! {…}
     

    Log a message at the Fatal level and abort the program.

    Inputs:
    args: values to be concatenated into the output location: Location of the caller (default is #caller_location)

    panicf ¶

    panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {…}
     

    Log a formatted message at the Fatal level and abort the program.

    Inputs:
    fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    warn ¶

    warn :: proc(args: ..any, sep: string = " ", location := #caller_location) {…}
     

    Log a message at the Warn level.

    Inputs:
    args: values to be concatenated into the output sep: separator to use when concatenating (default is " ") location: Location of the caller (default is #caller_location)

    warnf ¶

    warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {…}
     

    Log a formatted message at the Warn level.

    Inputs:
    fmt_str: A format string, e.g. `"a: %v, b: %v" args: Arguments for the format string location: Location of the caller (default is #caller_location)

    Procedure Groups

    This section is empty.

    Source Files

    Generation Information

    Generated with odin version dev-2026-07 (vendor "odin") Windows_amd64 @ 2026-07-06 22:06:12.094260500 +0000 UTC