Repository: rauc/rauc (C)

Issue:
Log message MESSAGE_ID_INSTALLATION_SUCCEEDED is missing the PRIORITY field in systemd journal
**Describe the bug**

While the other log messages in install.c are logged with their respective priority, MESSAGE_ID_INSTALLATION_SUCCEEDED is missing the actual PRIORITY field in the journal.

It's treated as being "info", though, so noone will barely notice it when browsing the journal but it surfaces in log management systems.



**Background information**

version 1.11.3, build by bitbake/Yocto
https://github.com/rauc/rauc/blob/v1.11.3/src/install.c#L1149

**To Reproduce**

1. install a bundle via rauc
2. journalctl -u rauc (here, it's not distinguishable from log messages with PRIORITY info
3. journalctl -u rauc -o verbose (here, this particular message is missing the PRIORITY field)

**Expected behavior**

Log message MESSAGE_ID_INSTALLATION_SUCCEEDED should have a PRITORITY field attached, either info (6) or notice (5).

**Logs**
```
Thu 2024-07-18 21:39:51.708571 CEST [s=a8d01e952a104323a49a60f3115ba123;i=1156;b=358b8dd314394f60a6e642e84c647137;m=19a3c032b;t=61d8abe1082f9;x=739432f9a5787195]
    PRIORITY=5
    _BOOT_ID=358b8dd314394f60a6e642e84c647137
    _MACHINE_ID=2063e02c3f724434bcd7e1717d0aff62
    _RUNTIME_SCOPE=system
    _UID=0
    _GID=0
    _SYSTEMD_SLICE=system.slice
    _TRANSPORT=journal
    _CAP_EFFECTIVE=1ffffffffff
    _PID=663
    _COMM=rauc
    _EXE=/usr/bin/rauc
    _CMDLINE=/usr/bin/rauc --mount=/run/rauc service
    _SYSTEMD_CGROUP=/system.slice/rauc.service
    _SYSTEMD_UNIT=rauc.service
    _SYSTEMD_INVOCATION_ID=7c28039f337d41b683f34bc4c8f16417
    GLIB_DOMAIN=rauc-event
    RAUC_EVENT_TYPE=mark
    SLOT_NAME=platform.1
    SLOT_BOOTNAME=platform1
    _HOSTNAME=<redacted>
    MESSAGE=Marked slot platform.1 as active
    MESSAGE_ID=8b5e7435e1054d86858278e7544fe6da
    BUNDLE_HASH=5fd0b95f57310edfb481895d3134fb4965b5243d69f72ae50ecfa34ed25e0d10
    _SOURCE_REALTIME_TIMESTAMP=1721331591708571
Thu 2024-07-18 21:39:51.726253 CEST [s=a8d01e952a104323a49a60f3115ba123;i=1157;b=358b8dd314394f60a6e642e84c647137;m=19a3c45b9;t=61d8abe10c586;x=e03b2969a012b8fa]
    _BOOT_ID=358b8dd314394f60a6e642e84c647137
    _MACHINE_ID=2063e02c3f724434bcd7e1717d0aff62
    _RUNTIME_SCOPE=system
    _UID=0
    _GID=0
    _SYSTEMD_SLICE=system.slice
    _TRANSPORT=journal
    _CAP_EFFECTIVE=1ffffffffff
    _PID=663
    _COMM=rauc
    _EXE=/usr/bin/rauc
    _CMDLINE=/usr/bin/rauc --mount=/run/rauc service
    _SYSTEMD_CGROUP=/system.slice/rauc.service
    _SYSTEMD_UNIT=rauc.service
    _SYSTEMD_INVOCATION_ID=7c28039f337d41b683f34bc4c8f16417
    GLIB_DOMAIN=rauc-event
    _HOSTNAME=<redacted>
    RAUC_EVENT_TYPE=install
    TRANSACTION_ID=5bd27691-bd38-47ab-b5a2-fdc99bae71f0
    BUNDLE_HASH=5fd0b95f57310edfb481895d3134fb4965b5243d69f72ae50ecfa34ed25e0d10
    MESSAGE=Installation 5bd27691 succeeded
    MESSAGE_ID=0163db5468ac4237b090d28490c301ed
    BUNDLE_DESCRIPTION=<redacted>
    BUNDLE_VERSION=<redacted>
    _SOURCE_REALTIME_TIMESTAMP=1721331591726253
```

**Additional context**

It's a very low priority issue.



Discussion: Good catch!
After reading `g_log_structured_array()` again which notes:

> This assumes that log_level is already present in fields (typically as the PRIORITY field).

it is quite clear why.

I guess my confusion comes from the `log_level` argument of `g_log_strctured_array()` which just seems to serve for the fatal mask and filtering but does not make it into a `"PRIORITY"` field.
It is also interesting that glib's `log_level_to_priority()` (that `g_log_structured()` uses to generate a `"PRIORITY"` from the `log_level`) is glib-internal only. Thus we have to map it ourselves (or use hard-coded "5")
@AndreasUfert I have created https://github.com/rauc/rauc/pull/1471 to address this.



Fix (patch):
diff --git a/include/event_log.h b/include/event_log.h
index e264e81d1..14935f10a 100644
--- a/include/event_log.h
+++ b/include/event_log.h
@@ -72,6 +72,15 @@ typedef struct _REventLogger {
 	void (*writer)(REventLogger* logger, const GLogField *fields, gsize n_fields);
 } REventLogger;
 
+/**
+ * Returns log level to use for "PRIORITY" field of structured log array
+ *
+ * @param log_level log level
+ *
+ * @return static string representing the log priority.
+ */
+const gchar* r_event_log_level_to_priority(GLogLevelFlags log_level);
+
 /**
  * Tests type string for being a supported event log type.
  *
diff --git a/src/event_log.c b/src/event_log.c
index a7ffa5950..444289724 100644
--- a/src/event_log.c
+++ b/src/event_log.c
@@ -24,6 +24,25 @@ gboolean r_event_log_is_supported_type(const gchar *type)
 	return g_strv_contains(supported_event_types, type);
 }
 
+const gchar * r_event_log_level_to_priority(GLogLevelFlags log_level)
+{
+	if (log_level & G_LOG_LEVEL_ERROR)
+		return "3";
+	else if (log_level & G_LOG_LEVEL_CRITICAL)
+		return "4";
+	else if (log_level & G_LOG_LEVEL_WARNING)
+		return "4";
+	else if (log_level & G_LOG_LEVEL_MESSAGE)
+		return "5";
+	else if (log_level & G_LOG_LEVEL_INFO)
+		return "6";
+	else if (log_level & G_LOG_LEVEL_DEBUG)
+		return "7";
+
+	/* Default to LOG_NOTICE for custom log levels. */
+	return "5";
+}
+
 void r_event_log_message(const gchar *type, const gchar *message, ...)
 {
 	va_list list;
diff --git a/src/install.c b/src/install.c
index 09b44abee..59ced9023 100644
--- a/src/install.c
+++ b/src/install.c
@@ -1124,8 +1124,9 @@ static void log_event_installation_done(RaucInstallArgs *args, RaucManifest *man
 {
 	g_autofree gchar *formatted = NULL;
 	GLogField fields[] = {
-		{"MESSAGE", NULL, -1 },
-		{"MESSAGE_ID", NULL, -1 },
+		{"MESSAGE", NULL, -1},
+		{"MESSAGE_ID", NULL, -1},
+		{"PRIORITY", r_event_log_level_to_priority(G_LOG_LEVEL_MESSAGE), -1},
 		{"GLIB_DOMAIN", R_EVENT_LOG_DOMAIN, -1},
 		{"RAUC_EVENT_TYPE", "install", -1},
 		{"BUNDLE_HASH", "", -1},
@@ -1152,9 +1153,9 @@ static void log_event_installation_done(RaucInstallArgs *args, RaucManifest *man
 
 	fields[0].value = formatted;
 	if (manifest) {
-		fields[4].value = manifest->hash ?: "";
-		fields[5].value = manifest->update_description ?: "";
-		fields[6].value = manifest->update_version ?: "";
+		fields[5].value = manifest->hash ?: "";
+		fields[6].value = manifest->update_description ?: "";
+		fields[7].value = manifest->update_version ?: "";
 	}
 
 	g_log_structured_array(G_LOG_LEVEL_MESSAGE, fields, G_N_ELEMENTS(fields));
diff --git a/src/main.c b/src/main.c
index 6e97b6062..1f2179d3a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2010,6 +2010,7 @@ static void r_event_log_booted(const RaucSlot *booted_slot)
 	GLogField fields[] = {
 		{"MESSAGE", NULL, -1 },
 		{"MESSAGE_ID", MESSAGE_ID_BOOTED, -1 },
+		{"PRIORITY", r_event_log_level_to_priority(G_LOG_LEVEL_MESSAGE), -1},
 		{"GLIB_DOMAIN", R_EVENT_LOG_DOMAIN, -1},
 		{"RAUC_EVENT_TYPE", "boot", -1},
 		{"SLOT_NAME", NULL, -1},
@@ -2022,13 +2023,13 @@ static void r_event_log_booted(const RaucSlot *booted_slot)
 
 	message = g_strdup_printf("Booted into %s (%s)", booted_slot->name, booted_slot->bootname);
 	fields[0].value = message;
-	fields[4].value = booted_slot->name;
-	fields[5].value = booted_slot->bootname;
-	fields[6].value = r_context()->boot_id;
+	fields[5].value = booted_slot->name;
+	fields[6].value = booted_slot->bootname;
+	fields[7].value = r_context()->boot_id;
 	if (booted_slot->status && booted_slot->status->bundle_hash) {
-		fields[7].value = booted_slot->status->bundle_hash;
+		fields[8].value = booted_slot->status->bundle_hash;
 	} else {
-		fields[7].value = "unknown";
+		fields[8].value = "unknown";
 	}
 	g_log_structured_array(G_LOG_LEVEL_MESSAGE, fields, G_N_ELEMENTS(fields));
 }
@@ -2039,6 +2040,7 @@ static void r_event_log_booted_external(void)
 	GLogField fields[] = {
 		{"MESSAGE", NULL, -1 },
 		{"MESSAGE_ID", MESSAGE_ID_BOOTED_EXTERNAL, -1 },
+		{"PRIORITY", r_event_log_level_to_priority(G_LOG_LEVEL_MESSAGE), -1},
 		{"GLIB_DOMAIN", R_EVENT_LOG_DOMAIN, -1},
 		{"RAUC_EVENT_TYPE", "boot", -1},
 		{"BOOT_ID", NULL, -1},
@@ -2046,7 +2048,7 @@ static void r_event_log_booted_external(void)
 
 	message = g_strdup_printf("Booted from external source");
 	fields[0].value = message;
-	fields[4].value = r_context()->boot_id;
+	fields[5].value = r_context()->boot_id;
 	g_log_structured_array(G_LOG_LEVEL_MESSAGE, fields, G_N_ELEMENTS(fields));
 }