Skip to content

Advanced Customizations Guide

This guide covers Logly's advanced customization features that allow you to tailor logging behavior to your specific needs.

Global Logs Root Path

The logs root path feature allows you to specify a single root directory where all log files will be stored, making it easy to manage logs from multiple sinks.

Configuration

zig
var config = logly.Config.default();
config.logs_root_path = "./logs";  // All file sinks will be stored in ./logs

const logger = try logly.Logger.initWithConfig(allocator, config);

// Adding sinks with relative paths
_ = try logger.addSink(logly.SinkConfig.file("application.log"));
_ = try logger.addSink(logly.SinkConfig.file("errors.log"));
_ = try logger.addSink(logly.SinkConfig.file("debug.log"));

Behavior

  • Automatic Directory Creation: If the root path doesn't exist, it will be automatically created
  • Path Resolution: File sink paths are automatically prepended with the root path
  • Non-intrusive: If directory creation fails, logging continues without interruption
  • Optional: If logs_root_path is not set, file sinks use absolute or relative paths as specified

Example Output

./logs/
├── application.log
├── errors.log
└── debug.log

Format Structure Customization

Customize how log messages are formatted and structured using FormatStructureConfig.

Configuration

zig
var config = logly.Config.default();
config.format_structure = .{
    .message_prefix = ">>> ",        // Add prefix to each message
    .message_suffix = " <<<",        // Add suffix to each message
    .field_separator = " | ",        // Separator between fields
    .enable_nesting = true,          // Enable hierarchical formatting
    .nesting_indent = "    ",        // Indentation for nested fields
    .include_empty_fields = false,   // Skip null/empty fields
    .placeholder_open = "{",         // Custom placeholder syntax
    .placeholder_close = "}",
};

const logger = try logly.Logger.initWithConfig(allocator, config);

Available Options

OptionPurposeExample
message_prefixText prepended to messages">>> "
message_suffixText appended to messages" <<<"
field_separatorSeparator between log fields" | "
enable_nestingSupport nested/hierarchical logstrue
nesting_indentIndentation for nested items" " (2 spaces)
include_empty_fieldsInclude null fields in outputfalse
placeholder_open/closeCustom placeholder syntax"[[", "]]"

Per-Level Color Customization

Define custom ANSI colors for each log level independently.

Configuration

zig
var config = logly.Config.default();
config.level_colors = .{
    .trace_color = "\x1b[36m",      // Cyan
    .debug_color = "\x1b[35m",      // Magenta
    .info_color = "\x1b[34m",       // Blue
    .success_color = "\x1b[32m",    // Green
    .warning_color = "\x1b[33m",    // Yellow
    .error_color = "\x1b[31m",      // Red
    .fail_color = "\x1b[31;1m",     // Bold Red
    .critical_color = "\x1b[1;31m", // Bold Red
    .use_rgb = false,               // Standard ANSI (not RGB)
    .support_background = false,    // Text colors only
    .reset_code = "\x1b[0m",        // Reset to default
};

const logger = try logly.Logger.initWithConfig(allocator, config);

Common ANSI Color Codes

Standard Colors (8-color mode):

  • "\x1b[30m" - Black
  • "\x1b[31m" - Red
  • "\x1b[32m" - Green
  • "\x1b[33m" - Yellow
  • "\x1b[34m" - Blue
  • "\x1b[35m" - Magenta
  • "\x1b[36m" - Cyan
  • "\x1b[37m" - White

Bright Colors (16-color mode):

  • "\x1b[90m" - Bright Black
  • "\x1b[91m" - Bright Red
  • "\x1b[92m" - Bright Green
  • "\x1b[93m" - Bright Yellow
  • "\x1b[94m" - Bright Blue
  • "\x1b[95m" - Bright Magenta
  • "\x1b[96m" - Bright Cyan
  • "\x1b[97m" - Bright White

Styles:

  • "\x1b[1;31m" - Bold Red
  • "\x1b[2;31m" - Dim Red
  • "\x1b[4;31m" - Underline Red
  • "\x1b[5;31m" - Blinking Red
  • "\x1b[7;31m" - Inverted Red

Highlighters and Alerts

Configure pattern matching and alerting for specific log messages.

Configuration

zig
var config = logly.Config.default();
config.highlighters = .{
    .enabled = true,
    .alert_on_match = true,
    .alert_min_severity = .warning,
    .log_matches = true,
    .max_matches_per_message = 10,
};

const logger = try logly.Logger.initWithConfig(allocator, config);

Options

OptionPurpose
enabledEnable/disable highlighter system
alert_on_matchTrigger alerts when patterns match
alert_min_severityMinimum severity to trigger alerts
log_matchesLog pattern matches as separate records
patternsArray of HighlightPattern structures
max_matches_per_messageMax patterns to match per message

Pattern Definition

zig
pub const HighlightPattern = struct {
    name: []const u8,              // Pattern identifier
    pattern: []const u8,           // Text or regex to match
    is_regex: bool = false,        // Is this a regex pattern?
    highlight_color: []const u8,   // Color for highlights
    severity: AlertSeverity,       // Severity level
    metadata: ?[]const u8 = null,  // Custom metadata
};

Alert Severity Levels

zig
pub const AlertSeverity = enum {
    trace,
    debug,
    info,
    success,
    warning,
    err,
    fail,
    critical,
};

Diagnostics Custom Path

Store system diagnostics in a separate file from regular logs.

Configuration

zig
var config = logly.Config.default();
config.diagnostics_output_path = "./logs/diagnostics.log";
config.logs_root_path = "./logs";
config.emit_system_diagnostics_on_init = true;

const logger = try logly.Logger.initWithConfig(allocator, config);

Behavior

  • Diagnostics are emitted at logger initialization if configured
  • Structured context fields (diag.os, diag.cpu, etc.) are available for custom formatting
  • Use the standard logSystemDiagnostics() method to emit on demand

Available Diagnostics Fields

When using custom log formats, these fields are available:

  • {diag.os} - Operating system name (windows, linux, macos)
  • {diag.arch} - Architecture (x86_64, aarch64, etc.)
  • {diag.cpu} - CPU model name
  • {diag.cores} - Number of logical cores
  • {diag.ram_total_mb} - Total RAM in megabytes
  • {diag.ram_avail_mb} - Available RAM in megabytes

Example with Custom Format

zig
var config = logly.Config.default();
config.log_format = "[{level}] {message} | CPU={diag.cpu} ({diag.cores} cores)";
config.emit_system_diagnostics_on_init = true;

const logger = try logly.Logger.initWithConfig(allocator, config);
try logger.logSystemDiagnostics(@src());

// Output:
// [INFO] [DIAGNOSTICS] os=windows arch=x86_64 cpu=rocketlake cores=16 ... | 
//   CPU=rocketlake (16 cores)

Complete Example

Here's a comprehensive example combining all customization features:

zig
const std = @import("std");
const logly = @import("logly");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var config = logly.Config.default();

    // Global root path
    config.logs_root_path = "./logs";

    // Format structure
    config.format_structure = .{
        .message_prefix = "[APP] ",
        .field_separator = " | ",
        .enable_nesting = true,
    };

    // Custom colors
    config.level_colors = .{
        .info_color = "\x1b[34m",     // Blue
        .warning_color = "\x1b[33m",  // Yellow
        .error_color = "\x1b[31m",    // Red
    };

    // Highlighters
    config.highlighters = .{
        .enabled = true,
        .alert_on_match = true,
        .log_matches = true,
    };

    // Diagnostics
    config.emit_system_diagnostics_on_init = true;

    const logger = try logly.Logger.initWithConfig(allocator, config);
    defer logger.deinit();

    // Add sinks (automatically use logs_root_path)
    _ = try logger.addSink(logly.SinkConfig.file("application.log"));
    _ = try logger.addSink(logly.SinkConfig.file("errors.log"));

    // Log messages
    try logger.info("Application started", @src());
    try logger.warning("Resource usage high", @src());
    try logger.err("Connection failed", @src());

    // Emit diagnostics
    try logger.logSystemDiagnostics(@src());
}

Combining with Other Features

All customization features work seamlessly with Logly's other capabilities:

  • Thread Pool: Customizations apply to all threaded log writes
  • Async Logging: Format customizations work with buffered output
  • Rotation: Logs are rotated within the configured root path
  • Compression: Compressed files are stored in the root path
  • Filtering: Color and format customizations apply to filtered logs
  • JSON Output: Customizations don't affect JSON structure

Performance Considerations

  • Format Structure: Minimal overhead; applies at formatting stage
  • Colors: ANSI codes add small amounts to output size
  • Highlighters: Pattern matching has O(n) complexity per message
  • Root Path: Single directory creation at logger init, no runtime overhead

Released under the MIT License.