report-basic: also report /etc/machine-info fields, just like os-release fields

The TAGS= field is really nice to have in reports, hence make this a
thing.
This commit is contained in:
Lennart Poettering
2026-05-22 12:17:09 +02:00
parent 469de233a3
commit ef9eddd202
2 changed files with 105 additions and 0 deletions
+65
View File
@@ -9,7 +9,9 @@
#include "alloc-util.h"
#include "architecture.h"
#include "cpu-set-util.h"
#include "env-file.h"
#include "hostname-setup.h"
#include "hostname-util.h"
#include "limits-util.h"
#include "log.h"
#include "metrics.h"
@@ -198,6 +200,51 @@ static int os_release_generate(const MetricFamily mf[static _FIELD_MAX - 1], sd_
return 0;
}
static int machine_info_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
enum {
MACHINE_INFO_FIELD_PRETTY_HOSTNAME,
MACHINE_INFO_FIELD_DEPLOYMENT,
MACHINE_INFO_FIELD_LOCATION,
MACHINE_INFO_FIELD_TAGS,
_MACHINE_INFO_FIELD_MAX,
};
char* values[_MACHINE_INFO_FIELD_MAX] = {};
CLEANUP_ELEMENTS(values, free_many_charp);
int r;
assert(mf && mf->name);
assert(link);
r = parse_env_file(/* f= */ NULL, etc_machine_info(),
"PRETTY_HOSTNAME", &values[MACHINE_INFO_FIELD_PRETTY_HOSTNAME],
"DEPLOYMENT", &values[MACHINE_INFO_FIELD_DEPLOYMENT],
"LOCATION", &values[MACHINE_INFO_FIELD_LOCATION],
"TAGS", &values[MACHINE_INFO_FIELD_TAGS]);
if (r < 0) {
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read machine-info file, ignoring: %m");
return 0;
}
for (size_t i = 0; i < _MACHINE_INFO_FIELD_MAX; i++) {
const char *v = values[i];
if (!v)
continue;
r = metric_build_send_string(
mf + i,
link,
/* object= */ NULL,
v,
/* fields= */ NULL);
if (r < 0)
return r;
}
return 0;
}
static int virtualization_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
assert(mf && mf->name);
assert(link);
@@ -222,6 +269,14 @@ static int virtualization_generate(const MetricFamily *mf, sd_varlink *link, voi
.generate = NULL, \
}
#define MACHINE_INFO_STANDARD_FIELD(name) \
{ \
METRIC_IO_SYSTEMD_BASIC_PREFIX "MachineInfo." name, \
"Machine identification (" name "= field from machine-info)", \
METRIC_FAMILY_TYPE_STRING, \
.generate = NULL, \
}
static const MetricFamily metric_family_table[] = {
/* Keep entries ordered alphabetically */
{
@@ -260,6 +315,16 @@ static const MetricFamily metric_family_table[] = {
METRIC_FAMILY_TYPE_STRING,
.generate = machine_id_generate,
},
{
METRIC_IO_SYSTEMD_BASIC_PREFIX "MachineInfo.PRETTY_HOSTNAME",
"Pretty hostname (PRETTY_HOSTNAME= field from machine-info)",
METRIC_FAMILY_TYPE_STRING,
.generate = machine_info_generate,
},
MACHINE_INFO_STANDARD_FIELD("DEPLOYMENT"),
MACHINE_INFO_STANDARD_FIELD("LOCATION"),
MACHINE_INFO_STANDARD_FIELD("TAGS"),
/* Keep those ↑ in sync with machine_info_generate(). */
{
METRIC_IO_SYSTEMD_BASIC_PREFIX "OSRelease.NAME",
"Operating system human-readable name (PRETTY_NAME= or NAME= field from os-release)",
+40
View File
@@ -62,6 +62,46 @@ id1="$(varlinkctl call --more /run/systemd/report/io.systemd.Basic io.systemd.Me
id2="$(. /etc/os-release; echo "$ID")"
[ "$id1" = "$id2" ]
# test io.systemd.Basic.MachineInfo.* metrics, sourced from /etc/machine-info
if [ -e /etc/machine-info ]; then
MACHINE_INFO_BACKUP="$(mktemp)"
cp /etc/machine-info "$MACHINE_INFO_BACKUP"
MACHINE_INFO_EXISTED=1
else
MACHINE_INFO_EXISTED=0
fi
restore_machine_info() {
set +e
if [ "$MACHINE_INFO_EXISTED" = 1 ]; then
cp "$MACHINE_INFO_BACKUP" /etc/machine-info
rm -f "$MACHINE_INFO_BACKUP"
else
rm -f /etc/machine-info
fi
set -e
}
trap restore_machine_info EXIT
cat >/etc/machine-info <<EOF
PRETTY_HOSTNAME="Test Machine"
DEPLOYMENT=test
LOCATION="Test Lab, Rack 3"
TAGS=foo:bar:baz
EOF
# The metric source re-reads /etc/machine-info on every call, so no service restart is needed.
machine_info_metrics="$(varlinkctl call --more /run/systemd/report/io.systemd.Basic io.systemd.Metrics.List {})"
machine_info_value() { echo "$machine_info_metrics" | jq --seq -r "select(.name == \"$1\") | .value"; }
[ "$(machine_info_value io.systemd.Basic.MachineInfo.PRETTY_HOSTNAME)" = "Test Machine" ]
[ "$(machine_info_value io.systemd.Basic.MachineInfo.DEPLOYMENT)" = "test" ]
[ "$(machine_info_value io.systemd.Basic.MachineInfo.LOCATION)" = "Test Lab, Rack 3" ]
[ "$(machine_info_value io.systemd.Basic.MachineInfo.TAGS)" = "foo:bar:baz" ]
restore_machine_info
trap - EXIT
# Test HTTP upload (plain http)
FAKE_SERVER=/usr/lib/systemd/tests/integration-tests/TEST-74-AUX-UTILS/TEST-74-AUX-UTILS.units/fake-report-server.py
CERTDIR=$(mktemp -d)