diff --git a/data/icons/bug-symbolic.svg b/data/icons/bug-symbolic.svg new file mode 100644 index 000000000..f3706fe3d --- /dev/null +++ b/data/icons/bug-symbolic.svg @@ -0,0 +1,20 @@ + + + + diff --git a/data/icons/icons.indicator.gresource.xml b/data/icons/icons.indicator.gresource.xml index a2569a58d..ad678d28b 100644 --- a/data/icons/icons.indicator.gresource.xml +++ b/data/icons/icons.indicator.gresource.xml @@ -1,6 +1,7 @@ + bug-symbolic.svg cpu-symbolic.svg gpu-symbolic.svg ram-symbolic.svg @@ -9,6 +10,9 @@ file-deleted-symbolic.svg temperature-sensor-symbolic.svg temperature-gpu-symbolic.svg + process-attention-symbolic.svg + process-critical-symbolic.svg + process-information-symbolic.svg extra/16/bash.svg extra/48/bash.svg extra/64/bash.svg diff --git a/data/icons/process-attention-symbolic.svg b/data/icons/process-attention-symbolic.svg new file mode 100644 index 000000000..d69e09200 --- /dev/null +++ b/data/icons/process-attention-symbolic.svg @@ -0,0 +1,31 @@ + + + + diff --git a/data/icons/process-critical-symbolic.svg b/data/icons/process-critical-symbolic.svg new file mode 100644 index 000000000..9f80452b2 --- /dev/null +++ b/data/icons/process-critical-symbolic.svg @@ -0,0 +1,21 @@ + + + + diff --git a/data/icons/process-information-symbolic.svg b/data/icons/process-information-symbolic.svg new file mode 100644 index 000000000..d59c28e8d --- /dev/null +++ b/data/icons/process-information-symbolic.svg @@ -0,0 +1,20 @@ + + + + diff --git a/src/Views/LogView/LogCell.vala b/src/Views/LogView/LogCell.vala index f2394cd85..a01857048 100644 --- a/src/Views/LogView/LogCell.vala +++ b/src/Views/LogView/LogCell.vala @@ -6,7 +6,8 @@ public class Monitor.LogCell : Granite.Bin { public enum CellType { ORIGIN, - MESSAGE + MESSAGE, + PRIORITY } public CellType cell_type { get; construct; } diff --git a/src/Views/LogView/LogView.vala b/src/Views/LogView/LogView.vala index b5c96a6a1..f707e5200 100644 --- a/src/Views/LogView/LogView.vala +++ b/src/Views/LogView/LogView.vala @@ -28,8 +28,14 @@ public class Monitor.LogView : Granite.Bin { origin_factory.setup.connect (setup_origin); origin_factory.bind.connect (bind); + var priority_factory = new Gtk.SignalListItemFactory (); + priority_factory.setup.connect (setup_priority); + priority_factory.bind.connect (bind_priority); + var origin_column = new Gtk.ColumnViewColumn (_("Sender"), origin_factory); + var priority_column = new Gtk.ColumnViewColumn (null, priority_factory); + var message_factory = new Gtk.SignalListItemFactory (); message_factory.setup.connect (setup_message); message_factory.bind.connect (bind); @@ -44,6 +50,7 @@ public class Monitor.LogView : Granite.Bin { vexpand = true }; column_view.append_column (origin_column); + column_view.append_column (priority_column); column_view.append_column (message_column); var scrolled = new Gtk.ScrolledWindow () { @@ -82,6 +89,18 @@ public class Monitor.LogView : Granite.Bin { item.child = new LogCell (MESSAGE); } + private void setup_priority (Object obj) { + var item = (Gtk.ListItem) obj; + item.child = new PriorityCell (); + } + + private void bind_priority (Object obj) { + var item = (Gtk.ListItem) obj; + var entry = (SystemdLogEntry) item.item; + var cell = (PriorityCell) item.child; + cell.bind (entry); + } + private void bind (Object obj) { var item = (Gtk.ListItem) obj; var entry = (SystemdLogEntry) item.item; diff --git a/src/Views/LogView/PriorityCell.vala b/src/Views/LogView/PriorityCell.vala new file mode 100644 index 000000000..4cb64a3cc --- /dev/null +++ b/src/Views/LogView/PriorityCell.vala @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2026 elementary, Inc. (https://elementary.io) + */ + +public class Monitor.PriorityCell : Granite.Bin { + private Gtk.Image image; + + construct { + image = new Gtk.Image (); + + child = image; + } + + public void bind (SystemdLogEntry entry) { + switch (entry.priority) { + case INFO: + image.icon_name = "process-information-symbolic"; + image.tooltip_text = _("Information"); + image.css_classes = {"accent", "blue"}; + break; + case DEBUG: + image.icon_name = "bug-symbolic"; + image.tooltip_text = _("Debug"); + image.css_classes = {"accent", "purple"}; + break; + case NOTICE: + image.icon_name = "process-attention-symbolic"; + image.tooltip_text = _("Message"); + image.css_classes = {"accent", "purple"}; + break; + case ALERT: + image.icon_name = "process-attention-symbolic"; + image.tooltip_text = _("Alert"); + image.css_classes = {"accent", "yellow"}; + break; + case WARNING: + image.icon_name = "dialog-warning-symbolic"; + image.tooltip_text = _("Warning"); + break; + case ERR: + image.icon_name = "process-error-symbolic"; + image.tooltip_text = _("Error"); + break; + case CRIT: + case EMERG: + image.icon_name = "process-critical-symbolic"; + image.tooltip_text = _("Critical"); + break; + } + } +} diff --git a/src/Views/LogView/SystemdLogEntry.vala b/src/Views/LogView/SystemdLogEntry.vala index 5beb2d913..f821f32b7 100644 --- a/src/Views/LogView/SystemdLogEntry.vala +++ b/src/Views/LogView/SystemdLogEntry.vala @@ -7,17 +7,24 @@ public string origin { get; construct; } public string message { get; construct; } public DateTime dt { get; construct; } - public string relative_time { get; construct; } + public Systemd.Journal.Priority priority { get; construct; } + public string relative_time { get; private set; } public uint section_start { get; set; } - public SystemdLogEntry (string origin, string message, DateTime time) { + public SystemdLogEntry (string origin, string message, DateTime time, Systemd.Journal.Priority priority) { Object ( - origin: origin, message: message, dt: time, - relative_time: format_time (time) + origin: origin, + message: message, + dt: time, + priority: priority ); } + construct { + relative_time = format_time (dt); + } + public bool matches (string term) { return origin.contains (term) || message.contains (term); } diff --git a/src/Views/LogView/SystemdLogModel.vala b/src/Views/LogView/SystemdLogModel.vala index 4225466a8..9e5e6fbea 100644 --- a/src/Views/LogView/SystemdLogModel.vala +++ b/src/Views/LogView/SystemdLogModel.vala @@ -135,6 +135,8 @@ public class Monitor.SystemdLogModel : GLib.Object, GLib.ListModel, Gtk.SectionM unowned uint8[] data; unowned uint8[] comm_data; + unowned uint8[] priority_data; + res = journal.get_data ("MESSAGE", out data); if (res != 0) { critical ("Failed to get message: %s", strerror (-res)); @@ -146,8 +148,11 @@ public class Monitor.SystemdLogModel : GLib.Object, GLib.ListModel, Gtk.SectionM comm_data = "_COMM=kernel".data; } + res = journal.get_data ("PRIORITY", out priority_data); + var origin = ((string) comm_data).offset ("_COMM=".length); var message = ((string) data).offset ("MESSAGE=".length); + var priority = ((string) priority_data).offset ("PRIORITY=".length); uint64 time; res = journal.get_realtime_usec (out time); @@ -158,7 +163,7 @@ public class Monitor.SystemdLogModel : GLib.Object, GLib.ListModel, Gtk.SectionM var dt = new DateTime.from_unix_utc ((int64) (time / TimeSpan.SECOND)); - var entry = new SystemdLogEntry (origin, message, dt); + var entry = new SystemdLogEntry (origin, message, dt, (Systemd.Journal.Priority) priority.to_int ()); // Filter if we're searching. We drop them and don't add them and use a filter model // because when searching for e.g. a non existent term this would fill up memory *quick* diff --git a/src/meson.build b/src/meson.build index 6bfc3d36d..beb0ad176 100644 --- a/src/meson.build +++ b/src/meson.build @@ -21,6 +21,7 @@ source_app_files = [ 'Views/SystemView/SystemGPUView.vala', 'Views/LogView/LogCell.vala', + 'Views/LogView/PriorityCell.vala', 'Views/LogView/LogView.vala', 'Views/LogView/SystemdLogEntry.vala', 'Views/LogView/SystemdLogModel.vala',