mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-15 06:26:07 +00:00
WIP
This commit is contained in:
parent
6575add452
commit
0ff19d5d26
@ -75,10 +75,20 @@ pub fn start(self: App, routes_module: type, options: AppOptions) !void {
|
|||||||
);
|
);
|
||||||
defer cache.deinit();
|
defer cache.deinit();
|
||||||
|
|
||||||
const server_options = try self.environment.getServerOptions();
|
var log_queue = try jetzig.loggers.LogQueue.init(self.allocator);
|
||||||
|
try log_queue.setFile(std.io.getStdOut());
|
||||||
|
|
||||||
|
const server_options = try self.environment.getServerOptions(&log_queue);
|
||||||
defer self.allocator.free(server_options.bind);
|
defer self.allocator.free(server_options.bind);
|
||||||
defer self.allocator.free(server_options.secret);
|
defer self.allocator.free(server_options.secret);
|
||||||
|
|
||||||
|
var log_thread = try std.Thread.spawn(
|
||||||
|
.{ .allocator = self.allocator },
|
||||||
|
jetzig.loggers.LogQueue.Reader.publish,
|
||||||
|
.{log_queue.reader},
|
||||||
|
);
|
||||||
|
defer log_thread.join();
|
||||||
|
|
||||||
if (server_options.detach) {
|
if (server_options.detach) {
|
||||||
const argv = try std.process.argsAlloc(self.allocator);
|
const argv = try std.process.argsAlloc(self.allocator);
|
||||||
defer std.process.argsFree(self.allocator, argv);
|
defer std.process.argsFree(self.allocator, argv);
|
||||||
|
@ -59,7 +59,10 @@ pub fn init(allocator: std.mem.Allocator) Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generate server initialization options using command line args with defaults.
|
/// Generate server initialization options using command line args with defaults.
|
||||||
pub fn getServerOptions(self: Environment) !jetzig.http.Server.ServerOptions {
|
pub fn getServerOptions(
|
||||||
|
self: Environment,
|
||||||
|
log_queue: *jetzig.loggers.LogQueue,
|
||||||
|
) !jetzig.http.Server.ServerOptions {
|
||||||
const options = try args.parseForCurrentProcess(Options, self.allocator, .print);
|
const options = try args.parseForCurrentProcess(Options, self.allocator, .print);
|
||||||
defer options.deinit();
|
defer options.deinit();
|
||||||
|
|
||||||
@ -72,22 +75,24 @@ pub fn getServerOptions(self: Environment) !jetzig.http.Server.ServerOptions {
|
|||||||
const environment = options.options.environment;
|
const environment = options.options.environment;
|
||||||
|
|
||||||
var logger = switch (options.options.@"log-format") {
|
var logger = switch (options.options.@"log-format") {
|
||||||
.development => jetzig.loggers.Logger{
|
.development, .json => jetzig.loggers.Logger{
|
||||||
.development_logger = jetzig.loggers.DevelopmentLogger.init(
|
.development_logger = jetzig.loggers.DevelopmentLogger.init(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
resolveLogLevel(options.options.@"log-level", environment),
|
resolveLogLevel(options.options.@"log-level", environment),
|
||||||
try getLogFile(.stdout, options.options),
|
log_queue,
|
||||||
try getLogFile(.stderr, options.options),
|
// try getLogFile(.stdout, options.options),
|
||||||
),
|
// try getLogFile(.stderr, options.options),
|
||||||
},
|
|
||||||
.json => jetzig.loggers.Logger{
|
|
||||||
.json_logger = jetzig.loggers.JsonLogger.init(
|
|
||||||
self.allocator,
|
|
||||||
resolveLogLevel(options.options.@"log-level", environment),
|
|
||||||
try getLogFile(.stdout, options.options),
|
|
||||||
try getLogFile(.stderr, options.options),
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
// TODO
|
||||||
|
// .json => jetzig.loggers.Logger{
|
||||||
|
// .json_logger = jetzig.loggers.JsonLogger.init(
|
||||||
|
// self.allocator,
|
||||||
|
// resolveLogLevel(options.options.@"log-level", environment),
|
||||||
|
// try getLogFile(.stdout, options.options),
|
||||||
|
// try getLogFile(.stderr, options.options),
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.options.detach and std.mem.eql(u8, options.options.log, "-")) {
|
if (options.options.detach and std.mem.eql(u8, options.options.log, "-")) {
|
||||||
|
@ -6,6 +6,7 @@ const Self = @This();
|
|||||||
|
|
||||||
pub const DevelopmentLogger = @import("loggers/DevelopmentLogger.zig");
|
pub const DevelopmentLogger = @import("loggers/DevelopmentLogger.zig");
|
||||||
pub const JsonLogger = @import("loggers/JsonLogger.zig");
|
pub const JsonLogger = @import("loggers/JsonLogger.zig");
|
||||||
|
pub const LogQueue = @import("loggers/LogQueue.zig");
|
||||||
|
|
||||||
pub const LogLevel = enum(u4) { TRACE, DEBUG, INFO, WARN, ERROR, FATAL };
|
pub const LogLevel = enum(u4) { TRACE, DEBUG, INFO, WARN, ERROR, FATAL };
|
||||||
pub const LogFormat = enum { development, json };
|
pub const LogFormat = enum { development, json };
|
||||||
|
@ -8,28 +8,23 @@ const Timestamp = jetzig.types.Timestamp;
|
|||||||
const LogLevel = jetzig.loggers.LogLevel;
|
const LogLevel = jetzig.loggers.LogLevel;
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
stdout: std.fs.File,
|
|
||||||
stderr: std.fs.File,
|
|
||||||
stdout_colorized: bool,
|
stdout_colorized: bool,
|
||||||
stderr_colorized: bool,
|
stderr_colorized: bool,
|
||||||
level: LogLevel,
|
level: LogLevel,
|
||||||
mutex: std.Thread.Mutex,
|
log_queue: *jetzig.loggers.LogQueue,
|
||||||
|
|
||||||
/// Initialize a new Development Logger.
|
/// Initialize a new Development Logger.
|
||||||
pub fn init(
|
pub fn init(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
level: LogLevel,
|
level: LogLevel,
|
||||||
stdout: std.fs.File,
|
log_queue: *jetzig.loggers.LogQueue,
|
||||||
stderr: std.fs.File,
|
|
||||||
) DevelopmentLogger {
|
) DevelopmentLogger {
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.level = level,
|
.level = level,
|
||||||
.stdout = stdout,
|
.log_queue = log_queue,
|
||||||
.stderr = stderr,
|
.stdout_colorized = true, // TODO
|
||||||
.stdout_colorized = stdout.isTty(),
|
.stderr_colorized = true, // TODO
|
||||||
.stderr_colorized = stderr.isTty(),
|
|
||||||
.mutex = std.Thread.Mutex{},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,19 +48,13 @@ pub fn log(
|
|||||||
.TRACE, .DEBUG, .INFO => self.stdout_colorized,
|
.TRACE, .DEBUG, .INFO => self.stdout_colorized,
|
||||||
.WARN, .ERROR, .FATAL => self.stderr_colorized,
|
.WARN, .ERROR, .FATAL => self.stderr_colorized,
|
||||||
};
|
};
|
||||||
const file = switch (level) {
|
const writer = switch (level) {
|
||||||
.TRACE, .DEBUG, .INFO => self.stdout,
|
.TRACE, .DEBUG, .INFO => self.log_queue.writer,
|
||||||
.WARN, .ERROR, .FATAL => self.stderr,
|
.WARN, .ERROR, .FATAL => self.log_queue.writer,
|
||||||
};
|
};
|
||||||
const writer = file.writer();
|
|
||||||
const level_formatted = if (colorized) colorizedLogLevel(level) else @tagName(level);
|
const level_formatted = if (colorized) colorizedLogLevel(level) else @tagName(level);
|
||||||
|
|
||||||
@constCast(self).mutex.lock();
|
|
||||||
defer @constCast(self).mutex.unlock();
|
|
||||||
|
|
||||||
try writer.print("{s: >5} [{s}] {s}\n", .{ level_formatted, iso8601, output });
|
try writer.print("{s: >5} [{s}] {s}\n", .{ level_formatted, iso8601, output });
|
||||||
|
|
||||||
if (!file.isTty()) try file.sync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Log a one-liner including response status code, path, method, duration, etc.
|
/// Log a one-liner including response status code, path, method, duration, etc.
|
||||||
|
92
src/jetzig/loggers/LogQueue.zig
Normal file
92
src/jetzig/loggers/LogQueue.zig
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const List = std.DoublyLinkedList([]const u8);
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
list: *List,
|
||||||
|
read_write_mutex: *std.Thread.Mutex,
|
||||||
|
condition: *std.Thread.Condition,
|
||||||
|
condition_mutex: *std.Thread.Mutex,
|
||||||
|
writer: *Writer = undefined,
|
||||||
|
reader: *Reader = undefined,
|
||||||
|
|
||||||
|
const LogQueue = @This();
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator) !LogQueue {
|
||||||
|
const list = try allocator.create(std.DoublyLinkedList([]const u8));
|
||||||
|
list.* = .{};
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.allocator = allocator,
|
||||||
|
.list = list,
|
||||||
|
.condition = try allocator.create(std.Thread.Condition),
|
||||||
|
.condition_mutex = try allocator.create(std.Thread.Mutex),
|
||||||
|
.read_write_mutex = try allocator.create(std.Thread.Mutex),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setFile(self: *LogQueue, file: std.fs.File) !void {
|
||||||
|
self.writer = try self.allocator.create(Writer);
|
||||||
|
self.writer.* = Writer{ .file = file, .queue = self };
|
||||||
|
self.reader = try self.allocator.create(Reader);
|
||||||
|
self.reader.* = Reader{ .file = file, .queue = self };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Writer = struct {
|
||||||
|
file: std.fs.File,
|
||||||
|
queue: *LogQueue,
|
||||||
|
|
||||||
|
pub fn isTty(self: Writer) bool {
|
||||||
|
return self.file.isTty();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(self: *Writer, comptime message: []const u8, args: anytype) !void {
|
||||||
|
const output = try std.fmt.allocPrint(self.queue.allocator, message, args);
|
||||||
|
defer self.queue.allocator.free(output);
|
||||||
|
try self.queue.append(output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Reader = struct {
|
||||||
|
file: std.fs.File,
|
||||||
|
queue: *LogQueue,
|
||||||
|
|
||||||
|
pub fn publish(self: *Reader) !void {
|
||||||
|
const writer = self.file.writer();
|
||||||
|
while (true) {
|
||||||
|
self.queue.condition_mutex.lock();
|
||||||
|
defer self.queue.condition_mutex.unlock();
|
||||||
|
|
||||||
|
self.queue.condition.wait(self.queue.condition_mutex);
|
||||||
|
|
||||||
|
while (try self.queue.popFirst()) |message| {
|
||||||
|
defer self.queue.allocator.free(message);
|
||||||
|
try writer.writeAll(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self.file.isTty()) try self.file.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn append(self: *LogQueue, message: []const u8) !void {
|
||||||
|
self.read_write_mutex.lock();
|
||||||
|
defer self.read_write_mutex.unlock();
|
||||||
|
|
||||||
|
const node = try self.allocator.create(List.Node);
|
||||||
|
node.* = .{ .data = try self.allocator.dupe(u8, message) };
|
||||||
|
self.list.append(node);
|
||||||
|
self.condition.signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn popFirst(self: *LogQueue) !?[]const u8 {
|
||||||
|
self.read_write_mutex.lock();
|
||||||
|
defer self.read_write_mutex.unlock();
|
||||||
|
|
||||||
|
if (self.list.popFirst()) |node| {
|
||||||
|
const value = node.data;
|
||||||
|
self.allocator.destroy(node);
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user