sylveos

Toy Operating System
Log | Files | Refs

journal.zig (4193B)


      1 const std = @import("std");
      2 
      3 const mem = @import("./mem.zig");
      4 // Kinda like std.log but journaling
      5 // In the future this would use runtime formatting
      6 
      7 pub const LogLevel = enum(u8) {
      8     // "The system is probably dead"
      9     Emergency = 0,
     10     // "A problem that requires immediate attention"
     11     Alert = 1,
     12     // Something has gone wrong, possibly recoverable
     13     Error = 2,
     14     // It is uncertain if something has gone wrong or not
     15     Warning = 3,
     16     // "Normal but perhaps noteworthy"
     17     Notice = 4,
     18     // General messages
     19     Info = 5,
     20     // Messages only useful for debugging
     21     Debug = 6,
     22 
     23     pub fn text(comptime self: LogLevel) []const u8 {
     24         return switch (self) {
     25             .Emergency => "emergency",
     26             .Alert => "alert",
     27             .Error => "error",
     28             .Warning => "warning",
     29             .Notice => "notice",
     30             .Info => "info",
     31             .Debug => "debug",
     32         };
     33     }
     34 
     35     pub fn text_short(comptime self: LogLevel) u8 {
     36         return switch (self) {
     37             .Emergency => '!',
     38             .Alert => 'A',
     39             .Error => 'E',
     40             .Warning => 'W',
     41             .Notice => 'N',
     42             .Info => 'I',
     43             .Debug => 'D',
     44         };
     45     }
     46 };
     47 
     48 pub const LogWriter = struct {
     49     node: std.SinglyLinkedList.Node,
     50     writer: *std.Io.Writer,
     51 };
     52 
     53 var log_level: LogLevel = .Info;
     54 var writers: std.SinglyLinkedList = .{ .first = null };
     55 
     56 // TODO; shouldn't have static buffer
     57 var buffer: [1024 * 1024]u8 = undefined;
     58 var fba: std.heap.FixedBufferAllocator = .init(&buffer);
     59 
     60 pub inline fn set_log_level(level: LogLevel) void {
     61     log_level = level;
     62 }
     63 
     64 pub fn log(comptime level: LogLevel, comptime scope: []const u8, comptime format: []const u8, args: anytype) void {
     65     const level_txt = comptime level.text_short();
     66     const prefix = if (scope.len == 0) ": " else scope ++ ": ";
     67 
     68     const cs = mem.enter_critical_section();
     69     defer cs.exit();
     70 
     71     var head = writers.first;
     72     while (head) |writer| {
     73         const node: *LogWriter = @fieldParentPtr("node", writer);
     74 
     75         node.writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch {
     76             // TODO; queue write error
     77             continue;
     78         };
     79 
     80         head = writer.next;
     81     }
     82 }
     83 
     84 pub fn push_writer(w: *std.Io.Writer) void {
     85     var writer = try fba.allocator().create(LogWriter);
     86     writer.writer = w;
     87     writers.prepend(&writer.node);
     88 }
     89 
     90 pub fn pop_writer(w: *std.Io.Writer) void {
     91     var head = writers.first;
     92     while (head) |writer| {
     93         const node: *LogWriter = @fieldParentPtr("node", writer);
     94 
     95         if (node.writer == w) {
     96             writers.remove(node);
     97             return;
     98         }
     99 
    100         head = writer.next;
    101     }
    102 }
    103 
    104 pub fn scoped(comptime scope: []const u8) type {
    105     return struct {
    106         pub fn emergency(comptime format: []const u8, args: anytype) void {
    107             @branchHint(.cold);
    108             log(.Emergency, scope, format, args);
    109         }
    110 
    111         pub fn alert(comptime format: []const u8, args: anytype) void {
    112             @branchHint(.cold);
    113             log(.Alert, scope, format, args);
    114         }
    115 
    116         pub fn err(comptime format: []const u8, args: anytype) void {
    117             @branchHint(.cold);
    118             log(.Error, scope, format, args);
    119         }
    120 
    121         pub fn warn(comptime format: []const u8, args: anytype) void {
    122             @branchHint(.cold);
    123             log(.Warning, scope, format, args);
    124         }
    125 
    126         pub fn notice(comptime format: []const u8, args: anytype) void {
    127             @branchHint(.cold);
    128             log(.Notice, scope, format, args);
    129         }
    130 
    131         pub fn info(comptime format: []const u8, args: anytype) void {
    132             @branchHint(.cold);
    133             log(.Info, scope, format, args);
    134         }
    135 
    136         pub fn debug(comptime format: []const u8, args: anytype) void {
    137             @branchHint(.cold);
    138             log(.Debug, scope, format, args);
    139         }
    140     };
    141 }
    142 
    143 const default = scoped("");
    144 pub const emergency = default.emergency;
    145 pub const alert = default.alert;
    146 pub const err = default.err;
    147 pub const warning = default.warn;
    148 pub const notice = default.notice;
    149 pub const info = default.info;
    150 pub const debug = default.debug;