report-basic: also report load average + swap size in metrics report
This commit is contained in:
committed by
Lennart Poettering
parent
f7786f2508
commit
491ee4afb1
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "sd-device.h"
|
||||
@@ -142,6 +143,67 @@ static int cpus_online_generate(const MetricFamily *mf, sd_varlink *link, void *
|
||||
/* fields= */ NULL);
|
||||
}
|
||||
|
||||
static int load_average_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
|
||||
enum {
|
||||
LOAD_AVERAGE_FIELD_1MIN,
|
||||
LOAD_AVERAGE_FIELD_5MIN,
|
||||
LOAD_AVERAGE_FIELD_15MIN,
|
||||
_LOAD_AVERAGE_FIELD_MAX,
|
||||
};
|
||||
|
||||
int r;
|
||||
|
||||
assert(mf && mf->name);
|
||||
assert(link);
|
||||
|
||||
/* The classic Linux load average, i.e. the exponentially damped moving average of the number of
|
||||
* runnable plus uninterruptible tasks over the last 1, 5 and 15 minutes. The kernel exposes these as
|
||||
* fixed-point numbers shifted left by SI_LOAD_SHIFT bits. */
|
||||
|
||||
struct sysinfo info;
|
||||
if (sysinfo(&info) < 0)
|
||||
return log_debug_errno(errno, "Failed to call sysinfo(): %m");
|
||||
|
||||
assert_cc(_LOAD_AVERAGE_FIELD_MAX == ELEMENTSOF(info.loads));
|
||||
|
||||
for (size_t i = 0; i < _LOAD_AVERAGE_FIELD_MAX; i++) {
|
||||
|
||||
r = metric_build_send_double(
|
||||
mf + i,
|
||||
link,
|
||||
/* object= */ NULL,
|
||||
(double) info.loads[i] / (UINT64_C(1) << SI_LOAD_SHIFT),
|
||||
/* fields= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int swap_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
|
||||
assert(mf && mf->name);
|
||||
assert(link);
|
||||
|
||||
/* The total amount of configured swap space, in bytes. */
|
||||
|
||||
struct sysinfo info;
|
||||
if (sysinfo(&info) < 0)
|
||||
return log_debug_errno(errno, "Failed to call sysinfo(): %m");
|
||||
|
||||
/* Overflow is unrealistic (would need >16 EiB of swap), but use MUL_SAFE to make this obvious to
|
||||
* static analyzers. */
|
||||
uint64_t swap;
|
||||
assert_se(MUL_SAFE(&swap, (uint64_t) info.totalswap, (uint64_t) info.mem_unit));
|
||||
|
||||
return metric_build_send_unsigned(
|
||||
mf,
|
||||
link,
|
||||
/* object= */ NULL,
|
||||
swap,
|
||||
/* fields= */ NULL);
|
||||
}
|
||||
|
||||
enum {
|
||||
FIELD_PRETTY_NAME,
|
||||
FIELD_NAME,
|
||||
@@ -500,6 +562,25 @@ static const MetricFamily metric_family_table[] = {
|
||||
METRIC_FAMILY_TYPE_STRING,
|
||||
.generate = kernel_version_generate,
|
||||
},
|
||||
{
|
||||
METRIC_IO_SYSTEMD_BASIC_PREFIX "LoadAverage1Min",
|
||||
"System load average over the last 1 minute",
|
||||
METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = load_average_generate,
|
||||
},
|
||||
{
|
||||
METRIC_IO_SYSTEMD_BASIC_PREFIX "LoadAverage5Min",
|
||||
"System load average over the last 5 minutes",
|
||||
METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = NULL,
|
||||
},
|
||||
{
|
||||
METRIC_IO_SYSTEMD_BASIC_PREFIX "LoadAverage15Min",
|
||||
"System load average over the last 15 minutes",
|
||||
METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = NULL,
|
||||
},
|
||||
/* Keep those ↑ in sync with load_average_generate(). */
|
||||
{
|
||||
METRIC_IO_SYSTEMD_BASIC_PREFIX "MachineID",
|
||||
"Machine ID",
|
||||
@@ -568,6 +649,12 @@ static const MetricFamily metric_family_table[] = {
|
||||
SMBIOS_STANDARD_FIELD("ChassisSerialNumber"),
|
||||
SMBIOS_STANDARD_FIELD("ChassisAssetTagNumber"),
|
||||
/* Keep those ↑ in sync with smbios_generate(). */
|
||||
{
|
||||
METRIC_IO_SYSTEMD_BASIC_PREFIX "SwapBytes",
|
||||
"Total configured swap space in bytes",
|
||||
METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = swap_generate,
|
||||
},
|
||||
{
|
||||
METRIC_IO_SYSTEMD_BASIC_PREFIX "TPM2.Manufacturer",
|
||||
"TPM2 device manufacturer (ID_TPM2_MANUFACTURER property of the tpmrm0 device)",
|
||||
|
||||
@@ -209,3 +209,23 @@ int metric_build_send_unsigned(
|
||||
|
||||
return metric_build_send(mf, link, object, v, fields);
|
||||
}
|
||||
|
||||
int metric_build_send_double(
|
||||
const MetricFamily *mf,
|
||||
sd_varlink *link,
|
||||
const char *object,
|
||||
double value,
|
||||
sd_json_variant *fields) {
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
int r;
|
||||
|
||||
assert(mf);
|
||||
assert(link);
|
||||
|
||||
r = sd_json_variant_new_real(&v, value);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to allocate JSON real: %m");
|
||||
|
||||
return metric_build_send(mf, link, object, v, fields);
|
||||
}
|
||||
|
||||
@@ -38,3 +38,4 @@ int metrics_method_list(const MetricFamily mfs[], sd_varlink *link, sd_json_vari
|
||||
|
||||
int metric_build_send_string(const MetricFamily* mf, sd_varlink *link, const char *object, const char *value, sd_json_variant *fields);
|
||||
int metric_build_send_unsigned(const MetricFamily* mf, sd_varlink *link, const char *object, uint64_t value, sd_json_variant *fields);
|
||||
int metric_build_send_double(const MetricFamily* mf, sd_varlink *link, const char *object, double value, sd_json_variant *fields);
|
||||
|
||||
@@ -62,6 +62,24 @@ 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 load average and swap metrics
|
||||
basic_metrics="$(varlinkctl call --more /run/systemd/report/io.systemd.Basic io.systemd.Metrics.List {})"
|
||||
# NB: '| tostring' turns the numeric value into a raw string, so 'jq -r' prints it cleanly
|
||||
# (numbers, unlike strings, are otherwise still emitted with the json-seq record separator).
|
||||
basic_value() { echo "$basic_metrics" | jq --seq -r "select(.name == \"$1\") | .value | tostring"; }
|
||||
|
||||
# The three classic load average fields must be present and numeric (jq's 'numbers' filter
|
||||
# emits the value only if it is a JSON number, so a non-empty result confirms both).
|
||||
for field in LoadAverage1Min LoadAverage5Min LoadAverage15Min; do
|
||||
loadavg="$(echo "$basic_metrics" | jq --seq -r "select(.name == \"io.systemd.Basic.$field\") | .value | numbers | tostring")"
|
||||
test -n "$loadavg"
|
||||
done
|
||||
|
||||
# SwapBytes must match the total the kernel reports in /proc/meminfo (which is in kB).
|
||||
swap_reported="$(basic_value io.systemd.Basic.SwapBytes)"
|
||||
swap_expected=$(( $(awk '/^SwapTotal:/ { print $2; found=1 } END { if (!found) print 0 }' /proc/meminfo) * 1024 ))
|
||||
[ "$swap_reported" = "$swap_expected" ]
|
||||
|
||||
# test io.systemd.Basic.MachineInfo.* metrics, sourced from /etc/machine-info
|
||||
if [ -e /etc/machine-info ]; then
|
||||
MACHINE_INFO_BACKUP="$(mktemp)"
|
||||
|
||||
Reference in New Issue
Block a user