Skip to content

ross-weir/logex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Logex

CI

logex (log extensions) is a minimal, extensible logging library for Zig that enhances std.log with additional features while maintaining a simple, drop-in interface.

Table of Contents

Features

  • Drop-in Extension: Extends std.log with extra features - easy to add and remove without changing logging calls throughout your project
  • Extensible Appenders: Comes with console and file appenders, with the ability to implement custom appenders for any logging destination
  • Customize Formatting: Multiple format options:
    • Text (compatible with std.log default format)
    • JSON
    • Custom (implement your own formatting function)
  • Runtime filtering: Extends scope/log level filtering with runtime options, this allows for environment variable based filtering similar to env_logger from the Rust logging ecosystem
  • Minimal Impact: logex aims to add minimal overhead by remaining comptime as much as possible like the default std.log implementation

Install

Add logex as a dependency to your zig project like so:

zig fetch --save git+https://github.com/ross-weir/logex.git

And configure it in your build.zig:

// .. snip

const logex = b.dependency("logex", .{
    .target = target,
    .optimize = optimize,
});

const exe_mod = b.createModule(.{
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
    .imports = &.{
        .{
            .name = "logex",
            .module = logex.module("logex"),
        },
    },
});

Quick Start

const std = @import("std");
const logex = @import("logex");

// Create appender types
// Log to the console at debug and above levels, using default text formatting
const ConsoleAppender = logex.appenders.Console(.debug, .{});
// Log to file at info and above levels, using JSON formatting
const FileAppender = logex.appenders.File(.info, .{
    .format = .json,
});

// Create logger type with both appender types
const Logger = logex.Logex(.{ ConsoleAppender, FileAppender });

// Use in std_options
pub const std_options: std.Options = .{
    .logFn = Logger.logFn,
};

pub fn main() !void {
    // Initialize appender instances
    const console_appender = ConsoleAppender.init;
    const file_appender = try FileAppender.init("app.log");

    // Initialize logger
    try Logger.init(.{}, .{ console_appender, file_appender });

    // Use std.log as usual
    // Debug message will only be displayed on console
    std.log.debug("Debug message", .{});
    // Info message will be logged to file and console
    std.log.info("Info message", .{});
}

Removing logex is as simple as removing Logger.logFn and deleting initialzation.

Appenders

logex comes with two built-in appenders:

  • Writer Appender: A generic threadsafe appender that writes to an underlying AnyWriter
  • Console Appender: Logs to stderr, works the same as the default logFn from std.log
  • File Appender: Logs to file

Creating Custom Appenders

You can create custom appenders by implementing the Appender interface:

const logex = @import("logex");

const MyCustomAppender = struct {
    pub fn log(
        self: *@This(),
        comptime record: *const logex.Record,
        context: *const logex.Context,
    ) !void {
        // Implement your logging logic
    }
};

See a more complete example here.

Formatting

logex supports multiple output formats:

  • Text: Default format compatible with std.log
  • JSON: Structured logging in JSON format
  • Custom: Implement your own formatting function

See a complete example using a custom formatter here.

Runtime Filtering

logex provides filtering at runtime that works alongside comptime filtering (std.options.log_scope_levels / std.options.log_level).

An environment variable based filter is provided out of the box with capabilities similar to the Rust ecosystem's env_logger. This allows you to configure log levels for different scopes at runtime through environment variables, without recompiling your application.

Environment Variable Configuration

By default, logex uses the ZIG_LOG environment variable for configuration. The format is:

scope1=level1,scope2=level2,level3

Where:

  • scope is the logging scope (e.g., "my_module")
  • level is one of: debug, info, warn, err
  • A level without a scope sets the default level

Examples:

# Set default level to info
export ZIG_LOG=info

# Set specific scopes
export ZIG_LOG=my_module=debug,other_module=warn

# Mix of scoped and default levels
export ZIG_LOG=info,my_module=debug,other_module=warn

See a complete example of runtime filtering here.

Examples

Check out the example directory for complete usage examples.

About

logex is a drop-in zig std.log extensions library enabling extra functionality/customization

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages