From d74323bbbf844df0febe2b1c9fa414d549e41847 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 17 Jun 2020 01:25:11 +0200 Subject: [PATCH] code: improve logging functions this implements a modified version of the logging interface proposed here: https://github.com/ziglang/zig/pull/5348 --- river/Config.zig | 1 - river/Control.zig | 1 - river/Cursor.zig | 8 +- river/InputManager.zig | 6 +- river/Keyboard.zig | 6 +- river/LayerSurface.zig | 10 +-- river/Output.zig | 30 ++++---- river/OutputStatus.zig | 4 +- river/Root.zig | 18 +++-- river/SeatStatus.zig | 1 - river/Server.zig | 28 ++++--- river/StatusManager.zig | 12 +-- river/View.zig | 10 +-- river/XdgToplevel.zig | 4 +- river/XwaylandUnmanaged.zig | 1 - river/XwaylandView.zig | 1 - river/log.zig | 149 +++++++++++++++++++++++++++++++----- river/main.zig | 9 +-- 18 files changed, 207 insertions(+), 92 deletions(-) diff --git a/river/Config.zig b/river/Config.zig index 9791019..4d0fd9e 100644 --- a/river/Config.zig +++ b/river/Config.zig @@ -22,7 +22,6 @@ const std = @import("std"); const c = @import("c.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Server = @import("Server.zig"); const Mapping = @import("Mapping.zig"); diff --git a/river/Control.zig b/river/Control.zig index 5a8657a..5e56e83 100644 --- a/river/Control.zig +++ b/river/Control.zig @@ -23,7 +23,6 @@ const c = @import("c.zig"); const command = @import("command.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Seat = @import("Seat.zig"); const Server = @import("Server.zig"); diff --git a/river/Cursor.zig b/river/Cursor.zig index b716da7..18bb9bf 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -21,10 +21,10 @@ const build_options = @import("build_options"); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); const LayerSurface = @import("LayerSurface.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const Seat = @import("Seat.zig"); const View = @import("View.zig"); @@ -89,7 +89,7 @@ pub fn init(self: *Self, seat: *Seat) !void { } } } else { - Log.Error.log("Failed to load an xcursor theme", .{}); + log.err(.cursor, "failed to load an xcursor theme", .{}); } self.mode = CursorMode.Passthrough; @@ -235,7 +235,7 @@ fn handleRequestSetCursor(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C // provided surface as the cursor image. It will set the hardware cursor // on the output that it's currently on and continue to do so as the // cursor moves between outputs. - Log.Debug.log("Focused client set cursor", .{}); + log.debug(.cursor, "focused client set cursor", .{}); c.wlr_cursor_set_surface( self.wlr_cursor, event.surface, @@ -259,7 +259,7 @@ fn processMotion(self: Self, time: u32) void { const wlr_seat = self.seat.wlr_seat; const focus_change = wlr_seat.pointer_state.focused_surface != wlr_surface; if (focus_change) { - Log.Debug.log("Pointer notify enter at ({},{})", .{ sx, sy }); + log.debug(.cursor, "pointer notify enter at ({},{})", .{ sx, sy }); c.wlr_seat_pointer_notify_enter(wlr_seat, wlr_surface, sx, sy); } else { // The enter event contains coordinates, so we only need to notify diff --git a/river/InputManager.zig b/river/InputManager.zig index 7c1337c..e9264a0 100644 --- a/river/InputManager.zig +++ b/river/InputManager.zig @@ -20,9 +20,9 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Seat = @import("Seat.zig"); const Server = @import("Server.zig"); @@ -102,7 +102,7 @@ pub fn inputAllowed(self: Self, wlr_surface: *c.wlr_surface) bool { fn handleInhibitActivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_inhibit_activate", listener.?); - Log.Debug.log("Input inhibitor activated", .{}); + log.debug(.input_manager, "input inhibitor activated", .{}); // Clear focus of all seats var seat_it = self.seats.first; @@ -116,7 +116,7 @@ fn handleInhibitActivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) fn handleInhibitDeactivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_inhibit_deactivate", listener.?); - Log.Debug.log("Input inhibitor deactivated", .{}); + log.debug(.input_manager, "input inhibitor deactivated", .{}); self.exclusive_client = null; diff --git a/river/Keyboard.zig b/river/Keyboard.zig index 8f57370..12b043f 100644 --- a/river/Keyboard.zig +++ b/river/Keyboard.zig @@ -20,9 +20,9 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Seat = @import("Seat.zig"); seat: *Seat, @@ -163,12 +163,12 @@ fn handleModifiers(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void /// Returns true if the keysym was handled. fn handleBuiltinMapping(self: Self, keysym: c.xkb_keysym_t) bool { if (keysym >= c.XKB_KEY_XF86Switch_VT_1 and keysym <= c.XKB_KEY_XF86Switch_VT_12) { - Log.Debug.log("Switch VT keysym received", .{}); + log.debug(.keyboard, "switch VT keysym received", .{}); const wlr_backend = self.seat.input_manager.server.wlr_backend; if (c.river_wlr_backend_is_multi(wlr_backend)) { if (c.river_wlr_backend_get_session(wlr_backend)) |session| { const vt = keysym - c.XKB_KEY_XF86Switch_VT_1 + 1; - Log.Debug.log("Switching to VT {}", .{vt}); + log.notice(.server, "switching to VT {}", .{vt}); _ = c.wlr_session_change_vt(session, vt); } } diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig index 6fa6822..e74b24b 100644 --- a/river/LayerSurface.zig +++ b/river/LayerSurface.zig @@ -20,10 +20,10 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); const Box = @import("Box.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const XdgPopup = @import("XdgPopup.zig"); @@ -79,7 +79,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_destroy", listener.?); const output = self.output; - Log.Debug.log("Layer surface '{}' destroyed", .{self.wlr_layer_surface.namespace}); + log.debug(.layer_shell, "layer surface '{}' destroyed", .{self.wlr_layer_surface.namespace}); // Remove listeners active the entire lifetime of the layer surface c.wl_list_remove(&self.listen_destroy.link); @@ -94,7 +94,7 @@ fn handleMap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_map", listener.?); const wlr_layer_surface = self.wlr_layer_surface; - Log.Debug.log("Layer surface '{}' mapped.", .{wlr_layer_surface.namespace}); + log.debug(.layer_shell, "layer surface '{}' mapped", .{wlr_layer_surface.namespace}); // Add listeners that are only active while mapped self.listen_commit.notify = handleCommit; @@ -115,7 +115,7 @@ fn handleMap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { fn handleUnmap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_unmap", listener.?); - Log.Debug.log("Layer surface '{}' unmapped.", .{self.wlr_layer_surface.namespace}); + log.debug(.layer_shell, "layer surface '{}' unmapped", .{self.wlr_layer_surface.namespace}); // This is a bit ugly: we need to use the wlr bool here since surfaces // may be closed during the inital configure which we preform @@ -164,7 +164,7 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const wlr_layer_surface = self.wlr_layer_surface; if (self.wlr_layer_surface.output == null) { - Log.Error.log("Layer surface committed with null output", .{}); + log.err(.layer_shell, "layer surface committed with null output", .{}); return; } diff --git a/river/Output.zig b/river/Output.zig index 67c70e7..290530d 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -21,12 +21,12 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const render = @import("render.zig"); const util = @import("util.zig"); const Box = @import("Box.zig"); const LayerSurface = @import("LayerSurface.zig"); -const Log = @import("log.zig").Log; const Root = @import("Root.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; @@ -288,11 +288,11 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void { box.height -= delta_size; if (box.width < minimum_size) { box.width = minimum_size; - Log.Info.log("Window configuration hits minimum view width.", .{}); + log.notice(.layout, "window hits minimum view width.", .{}); } if (box.height < minimum_size) { box.height = minimum_size; - Log.Info.log("Window configuration hits minimum view height.", .{}); + log.notice(.layout, "window hits minimum view height.", .{}); } try view_boxen.append(box); } @@ -338,12 +338,12 @@ pub fn arrangeViews(self: *Self) void { layoutExternal(self, visible_count, output_tags) catch |err| { switch (err) { - LayoutError.BadExitCode => Log.Error.log("Layout command exited with non-zero return code.", .{}), - LayoutError.BadWindowConfiguration => Log.Error.log("Invalid window configuration.", .{}), - LayoutError.ConfigurationMismatch => Log.Error.log("Mismatch between amount of window configurations and visible windows.", .{}), - else => Log.Error.log("Encountered unexpected error while trying to use external layout.", .{}), + LayoutError.BadExitCode => log.err(.layout, "layout command exited with non-zero return code", .{}), + LayoutError.BadWindowConfiguration => log.err(.layout, "invalid window configuration", .{}), + LayoutError.ConfigurationMismatch => log.err(.layout, "mismatch between window configuration and visible window counts", .{}), + else => log.err(.layout, "'{}' error while trying to use external layout", .{err}), } - Log.Error.log("Falling back to internal layout", .{}); + log.err(.layout, "falling back to internal layout", .{}); layoutFull(self, visible_count, output_tags); }; } @@ -461,8 +461,9 @@ fn arrangeLayer( new_box.width = bounds.width - (current_state.margin.left + current_state.margin.right); } else { - Log.Error.log( - "Protocol Error: layer surface '{}' requested width 0 without anchoring to opposite edges.", + log.err( + .layer_shell, + "protocol error: layer surface '{}' requested width 0 without anchoring to opposite edges", .{layer_surface.wlr_layer_surface.namespace}, ); c.wlr_layer_surface_v1_close(layer_surface.wlr_layer_surface); @@ -490,8 +491,9 @@ fn arrangeLayer( new_box.height = bounds.height - (current_state.margin.top + current_state.margin.bottom); } else { - Log.Error.log( - "Protocol Error: layer surface '{}' requested height 0 without anchoring to opposite edges.", + log.err( + .layer_shell, + "protocol error: layer surface '{}' requested height 0 without anchoring to opposite edges", .{layer_surface.wlr_layer_surface.namespace}, ); c.wlr_layer_surface_v1_close(layer_surface.wlr_layer_surface); @@ -559,7 +561,7 @@ fn arrangeLayer( } // Tell the client to assume the new size - Log.Debug.log("send configure, {} x {}", .{ layer_surface.box.width, layer_surface.box.height }); + log.debug(.layer_shell, "send configure, {} x {}", .{ layer_surface.box.width, layer_surface.box.height }); c.wlr_layer_surface_v1_configure( layer_surface.wlr_layer_surface, layer_surface.box.width, @@ -574,7 +576,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_destroy", listener.?); const root = self.root; - Log.Debug.log("Output {} destroyed", .{self.wlr_output.name}); + log.debug(.server, "output '{}' destroyed", .{self.wlr_output.name}); // Use the first output in the list that is not the one being destroyed. // If there is no other real output, use the noop output. diff --git a/river/OutputStatus.zig b/river/OutputStatus.zig index 6b09dd1..129570a 100644 --- a/river/OutputStatus.zig +++ b/river/OutputStatus.zig @@ -20,9 +20,9 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; @@ -64,7 +64,7 @@ pub fn sendViewTags(self: Self) void { while (it.next()) |node| view_tags.append(node.view.current_tags) catch { c.wl_resource_post_no_memory(self.wl_resource); - Log.Error.log("out of memory", .{}); + log.crit(.river_status, "out of memory", .{}); return; }; diff --git a/river/Root.zig b/river/Root.zig index 70a1426..dc1a92a 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -21,9 +21,9 @@ const std = @import("std"); const build_options = @import("build_options"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const Server = @import("Server.zig"); const View = @import("View.zig"); @@ -156,21 +156,22 @@ fn startTransaction(self: *Self) void { } if (self.pending_configures > 0) { - Log.Debug.log( - "Started transaction with {} pending configures.", + log.debug( + .transaction, + "started transaction with {} pending configure(s)", .{self.pending_configures}, ); // Set timeout to 200ms if (c.wl_event_source_timer_update(self.transaction_timer, 200) < 0) { - Log.Error.log("failed to update timer.", .{}); + log.err(.transaction, "failed to update timer", .{}); self.commitTransaction(); } } else { // No views need configures, clear the current timer in case we are // interrupting another transaction and commit. if (c.wl_event_source_timer_update(self.transaction_timer, 0) < 0) - Log.Error.log("error disarming timer", .{}); + log.err(.transaction, "error disarming timer", .{}); self.commitTransaction(); } } @@ -178,7 +179,7 @@ fn startTransaction(self: *Self) void { fn handleTimeout(data: ?*c_void) callconv(.C) c_int { const self = util.voidCast(Self, data.?); - Log.Error.log("Transaction timed out. Some imperfect frames may be shown.", .{}); + log.err(.transaction, "time out occurred, some imperfect frames may be shown", .{}); self.commitTransaction(); @@ -190,7 +191,7 @@ pub fn notifyConfigured(self: *Self) void { if (self.pending_configures == 0) { // Disarm the timer, as we didn't timeout if (c.wl_event_source_timer_update(self.transaction_timer, 0) == -1) - Log.Error.log("Error disarming timer", .{}); + log.err(.transaction, "error disarming timer", .{}); self.commitTransaction(); } } @@ -212,7 +213,8 @@ fn commitTransaction(self: *Self) void { // If there were pending focused tags, make them the current focus if (output.pending_focused_tags) |tags| { - Log.Debug.log( + log.debug( + .output, "changing current focus: {b:0>10} to {b:0>10}", .{ output.current_focused_tags, tags }, ); diff --git a/river/SeatStatus.zig b/river/SeatStatus.zig index 1f6b408..230a196 100644 --- a/river/SeatStatus.zig +++ b/river/SeatStatus.zig @@ -22,7 +22,6 @@ const std = @import("std"); const c = @import("c.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Seat = @import("Seat.zig"); const Output = @import("Output.zig"); const View = @import("View.zig"); diff --git a/river/Server.zig b/river/Server.zig index 6f99d18..3d4307a 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -21,6 +21,7 @@ const build_options = @import("build_options"); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); const Config = @import("Config.zig"); @@ -28,7 +29,6 @@ const Control = @import("Control.zig"); const DecorationManager = @import("DecorationManager.zig"); const InputManager = @import("InputManager.zig"); const LayerSurface = @import("LayerSurface.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const Root = @import("Root.zig"); const StatusManager = @import("StatusManager.zig"); @@ -181,7 +181,7 @@ pub fn run(self: Self) void { fn handleNewOutput(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_new_output", listener.?); const wlr_output = util.voidCast(c.wlr_output, data.?); - Log.Debug.log("New output {}", .{wlr_output.name}); + log.debug(.server, "new output {}", .{wlr_output.name}); self.root.addOutput(wlr_output); } @@ -192,11 +192,11 @@ fn handleNewXdgSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) v const wlr_xdg_surface = util.voidCast(c.wlr_xdg_surface, data.?); if (wlr_xdg_surface.role == .WLR_XDG_SURFACE_ROLE_POPUP) { - Log.Debug.log("New xdg_popup", .{}); + log.debug(.server, "new xdg_popup", .{}); return; } - Log.Debug.log("New xdg_toplevel", .{}); + log.debug(.server, "new xdg_toplevel", .{}); // The View will add itself to the output's view stack on map const output = self.input_manager.default_seat.focused_output; @@ -209,7 +209,8 @@ fn handleNewLayerSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) const self = @fieldParentPtr(Self, "listen_new_layer_surface", listener.?); const wlr_layer_surface = util.voidCast(c.wlr_layer_surface_v1, data.?); - Log.Debug.log( + log.debug( + .server, "New layer surface: namespace {}, layer {}, anchor {}, size {}x{}, margin ({},{},{},{}), exclusive_zone {}", .{ wlr_layer_surface.namespace, @@ -230,14 +231,16 @@ fn handleNewLayerSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) if (wlr_layer_surface.output == null) { if (self.root.outputs.first) |node| { const output = &node.data; - Log.Debug.log( - "New layer surface had null output, assigning it to output {}", + log.debug( + .server, + "new layer surface had null output, assigning it to output '{}'", .{output.wlr_output.name}, ); wlr_layer_surface.output = output.wlr_output; } else { - Log.Error.log( - "No output available for layer surface '{}'", + log.err( + .server, + "no output available for layer surface '{}'", .{wlr_layer_surface.namespace}, ); c.wlr_layer_surface_v1_close(wlr_layer_surface); @@ -256,7 +259,7 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv( const wlr_xwayland_surface = util.voidCast(c.wlr_xwayland_surface, data.?); if (wlr_xwayland_surface.override_redirect) { - Log.Debug.log("New unmanaged xwayland surface", .{}); + log.debug(.server, "new unmanaged xwayland surface", .{}); // The unmanged surface will add itself to the list of unmanaged views // in Root when it is mapped. const node = util.allocator.create(std.TailQueue(XwaylandUnmanaged).Node) catch unreachable; @@ -264,8 +267,9 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv( return; } - Log.Debug.log( - "New xwayland surface: title '{}', class '{}'", + log.debug( + .server, + "new xwayland surface: title '{}', class '{}'", .{ wlr_xwayland_surface.title, wlr_xwayland_surface.class }, ); diff --git a/river/StatusManager.zig b/river/StatusManager.zig index 0fe3d6e..c6de81a 100644 --- a/river/StatusManager.zig +++ b/river/StatusManager.zig @@ -20,9 +20,9 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const OutputStatus = @import("OutputStatus.zig"); const Seat = @import("Seat.zig"); @@ -72,7 +72,7 @@ fn bind(wl_client: ?*c.wl_client, data: ?*c_void, version: u32, id: u32) callcon id, ) orelse { c.wl_client_post_no_memory(wl_client); - Log.Error.log("out of memory\n", .{}); + log.crit(.river_status, "out of memory", .{}); return; }; c.wl_resource_set_implementation(wl_resource, &implementation, self, null); @@ -95,7 +95,7 @@ fn getRiverOutputStatus( const node = util.allocator.create(std.SinglyLinkedList(OutputStatus).Node) catch { c.wl_client_post_no_memory(wl_client); - Log.Error.log("out of memory\n", .{}); + log.crit(.river_status, "out of memory", .{}); return; }; @@ -107,7 +107,7 @@ fn getRiverOutputStatus( ) orelse { c.wl_client_post_no_memory(wl_client); util.allocator.destroy(node); - Log.Error.log("out of memory\n", .{}); + log.crit(.river_status, "out of memory", .{}); return; }; @@ -128,7 +128,7 @@ fn getRiverSeatStatus( const node = util.allocator.create(std.SinglyLinkedList(SeatStatus).Node) catch { c.wl_client_post_no_memory(wl_client); - Log.Error.log("out of memory\n", .{}); + log.crit(.river_status, "out of memory", .{}); return; }; @@ -140,7 +140,7 @@ fn getRiverSeatStatus( ) orelse { c.wl_client_post_no_memory(wl_client); util.allocator.destroy(node); - Log.Error.log("out of memory\n", .{}); + log.crit(.river_status, "out of memory", .{}); return; }; diff --git a/river/View.zig b/river/View.zig index 0ff2344..12226ec 100644 --- a/river/View.zig +++ b/river/View.zig @@ -21,10 +21,10 @@ const build_options = @import("build_options"); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); const Box = @import("Box.zig"); -const Log = @import("log.zig").Log; const Output = @import("Output.zig"); const Root = @import("Root.zig"); const ViewStack = @import("view_stack.zig").ViewStack; @@ -138,7 +138,7 @@ pub fn configure(self: Self) void { .xwayland_view => |xwayland_view| xwayland_view.configure(pending_box), } } else { - Log.Error.log("Configure called on a View with no pending box", .{}); + log.err(.transaction, "configure called on a View with no pending box", .{}); } } @@ -155,7 +155,7 @@ pub fn dropSavedBuffers(self: *Self) void { pub fn saveBuffers(self: *Self) void { if (self.saved_buffers.items.len > 0) { - Log.Error.log("view already has buffers saved, overwriting", .{}); + log.err(.transaction, "view already has buffers saved, overwriting", .{}); self.saved_buffers.items.len = 0; } @@ -270,7 +270,7 @@ pub fn getTitle(self: Self) [*:0]const u8 { pub fn map(self: *Self) void { const root = self.output.root; - Log.Debug.log("View '{}' mapped", .{self.getTitle()}); + log.debug(.server, "view '{}' mapped", .{self.getTitle()}); // Add the view to the stack of its output const node = @fieldParentPtr(ViewStack(Self).Node, "view", self); @@ -294,7 +294,7 @@ pub fn map(self: *Self) void { pub fn unmap(self: *Self) void { const root = self.output.root; - Log.Debug.log("View '{}' unmapped", .{self.getTitle()}); + log.debug(.server, "view '{}' unmapped", .{self.getTitle()}); self.wlr_surface = null; diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index a217742..ee9b113 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -20,10 +20,10 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); const Box = @import("Box.zig"); -const Log = @import("log.zig").Log; const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XdgPopup = @import("XdgPopup.zig"); @@ -235,7 +235,7 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { } else { // TODO: handle unexpected change in dimensions if (!std.meta.eql(view.surface_box, new_box)) - Log.Error.log("View changed size unexpectedly", .{}); + log.err(.xdg_shell, "view changed size unexpectedly", .{}); view.surface_box = new_box; } } diff --git a/river/XwaylandUnmanaged.zig b/river/XwaylandUnmanaged.zig index f21f064..fe6f366 100644 --- a/river/XwaylandUnmanaged.zig +++ b/river/XwaylandUnmanaged.zig @@ -23,7 +23,6 @@ const c = @import("c.zig"); const util = @import("util.zig"); const Box = @import("Box.zig"); -const Log = @import("log.zig").Log; const Root = @import("Root.zig"); root: *Root, diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig index 171aba2..9195d83 100644 --- a/river/XwaylandView.zig +++ b/river/XwaylandView.zig @@ -22,7 +22,6 @@ const std = @import("std"); const c = @import("c.zig"); const Box = @import("Box.zig"); -const Log = @import("log.zig").Log; const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XdgPopup = @import("XdgPopup.zig"); diff --git a/river/log.zig b/river/log.zig index 30d2564..1874630 100644 --- a/river/log.zig +++ b/river/log.zig @@ -17,25 +17,138 @@ const std = @import("std"); -pub const Log = enum { - const Self = @This(); +pub const Level = enum { + /// Emergency: a condition that cannot be handled, usually followed by a + /// panic. + emerg, + /// Alert: a condition that should be corrected immediately (e.g. database + /// corruption). + alert, + /// Critical: A bug has been detected or something has gone wrong and it + /// will have an effect on the operation of the program. + crit, + /// Error: A bug has been detected or something has gone wrong but it is + /// recoverable. + err, + /// Warning: it is uncertain if something has gone wrong or not, but the + /// circumstances would be worth investigating. + warn, + /// Notice: non-error but significant conditions. + notice, + /// Informational: general messages about the state of the program. + info, + /// Debug: messages only useful for debugging. + debug, +}; - Silent = 0, - Error = 1, - Info = 2, - Debug = 3, +/// The default log level is based on build mode. Note that in ReleaseSmall +/// builds the default level is emerg but no messages will be stored/logged +/// to save space. +pub var level: Level = switch (std.builtin.mode) { + .Debug => .debug, + .ReleaseSafe => .notice, + .ReleaseFast => .err, + .ReleaseSmall => .emerg, +}; - var verbosity = Self.Error; - - pub fn init(_verbosity: Self) void { - verbosity = _verbosity; - } - - fn log(level: Self, comptime format: []const u8, args: var) void { - if (@enumToInt(level) <= @enumToInt(verbosity)) { - // TODO: log the time since start in the same format as wlroots - // TODO: use color if logging to a tty - std.debug.warn("[{}] " ++ format ++ "\n", .{@tagName(level)} ++ args); +fn log( + comptime message_level: Level, + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + if (@enumToInt(message_level) <= @enumToInt(level)) { + // Don't store/log messages in release small mode to save space + if (std.builtin.mode != .ReleaseSmall) { + const stderr = std.debug.getStderrStream(); + stderr.print(@tagName(message_level) ++ ": (" ++ @tagName(scope) ++ ") " ++ + format ++ "\n", args) catch return; } } -}; +} + +/// Log an emergency message to stderr. This log level is intended to be used +/// for conditions that cannot be handled and is usually followed by a panic. +pub fn emerg( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + @setCold(true); + log(.emerg, scope, format, args); +} + +/// Log an alert message to stderr. This log level is intended to be used for +/// conditions that should be corrected immediately (e.g. database corruption). +pub fn alert( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + @setCold(true); + log(.alert, scope, format, args); +} + +/// Log a critical message to stderr. This log level is intended to be used +/// when a bug has been detected or something has gone wrong and it will have +/// an effect on the operation of the program. +pub fn crit( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + @setCold(true); + log(.crit, scope, format, args); +} + +/// Log an error message to stderr. This log level is intended to be used when +/// a bug has been detected or something has gone wrong but it is recoverable. +pub fn err( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + @setCold(true); + log(.err, scope, format, args); +} + +/// Log a warning message to stderr. This log level is intended to be used if +/// it is uncertain whether something has gone wrong or not, but the +/// circumstances would be worth investigating. +pub fn warn( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + log(.warn, scope, format, args); +} + +/// Log a notice message to stderr. This log level is intended to be used for +/// non-error but significant conditions. +pub fn notice( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + log(.notice, scope, format, args); +} + +/// Log an info message to stderr. This log level is intended to be used for +/// general messages about the state of the program. +pub fn info( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + log(.info, scope, format, args); +} + +/// Log a debug message to stderr. This log level is intended to be used for +/// messages which are only useful for debugging. +pub fn debug( + comptime scope: @TypeOf(.foobar), + comptime format: []const u8, + args: var, +) void { + log(.debug, scope, format, args); +} diff --git a/river/main.zig b/river/main.zig index 0e95b5c..2275efe 100644 --- a/river/main.zig +++ b/river/main.zig @@ -18,9 +18,9 @@ const std = @import("std"); const c = @import("c.zig"); +const log = @import("log.zig"); const util = @import("util.zig"); -const Log = @import("log.zig").Log; const Server = @import("Server.zig"); const usage: []const u8 = @@ -58,10 +58,9 @@ pub fn main() !void { } } - Log.init(Log.Debug); c.wlr_log_init(.WLR_ERROR, null); - Log.Info.log("Initializing server", .{}); + log.info(.server, "initializing", .{}); var server: Server = undefined; try server.init(); @@ -76,9 +75,9 @@ pub fn main() !void { try std.ChildProcess.spawn(child); } - Log.Info.log("Running server...", .{}); + log.info(.server, "running...", .{}); server.run(); - Log.Info.log("Shutting down server", .{}); + log.info(.server, "shutting down", .{}); }