diff --git a/src/handler.zig b/src/handler.zig index 4bee291..52df428 100644 --- a/src/handler.zig +++ b/src/handler.zig @@ -4,32 +4,21 @@ const KeyValue = @import("kv.zig").KeyValue; const builtin = @import("builtin"); pub const LogHandler = struct { - pub fn levelToString(level: Level) []const u8 { - return switch (level) { - .Trace => "Trace", - .Debug => "Debug", - .Info => "Info", - .Warn => "Warn", - .Error => "Error", - .Fatal => "Fatal", - }; - } - pub fn log(_: *LogHandler, level: Level, msg: []const u8, kv: ?[]const KeyValue) !void { var buffer: [256]u8 = undefined; - const level_str = levelToString(level); + const level_str = level.toString(); if (!builtin.is_test) { try std.io.getStdOut().writer().print("{s}: {s}\n", .{ level_str, msg }); } //std.debug.print("{s}: {s}\n", .{ level_str, msg }); if (kv) |values| { for (values) |entry| { - const valueString = switch (entry.value) { + const value_string = switch (entry.value) { .String => entry.value.String, .Int => try std.fmt.bufPrint(&buffer, "{}", .{entry.value.Int}), .Float => try std.fmt.bufPrint(&buffer, "{}", .{entry.value.Float}), }; - std.debug.print("{s}={s}\n", .{ entry.key, valueString }); + std.debug.print("{s}={s}\n", .{ entry.key, value_string }); } } } @@ -39,11 +28,11 @@ pub const FileHandler = struct { // ... file-specific fields ... pub fn log(_: *FileHandler, _: Level, _: []const u8, _: ?[]const KeyValue) !void { - return error.NotImplemented; + @compileError("not implemented"); } pub fn rotate(_: *FileHandler) !void { - return error.NotImplemented; + @compileError("not implemented"); } }; @@ -51,7 +40,7 @@ pub const NetworkHandler = struct { // ... network-specific fields ... pub fn log(_: *NetworkHandler, _: Level, _: []const u8, _: ?[]const KeyValue) !void { - return error.NotImplemented; + @compileError("not implemented"); } }; @@ -60,6 +49,6 @@ pub const AsyncLogHandler = struct { pub fn log(_: *AsyncLogHandler, _: Level, _: []const u8, _: ?[]const KeyValue) !void { // ... enqueue log message for processing by a separate worker thread ... - return error.NotImplemented; + @compileError("not implemented"); } }; diff --git a/src/json.zig b/src/json.zig index 88b37b4..bade8b3 100644 --- a/src/json.zig +++ b/src/json.zig @@ -4,41 +4,29 @@ const Level = @import("level.zig").Level; const kv = @import("kv.zig"); fn appendFormattedInt(buffer: *std.ArrayList(u8), value: i64) !void { - var tmpBuf: [20]u8 = undefined; // Buffer for integer formatting - const formatted = try std.fmt.bufPrint(&tmpBuf, "{}", .{value}); + var tmp_buf: [20]u8 = undefined; // Buffer for integer formatting + const formatted = try std.fmt.bufPrint(&tmp_buf, "{}", .{value}); try buffer.appendSlice(formatted); } fn appendFormattedFloat(buffer: *std.ArrayList(u8), value: f64) !void { - var tmpBuf: [32]u8 = undefined; // Buffer for float formatting - const formatted = try std.fmt.bufPrint(&tmpBuf, "{d:.2}", .{value}); + var tmp_buf: [32]u8 = undefined; // Buffer for float formatting + const formatted = try std.fmt.bufPrint(&tmp_buf, "{d:.2}", .{value}); try buffer.appendSlice(formatted); } -fn appendLevel(buffer: *std.ArrayList(u8), level: Level) !void { - const levelStr = switch (level) { - .Info => "Info", - .Warn => "Warn", - .Error => "Error", - .Debug => "Debug", - .Trace => "Trace", - .Fatal => "Fatal", // Handling the 'Fatal' case - }; - try buffer.appendSlice(levelStr); -} - pub fn serializeLogMessage(log: LogMessage) ![]u8 { var buffer = std.ArrayList(u8).init(std.heap.page_allocator); defer buffer.deinit(); try buffer.appendSlice("{\"level\": \""); - try appendLevel(&buffer, log.level); + try buffer.appendSlice(log.level.toString()); try buffer.appendSlice("\", \"message\": \""); try buffer.appendSlice(log.msg); try buffer.appendSlice("\""); - if (log.kv) |kvPairs| { - for (kvPairs) |pair| { + if (log.kv) |kv_pairs| { + for (kv_pairs) |pair| { try buffer.appendSlice(", \""); try buffer.appendSlice(pair.key); try buffer.appendSlice("\": "); @@ -60,7 +48,7 @@ pub fn serializeLogMessage(log: LogMessage) ![]u8 { } test "JSON Serialization Test - Level and Message" { - const logMsg = LogMessage{ + const log_msg = LogMessage{ .level = Level.Info, .msg = "Test message", .kv = &[_]kv.KeyValue{ @@ -71,7 +59,7 @@ test "JSON Serialization Test - Level and Message" { }, }; - const serializedMsg = try serializeLogMessage(logMsg); + const serialized_msg = try serializeLogMessage(log_msg); - try std.testing.expectEqualStrings("{\"level\": \"Info\", \"message\": \"Test message\", \"key1\": \"value1\", \"key2\": 42, \"key3\": 3.14}", serializedMsg); + try std.testing.expectEqualStrings("{\"level\": \"Info\", \"message\": \"Test message\", \"key1\": \"value1\", \"key2\": 42, \"key3\": 3.14}", serialized_msg); } diff --git a/src/level.zig b/src/level.zig index f11b9cc..3af1a41 100644 --- a/src/level.zig +++ b/src/level.zig @@ -5,4 +5,8 @@ pub const Level = enum { Warn, Error, Fatal, + + pub fn toString(self: Level) []const u8 { + return @tagName(self); + } }; diff --git a/src/logger.zig b/src/logger.zig index 5daef9f..30ae6d5 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -15,73 +15,72 @@ pub const LogRecord = struct { pub fn Logger(comptime HandlerType: type) type { return struct { level: Level, - outputFormat: OutputFormat, + output_format: OutputFormat, handler: *HandlerType, // Ensure this is a pointer - pub fn init(_: *std.mem.Allocator, level: Level, outputFormat: OutputFormat, handler: *HandlerType) ZlogError!Logger(HandlerType) { - return Logger(HandlerType){ + const Self = @This(); + + pub fn init(_: *std.mem.Allocator, level: Level, outputFormat: OutputFormat, handler: *HandlerType) ZlogError!Self { + return Self{ .level = level, - .outputFormat = outputFormat, + .output_format = outputFormat, .handler = handler, // Store the pointer directly }; } - pub fn setLevel(self: *Logger(HandlerType), newLevel: Level) ZlogError!void { - if (!std.meta.enumsHaveMember(Level, newLevel)) { - return error.InvalidLevel; - } - self.level = newLevel; + pub fn setLevel(self: *Self, new_level: Level) ZlogError!void { + self.level = new_level; return self; } - pub fn info(self: *Logger(HandlerType), msg: []const u8, kv: ?[]const KeyValue) void { - self.log(msg, kv) catch |logErr| { - std.debug.print("Log error: {}\n", .{logErr}); + pub fn info(self: *Self, msg: []const u8, kv: ?[]const KeyValue) void { + self.log(msg, kv) catch |log_err| { + std.debug.print("Log error: {}\n", .{log_err}); return; }; } - pub fn warn(self: *Logger(HandlerType), msg: []const u8, kv: ?[]const KeyValue) void { - self.log(msg, kv) catch |logErr| { - std.debug.print("Log error: {}\n", .{logErr}); + pub fn warn(self: *Self, msg: []const u8, kv: ?[]const KeyValue) void { + self.log(msg, kv) catch |log_err| { + std.debug.print("Log error: {}\n", .{log_err}); return; }; } - pub fn err(self: *Logger(HandlerType), msg: []const u8, kv: ?[]const KeyValue) void { - self.log(msg, kv) catch |logErr| { - std.debug.print("Log error: {}\n", .{logErr}); + pub fn err(self: *Self, msg: []const u8, kv: ?[]const KeyValue) void { + self.log(msg, kv) catch |log_err| { + std.debug.print("Log error: {}\n", .{log_err}); return; }; } - pub fn debug(self: *Logger(HandlerType), msg: []const u8, kv: ?[]const KeyValue) void { - self.log(msg, kv) catch |logErr| { - std.debug.print("Log error: {}\n", .{logErr}); + pub fn debug(self: *Self, msg: []const u8, kv: ?[]const KeyValue) void { + self.log(msg, kv) catch |log_err| { + std.debug.print("Log error: {}\n", .{log_err}); return; }; } - pub fn trace(self: *Logger(HandlerType), msg: []const u8, kv: ?[]const KeyValue) void { - self.log(msg, kv) catch |logErr| { - std.debug.print("Log error: {}\n", .{logErr}); + pub fn trace(self: *Self, msg: []const u8, kv: ?[]const KeyValue) void { + self.log(msg, kv) catch |log_err| { + std.debug.print("Log error: {}\n", .{log_err}); return; }; } - pub fn log(self: *Logger(HandlerType), msg: []const u8, kv: ?[]const KeyValue) anyerror!void { + pub fn log(self: *Self, msg: []const u8, kv: ?[]const KeyValue) anyerror!void { // Debug print to show the handler's address //std.debug.print("Logger: Logging with Logger instance at address {}\n", .{@intFromPtr(self)}); // Updated line - if (self.outputFormat == OutputFormat.JSON) { - const logMsg = LogRecord{ .level = self.level, .msg = msg, .kv = kv }; - const serializedMsg = json.serializeLogMessage(logMsg) catch |JsonErr| { - std.debug.print("Error serializing log message: {}\n", .{JsonErr}); + if (self.output_format == OutputFormat.JSON) { + const log_msg = LogRecord{ .level = self.level, .msg = msg, .kv = kv }; + const serialized_msg = json.serializeLogMessage(log_msg) catch |json_err| { + std.debug.print("Error serializing log message: {}\n", .{json_err}); return error.HandlerFailure; }; // Pass the serialized message slice directly - try self.handler.log(self.level, serializedMsg, null); + try self.handler.log(self.level, serialized_msg, null); } else { // Handle non-JSON formats as before if (kv) |keyValues| { diff --git a/src/test.zig b/src/test.zig index eb713ab..794d6db 100644 --- a/src/test.zig +++ b/src/test.zig @@ -6,13 +6,14 @@ const LogHandler = @import("handler.zig").LogHandler; const kv = @import("kv.zig"); const OutputFormat = @import("logger.zig").OutputFormat; -var globalAllocator = std.heap.page_allocator; +var global_allocator = std.heap.page_allocator; -fn setupLogger(comptime HandlerType: type, logLevel: Level, format: OutputFormat, handler: *HandlerType) !Logger(HandlerType) { - return Logger(HandlerType).init(&globalAllocator, logLevel, format, handler); +fn setupLogger(comptime HandlerType: type, log_level: Level, format: OutputFormat, handler: *HandlerType) !Logger(HandlerType) { + return Logger(HandlerType).init(&global_allocator, log_level, format, handler); } test "Benchmark different log levels" { + // do wyp p p var handler = LogHandler{}; var logger = try setupLogger(LogHandler, Level.Info, OutputFormat.PlainText, &handler); @@ -28,25 +29,25 @@ test "Benchmark Synchronous vs Asynchronous Logging" { var logger = try setupLogger(LogHandler, Level.Error, OutputFormat.PlainText, &handler); // Synchronous Logging - const startSync = std.time.milliTimestamp(); + const start_sync = std.time.milliTimestamp(); logger.info("Synchronous log message", null); - const endSync = std.time.milliTimestamp(); + const end_sync = std.time.milliTimestamp(); // Asynchronous Logging - const startAsync = std.time.milliTimestamp(); + const start_async = std.time.milliTimestamp(); //logger.asyncLog("Asynchronous log message"); - const endAsync = std.time.milliTimestamp(); + const end_async = std.time.milliTimestamp(); - std.debug.print("Synchronous Logging took {} ms\n", .{endSync - startSync}); - std.debug.print("Not Implemented - Asynchronous Logging took {} ms\n", .{endAsync - startAsync}); + std.debug.print("Synchronous Logging took {} ms\n", .{end_sync - start_sync}); + std.debug.print("Not Implemented - Asynchronous Logging took {} ms\n", .{end_async - start_async}); } const MockLogHandler = struct { - capturedOutput: std.ArrayList(u8), + captured_output: std.ArrayList(u8), pub fn log(self: *MockLogHandler, _: Level, msg: []const u8, _: ?[]const kv.KeyValue) anyerror!void { //std.debug.print("Before appending, capturedOutput length: {}\n", .{self.capturedOutput.items.len}); - try self.capturedOutput.appendSlice(msg); + try self.captured_output.appendSlice(msg); //std.debug.print("After appending, capturedOutput length: {}\n", .{self.capturedOutput.items.len}); //std.debug.print("Captured message: {s}\n", .{msg}); } @@ -54,28 +55,28 @@ const MockLogHandler = struct { test "JSON Logging Test" { var allocator = std.heap.page_allocator; - var mockHandler = MockLogHandler{ .capturedOutput = std.ArrayList(u8).init(allocator) }; - defer mockHandler.capturedOutput.deinit(); + var mock_handler = MockLogHandler{ .captured_output = std.ArrayList(u8).init(allocator) }; + defer mock_handler.captured_output.deinit(); //std.debug.print("Test: Created MockLogHandler at address {}\n", .{@intFromPtr(&mockHandler)}); // Debug print - var logger = try Logger(MockLogHandler).init(&allocator, Level.Info, OutputFormat.JSON, &mockHandler); + var logger = try Logger(MockLogHandler).init(&allocator, Level.Info, OutputFormat.JSON, &mock_handler); //std.debug.print("Test: Created Logger at address {}\n", .{@intFromPtr(&logger)}); // Debug print - const kvPairs = &[_]kv.KeyValue{ + const kv_pairs = &.{ kv.KeyValue{ .key = "key1", .value = kv.Value{ .String = "value1" } }, kv.KeyValue{ .key = "key2", .value = kv.Value{ .Int = 42 } }, kv.KeyValue{ .key = "key3", .value = kv.Value{ .Float = 3.14 } }, }; - logger.info("Test message", kvPairs); + logger.info("Test message", kv_pairs); //std.debug.print("MockLogHandler: capturedOutput length = {}\n", .{mockHandler.capturedOutput.items.len}); // Debug print - const loggedJson = mockHandler.capturedOutput.items; + const logged_json = mock_handler.captured_output.items; //std.debug.print("MockLogHandler: loggedJson = {s}\n", .{loggedJson}); // Debug line - try std.testing.expectEqualStrings("{\"level\": \"Info\", \"message\": \"Test message\", \"key1\": \"value1\", \"key2\": 42, \"key3\": 3.14}", loggedJson); + try std.testing.expectEqualStrings("{\"level\": \"Info\", \"message\": \"Test message\", \"key1\": \"value1\", \"key2\": 42, \"key3\": 3.14}", logged_json); } pub fn main() !void {}