This commit is contained in:
Bob Farrell 2024-05-09 21:30:11 +01:00
parent 63b4265131
commit b39653b90f
5 changed files with 61 additions and 37 deletions

View File

@ -101,15 +101,16 @@ pub fn runtimeWhite(allocator: std.mem.Allocator, message: []const u8) ![]const
return try runtimeWrap(allocator, codes.white, message); return try runtimeWrap(allocator, codes.white, message);
} }
pub fn duration(allocator: std.mem.Allocator, delta: i64) ![]const u8 { pub fn duration(buf: *[256]u8, delta: i64) ![]const u8 {
var buf: [1024]u8 = undefined; const code = if (delta < 1000000)
const formatted_duration = try std.fmt.bufPrint(&buf, "{}", .{std.fmt.fmtDurationSigned(delta)}); codes.green
else if (delta < 5000000)
if (delta < 1000000) { codes.yellow
return try runtimeGreen(allocator, formatted_duration); else
} else if (delta < 5000000) { codes.red;
return try runtimeYellow(allocator, formatted_duration); return try std.fmt.bufPrint(
} else { buf,
return try runtimeRed(allocator, formatted_duration); "{s}{s}m{}{s}{s}m",
} .{ codes.escape, code, std.fmt.fmtDurationSigned(delta), codes.escape, codes.reset },
);
} }

View File

@ -22,9 +22,9 @@ pub fn init(
return .{ return .{
.allocator = allocator, .allocator = allocator,
.level = level, .level = level,
.log_queue = log_queue, .log_queue = log_queue, // TODO: stdout/stderr queues
.stdout_colorized = true, // TODO .stdout_colorized = log_queue.is_tty,
.stderr_colorized = true, // TODO .stderr_colorized = log_queue.is_tty,
}; };
} }
@ -40,9 +40,9 @@ pub fn log(
const output = try std.fmt.allocPrint(self.allocator, message, args); const output = try std.fmt.allocPrint(self.allocator, message, args);
defer self.allocator.free(output); defer self.allocator.free(output);
const timestamp = Timestamp.init(std.time.timestamp(), self.allocator); const timestamp = Timestamp.init(std.time.timestamp());
const iso8601 = try timestamp.iso8601(); var timestamp_buf: [256]u8 = undefined;
defer self.allocator.free(iso8601); const iso8601 = try timestamp.iso8601(&timestamp_buf);
const colorized = switch (level) { const colorized = switch (level) {
.TRACE, .DEBUG, .INFO => self.stdout_colorized, .TRACE, .DEBUG, .INFO => self.stdout_colorized,
@ -59,15 +59,15 @@ pub fn log(
/// Log a one-liner including response status code, path, method, duration, etc. /// Log a one-liner including response status code, path, method, duration, etc.
pub fn logRequest(self: DevelopmentLogger, request: *const jetzig.http.Request) !void { pub fn logRequest(self: DevelopmentLogger, request: *const jetzig.http.Request) !void {
var duration_buf: [256]u8 = undefined;
const formatted_duration = if (self.stdout_colorized) const formatted_duration = if (self.stdout_colorized)
try jetzig.colors.duration(self.allocator, jetzig.util.duration(request.start_time)) try jetzig.colors.duration(&duration_buf, jetzig.util.duration(request.start_time))
else else
try std.fmt.allocPrint( try std.fmt.bufPrint(
self.allocator, &duration_buf,
"{}", "{}",
.{std.fmt.fmtDurationSigned(jetzig.util.duration(request.start_time))}, .{std.fmt.fmtDurationSigned(jetzig.util.duration(request.start_time))},
); );
defer self.allocator.free(formatted_duration);
const status: jetzig.http.status_codes.TaggedStatusCode = switch (request.response.status_code) { const status: jetzig.http.status_codes.TaggedStatusCode = switch (request.response.status_code) {
inline else => |status_code| @unionInit( inline else => |status_code| @unionInit(
@ -82,14 +82,19 @@ pub fn logRequest(self: DevelopmentLogger, request: *const jetzig.http.Request)
else else
status.getFormatted(.{}); status.getFormatted(.{});
const message = try std.fmt.allocPrint(self.allocator, "[{s}/{s}/{s}] {s}", .{ const timestamp = Timestamp.init(std.time.timestamp());
var timestamp_buf: [256]u8 = undefined;
const iso8601 = try timestamp.iso8601(&timestamp_buf);
const writer = self.log_queue.writer;
try writer.print("{s: >5} [{s}] [{s}/{s}/{s}] {s}\n", .{
if (self.stdout_colorized) colorizedLogLevel(.INFO) else @tagName(.INFO),
iso8601,
formatted_duration, formatted_duration,
request.fmtMethod(self.stdout_colorized), request.fmtMethod(self.stdout_colorized),
formatted_status, formatted_status,
request.path.path, request.path.path,
}); });
defer self.allocator.free(message);
try self.log(.INFO, "{s}", .{message});
} }
fn colorizedLogLevel(comptime level: LogLevel) []const u8 { fn colorizedLogLevel(comptime level: LogLevel) []const u8 {

View File

@ -54,9 +54,9 @@ pub fn log(
const output = try std.fmt.allocPrint(self.allocator, message, args); const output = try std.fmt.allocPrint(self.allocator, message, args);
defer self.allocator.free(output); defer self.allocator.free(output);
const timestamp = Timestamp.init(std.time.timestamp(), self.allocator); const timestamp = Timestamp.init(std.time.timestamp());
const iso8601 = try timestamp.iso8601(); var timestamp_buf: [256]u8 = undefined;
defer self.allocator.free(iso8601); const iso8601 = try timestamp.iso8601(&timestamp_buf);
const file = self.getFile(level); const file = self.getFile(level);
const writer = file.writer(); const writer = file.writer();
@ -80,9 +80,9 @@ pub fn logRequest(self: *const JsonLogger, request: *const jetzig.http.Request)
const duration = jetzig.util.duration(request.start_time); const duration = jetzig.util.duration(request.start_time);
const timestamp = Timestamp.init(std.time.timestamp(), self.allocator); const timestamp = Timestamp.init(std.time.timestamp());
const iso8601 = try timestamp.iso8601(); var timestamp_buf: [256]u8 = undefined;
defer self.allocator.free(iso8601); const iso8601 = try timestamp.iso8601(&timestamp_buf);
const status = switch (request.response.status_code) { const status = switch (request.response.status_code) {
inline else => |status_code| @unionInit( inline else => |status_code| @unionInit(

View File

@ -8,6 +8,9 @@ condition: *std.Thread.Condition,
condition_mutex: *std.Thread.Mutex, condition_mutex: *std.Thread.Mutex,
writer: *Writer = undefined, writer: *Writer = undefined,
reader: *Reader = undefined, reader: *Reader = undefined,
pool: std.ArrayList(*List.Node),
position: usize,
is_tty: bool = undefined,
const LogQueue = @This(); const LogQueue = @This();
@ -21,6 +24,8 @@ pub fn init(allocator: std.mem.Allocator) !LogQueue {
.condition = try allocator.create(std.Thread.Condition), .condition = try allocator.create(std.Thread.Condition),
.condition_mutex = try allocator.create(std.Thread.Mutex), .condition_mutex = try allocator.create(std.Thread.Mutex),
.read_write_mutex = try allocator.create(std.Thread.Mutex), .read_write_mutex = try allocator.create(std.Thread.Mutex),
.pool = std.ArrayList(*List.Node).init(allocator),
.position = 0,
}; };
} }
@ -29,6 +34,7 @@ pub fn setFile(self: *LogQueue, file: std.fs.File) !void {
self.writer.* = Writer{ .file = file, .queue = self }; self.writer.* = Writer{ .file = file, .queue = self };
self.reader = try self.allocator.create(Reader); self.reader = try self.allocator.create(Reader);
self.reader.* = Reader{ .file = file, .queue = self }; self.reader.* = Reader{ .file = file, .queue = self };
self.is_tty = file.isTty();
} }
pub const Writer = struct { pub const Writer = struct {
@ -71,9 +77,17 @@ pub fn append(self: *LogQueue, message: []const u8) !void {
self.read_write_mutex.lock(); self.read_write_mutex.lock();
defer self.read_write_mutex.unlock(); defer self.read_write_mutex.unlock();
const node = try self.allocator.create(List.Node); const node = if (self.position >= self.pool.items.len) blk: {
self.position += 1;
break :blk try self.allocator.create(List.Node);
} else blk: {
self.position += 1;
break :blk self.pool.items[self.position - 1];
};
node.* = .{ .data = message }; node.* = .{ .data = message };
self.list.append(node); self.list.append(node);
self.condition.signal(); self.condition.signal();
} }
@ -83,7 +97,12 @@ pub fn popFirst(self: *LogQueue) !?[]const u8 {
if (self.list.popFirst()) |node| { if (self.list.popFirst()) |node| {
const value = node.data; const value = node.data;
self.allocator.destroy(node); self.position -= 1;
if (self.position < self.pool.items.len) {
self.pool.items[self.position] = node;
} else {
try self.pool.append(node);
}
return value; return value;
} else { } else {
return null; return null;

View File

@ -3,7 +3,6 @@ const std = @import("std");
const Self = @This(); const Self = @This();
timestamp: i64, timestamp: i64,
allocator: std.mem.Allocator,
const constants = struct { const constants = struct {
pub const seconds_in_day: i64 = 60 * 60 * 24; pub const seconds_in_day: i64 = 60 * 60 * 24;
@ -12,18 +11,18 @@ const constants = struct {
pub const epoch_year: i64 = 1970; pub const epoch_year: i64 = 1970;
}; };
pub fn init(timestamp: i64, allocator: std.mem.Allocator) Self { pub fn init(timestamp: i64) Self {
return .{ .allocator = allocator, .timestamp = timestamp }; return .{ .timestamp = timestamp };
} }
pub fn iso8601(self: *const Self) ![]const u8 { pub fn iso8601(self: *const Self, buf: *[256]u8) ![]const u8 {
const u32_year: u32 = @intCast(self.year()); const u32_year: u32 = @intCast(self.year());
const u32_month: u32 = @intCast(self.month()); const u32_month: u32 = @intCast(self.month());
const u32_day_of_month: u32 = @intCast(self.dayOfMonth()); const u32_day_of_month: u32 = @intCast(self.dayOfMonth());
const u32_hour: u32 = @intCast(self.hour()); const u32_hour: u32 = @intCast(self.hour());
const u32_minute: u32 = @intCast(self.minute()); const u32_minute: u32 = @intCast(self.minute());
const u32_second: u32 = @intCast(self.second()); const u32_second: u32 = @intCast(self.second());
return try std.fmt.allocPrint(self.allocator, "{d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2}", .{ return try std.fmt.bufPrint(buf, "{d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2}", .{
u32_year, u32_year,
u32_month, u32_month,
u32_day_of_month, u32_day_of_month,