prefect server in zig
1const std = @import("std");
2const posix = std.posix;
3
4pub const Level = enum(u8) {
5 debug = 10,
6 info = 20,
7 warning = 30,
8 err = 40,
9 critical = 50,
10
11 pub fn fromString(s: []const u8) Level {
12 if (std.ascii.eqlIgnoreCase(s, "DEBUG")) return .debug;
13 if (std.ascii.eqlIgnoreCase(s, "INFO")) return .info;
14 if (std.ascii.eqlIgnoreCase(s, "WARNING") or std.ascii.eqlIgnoreCase(s, "WARN")) return .warning;
15 if (std.ascii.eqlIgnoreCase(s, "ERROR")) return .err;
16 if (std.ascii.eqlIgnoreCase(s, "CRITICAL")) return .critical;
17 return .warning;
18 }
19
20 pub fn name(self: Level) []const u8 {
21 return switch (self) {
22 .debug => "DEBUG",
23 .info => "INFO",
24 .warning => "WARNING",
25 .err => "ERROR",
26 .critical => "CRITICAL",
27 };
28 }
29};
30
31var server_level: Level = .warning;
32
33pub fn init() void {
34 if (posix.getenv("PREFECT_SERVER_LOGGING_LEVEL")) |level_str| {
35 server_level = Level.fromString(level_str);
36 } else if (posix.getenv("PREFECT_LOGGING_LEVEL")) |level_str| {
37 server_level = Level.fromString(level_str);
38 }
39}
40
41pub fn setLevel(level: Level) void {
42 server_level = level;
43}
44
45pub fn getLevel() Level {
46 return server_level;
47}
48
49fn getTimestamp(buf: *[12]u8) []const u8 {
50 const ms_total = std.time.milliTimestamp();
51 const ms: u64 = @intCast(@mod(ms_total, 1000));
52 const epoch_secs: u64 = @intCast(@divFloor(ms_total, 1000));
53 const secs_today = epoch_secs % 86400;
54 const hours = secs_today / 3600;
55 const mins = (secs_today % 3600) / 60;
56 const secs = secs_today % 60;
57
58 return std.fmt.bufPrint(buf, "{d:0>2}:{d:0>2}:{d:0>2}.{d:0>3}", .{
59 hours, mins, secs, ms,
60 }) catch "00:00:00.000";
61}
62
63fn writeStderr(data: []const u8) void {
64 const stderr = std.fs.File.stderr();
65 stderr.writeAll(data) catch {};
66}
67
68pub fn log(level: Level, component: []const u8, comptime fmt: []const u8, args: anytype) void {
69 if (@intFromEnum(level) < @intFromEnum(server_level)) return;
70
71 var ts_buf: [12]u8 = undefined;
72 const ts = getTimestamp(&ts_buf);
73
74 var buf: [4096]u8 = undefined;
75 const len = (std.fmt.bufPrint(&buf, "{s} | {s: <8} | {s} - " ++ fmt ++ "\n", .{
76 ts,
77 level.name(),
78 component,
79 } ++ args) catch return).len;
80
81 writeStderr(buf[0..len]);
82}
83
84pub fn debug(component: []const u8, comptime fmt: []const u8, args: anytype) void {
85 log(.debug, component, fmt, args);
86}
87
88pub fn info(component: []const u8, comptime fmt: []const u8, args: anytype) void {
89 log(.info, component, fmt, args);
90}
91
92pub fn warn(component: []const u8, comptime fmt: []const u8, args: anytype) void {
93 log(.warning, component, fmt, args);
94}
95
96pub fn err(component: []const u8, comptime fmt: []const u8, args: anytype) void {
97 log(.err, component, fmt, args);
98}
99
100pub fn critical(component: []const u8, comptime fmt: []const u8, args: anytype) void {
101 log(.critical, component, fmt, args);
102}