Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions data/icons/bug-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions data/icons/icons.indicator.gresource.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/io/elementary/monitor/icons">
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/categories/bug-symbolic.svg">bug-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/devices/cpu-symbolic.svg">cpu-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/devices/gpu-symbolic.svg">gpu-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/devices/ram-symbolic.svg">ram-symbolic.svg</file>
Expand All @@ -9,6 +10,9 @@
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/mimetypes/file-deleted-symbolic.svg">file-deleted-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/devices/temperature-sensor-symbolic.svg">temperature-sensor-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/devices/temperature-gpu-symbolic.svg">temperature-gpu-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/status/process-attention-symbolic.svg">process-attention-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/status/process-emergency-symbolic.svg">process-critical-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="scalable/status/process-information-symbolic.svg">process-information-symbolic.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="16x16/actions/bash.svg">extra/16/bash.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="48x48/actions/bash.svg">extra/48/bash.svg</file>
<file compressed="true" preprocess="xml-stripblanks" alias="64x64/actions/bash.svg">extra/64/bash.svg</file>
Expand Down
31 changes: 31 additions & 0 deletions data/icons/process-attention-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions data/icons/process-critical-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions data/icons/process-information-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/Views/LogView/LogCell.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
public class Monitor.LogCell : Granite.Bin {
public enum CellType {
ORIGIN,
MESSAGE
MESSAGE,
PRIORITY
}

public CellType cell_type { get; construct; }
Expand Down
19 changes: 19 additions & 0 deletions src/Views/LogView/LogView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 () {
Expand Down Expand Up @@ -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;
Expand Down
52 changes: 52 additions & 0 deletions src/Views/LogView/PriorityCell.vala
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
15 changes: 11 additions & 4 deletions src/Views/LogView/SystemdLogEntry.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
7 changes: 6 additions & 1 deletion src/Views/LogView/SystemdLogModel.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
Expand All @@ -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*
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Loading