const std = @import("std"); const posix = std.posix; pub const Level = enum(u8) { debug = 10, info = 20, warning = 30, err = 40, critical = 50, pub fn fromString(s: []const u8) Level { if (std.ascii.eqlIgnoreCase(s, "DEBUG")) return .debug; if (std.ascii.eqlIgnoreCase(s, "INFO")) return .info; if (std.ascii.eqlIgnoreCase(s, "WARNING") or std.ascii.eqlIgnoreCase(s, "WARN")) return .warning; if (std.ascii.eqlIgnoreCase(s, "ERROR")) return .err; if (std.ascii.eqlIgnoreCase(s, "CRITICAL")) return .critical; return .warning; } pub fn name(self: Level) []const u8 { return switch (self) { .debug => "DEBUG", .info => "INFO", .warning => "WARNING", .err => "ERROR", .critical => "CRITICAL", }; } }; var server_level: Level = .warning; pub fn init() void { if (posix.getenv("PREFECT_SERVER_LOGGING_LEVEL")) |level_str| { server_level = Level.fromString(level_str); } else if (posix.getenv("PREFECT_LOGGING_LEVEL")) |level_str| { server_level = Level.fromString(level_str); } } pub fn setLevel(level: Level) void { server_level = level; } pub fn getLevel() Level { return server_level; } fn getTimestamp(buf: *[12]u8) []const u8 { const ms_total = std.time.milliTimestamp(); const ms: u64 = @intCast(@mod(ms_total, 1000)); const epoch_secs: u64 = @intCast(@divFloor(ms_total, 1000)); const secs_today = epoch_secs % 86400; const hours = secs_today / 3600; const mins = (secs_today % 3600) / 60; const secs = secs_today % 60; return std.fmt.bufPrint(buf, "{d:0>2}:{d:0>2}:{d:0>2}.{d:0>3}", .{ hours, mins, secs, ms, }) catch "00:00:00.000"; } fn writeStderr(data: []const u8) void { const stderr = std.fs.File.stderr(); stderr.writeAll(data) catch {}; } pub fn log(level: Level, component: []const u8, comptime fmt: []const u8, args: anytype) void { if (@intFromEnum(level) < @intFromEnum(server_level)) return; var ts_buf: [12]u8 = undefined; const ts = getTimestamp(&ts_buf); var buf: [4096]u8 = undefined; const len = (std.fmt.bufPrint(&buf, "{s} | {s: <8} | {s} - " ++ fmt ++ "\n", .{ ts, level.name(), component, } ++ args) catch return).len; writeStderr(buf[0..len]); } pub fn debug(component: []const u8, comptime fmt: []const u8, args: anytype) void { log(.debug, component, fmt, args); } pub fn info(component: []const u8, comptime fmt: []const u8, args: anytype) void { log(.info, component, fmt, args); } pub fn warn(component: []const u8, comptime fmt: []const u8, args: anytype) void { log(.warning, component, fmt, args); } pub fn err(component: []const u8, comptime fmt: []const u8, args: anytype) void { log(.err, component, fmt, args); } pub fn critical(component: []const u8, comptime fmt: []const u8, args: anytype) void { log(.critical, component, fmt, args); }