report: add more metrics to the Varlink metrics API (#41078)
This commit is contained in:
+244
-1
@@ -11,6 +11,118 @@
|
||||
#include "unit.h"
|
||||
#include "varlink-metrics.h"
|
||||
|
||||
static int active_timestamp_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
Unit *unit;
|
||||
char *key;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *enter_fields = NULL;
|
||||
r = sd_json_buildo(&enter_fields, SD_JSON_BUILD_PAIR_STRING("event", "enter"));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *exit_fields = NULL;
|
||||
r = sd_json_buildo(&exit_fields, SD_JSON_BUILD_PAIR_STRING("event", "exit"));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
HASHMAP_FOREACH_KEY(unit, key, manager->units) {
|
||||
/* ignore aliases */
|
||||
if (key != unit->id)
|
||||
continue;
|
||||
|
||||
r = metric_build_send_unsigned(
|
||||
context,
|
||||
unit->id,
|
||||
unit->active_enter_timestamp.realtime,
|
||||
enter_fields);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = metric_build_send_unsigned(
|
||||
context,
|
||||
unit->id,
|
||||
unit->active_exit_timestamp.realtime,
|
||||
exit_fields);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inactive_exit_timestamp_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
Unit *unit;
|
||||
char *key;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
HASHMAP_FOREACH_KEY(unit, key, manager->units) {
|
||||
/* ignore aliases */
|
||||
if (key != unit->id)
|
||||
continue;
|
||||
|
||||
r = metric_build_send_unsigned(
|
||||
context,
|
||||
unit->id,
|
||||
unit->inactive_exit_timestamp.realtime,
|
||||
/* fields= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int state_change_timestamp_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
Unit *unit;
|
||||
char *key;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
HASHMAP_FOREACH_KEY(unit, key, manager->units) {
|
||||
/* ignore aliases */
|
||||
if (key != unit->id)
|
||||
continue;
|
||||
|
||||
r = metric_build_send_unsigned(
|
||||
context,
|
||||
unit->id,
|
||||
unit->state_change_timestamp.realtime,
|
||||
/* fields= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int status_errno_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
LIST_FOREACH(units_by_type, unit, manager->units_by_type[UNIT_SERVICE]) {
|
||||
r = metric_build_send_unsigned(
|
||||
context,
|
||||
unit->id,
|
||||
(uint64_t) SERVICE(unit)->status_errno,
|
||||
/* fields= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unit_active_state_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
Unit *unit;
|
||||
@@ -108,7 +220,7 @@ static int units_by_type_total_build_json(MetricFamilyContext *context, void *us
|
||||
|
||||
static int units_by_state_total_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
UnitActiveState counters[_UNIT_ACTIVE_STATE_MAX] = {};
|
||||
uint64_t counters[_UNIT_ACTIVE_STATE_MAX] = {};
|
||||
Unit *unit;
|
||||
char *key;
|
||||
int r;
|
||||
@@ -143,14 +255,133 @@ static int units_by_state_total_build_json(MetricFamilyContext *context, void *u
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jobs_queued_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
|
||||
assert(context);
|
||||
|
||||
return metric_build_send_unsigned(
|
||||
context,
|
||||
/* object= */ NULL,
|
||||
hashmap_size(manager->jobs),
|
||||
/* fields= */ NULL);
|
||||
}
|
||||
|
||||
static int system_state_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
|
||||
assert(context);
|
||||
|
||||
return metric_build_send_string(
|
||||
context,
|
||||
/* object= */ NULL,
|
||||
manager_state_to_string(manager_state(manager)),
|
||||
/* fields= */ NULL);
|
||||
}
|
||||
|
||||
static int units_by_load_state_total_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
uint64_t counters[_UNIT_LOAD_STATE_MAX] = {};
|
||||
Unit *unit;
|
||||
char *key;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
HASHMAP_FOREACH_KEY(unit, key, manager->units) {
|
||||
/* ignore aliases */
|
||||
if (key != unit->id)
|
||||
continue;
|
||||
|
||||
counters[unit->load_state]++;
|
||||
}
|
||||
|
||||
for (UnitLoadState state = 0; state < _UNIT_LOAD_STATE_MAX; state++) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *fields = NULL;
|
||||
|
||||
r = sd_json_buildo(&fields, SD_JSON_BUILD_PAIR_STRING("load_state", unit_load_state_to_string(state)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = metric_build_send_unsigned(
|
||||
context,
|
||||
/* object= */ NULL,
|
||||
counters[state],
|
||||
fields);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int units_total_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
uint64_t count = 0;
|
||||
Unit *unit;
|
||||
char *key;
|
||||
|
||||
assert(context);
|
||||
|
||||
HASHMAP_FOREACH_KEY(unit, key, manager->units) {
|
||||
/* ignore aliases */
|
||||
if (key != unit->id)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return metric_build_send_unsigned(
|
||||
context,
|
||||
/* object= */ NULL,
|
||||
count,
|
||||
/* fields= */ NULL);
|
||||
}
|
||||
|
||||
static const MetricFamily metric_family_table[] = {
|
||||
/* Keep metrics ordered alphabetically */
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "ActiveTimestamp",
|
||||
.description = "Per unit metric: timestamp of active state transitions in microseconds; 0 indicates the transition has not occurred",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = active_timestamp_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "InactiveExitTimestamp",
|
||||
.description = "Per unit metric: timestamp when the unit last exited the inactive state in microseconds; 0 indicates the transition has not occurred",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = inactive_exit_timestamp_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "JobsQueued",
|
||||
.description = "Number of jobs currently queued",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = jobs_queued_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "NRestarts",
|
||||
.description = "Per unit metric: number of restarts",
|
||||
.type = METRIC_FAMILY_TYPE_COUNTER,
|
||||
.generate = nrestarts_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "StateChangeTimestamp",
|
||||
.description = "Per unit metric: timestamp of the last state change in microseconds; 0 indicates no state change has occurred",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = state_change_timestamp_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "StatusErrno",
|
||||
.description = "Per service metric: errno status of the service",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = status_errno_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "SystemState",
|
||||
.description = "Overall system state",
|
||||
.type = METRIC_FAMILY_TYPE_STRING,
|
||||
.generate = system_state_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "UnitActiveState",
|
||||
.description = "Per unit metric: active state",
|
||||
@@ -163,6 +394,12 @@ static const MetricFamily metric_family_table[] = {
|
||||
.type = METRIC_FAMILY_TYPE_STRING,
|
||||
.generate = unit_load_state_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "UnitsByLoadStateTotal",
|
||||
.description = "Total number of units by load state",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = units_by_load_state_total_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "UnitsByStateTotal",
|
||||
.description = "Total number of units of different state",
|
||||
@@ -175,6 +412,12 @@ static const MetricFamily metric_family_table[] = {
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = units_by_type_total_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_MANAGER_PREFIX "UnitsTotal",
|
||||
.description = "Total number of units",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = units_total_build_json,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-json.h"
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "argv-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
@@ -99,6 +101,55 @@ static int managed_interfaces_build_json(MetricFamilyContext *context, void *use
|
||||
return metric_build_send_unsigned(context, /* object= */ NULL, count, /* fields= */ NULL);
|
||||
}
|
||||
|
||||
static int required_for_online_build_json(MetricFamilyContext *context, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(context);
|
||||
|
||||
HASHMAP_FOREACH(link, manager->links_by_index) {
|
||||
if (!link->network)
|
||||
continue;
|
||||
|
||||
if (link->network->required_for_online == 0) {
|
||||
r = metric_build_send_string(
|
||||
context,
|
||||
link->ifname,
|
||||
"no",
|
||||
/* fields= */ NULL);
|
||||
} else {
|
||||
LinkOperationalStateRange range;
|
||||
link_required_operstate_for_online(link, &range);
|
||||
|
||||
const char *min_str = link_operstate_to_string(range.min);
|
||||
const char *max_str = link_operstate_to_string(range.max);
|
||||
|
||||
if (range.min == range.max)
|
||||
r = metric_build_send_string(
|
||||
context,
|
||||
link->ifname,
|
||||
min_str,
|
||||
/* fields= */ NULL);
|
||||
else {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
if (asprintf(&value, "%s:%s", min_str, max_str) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = metric_build_send_string(
|
||||
context,
|
||||
link->ifname,
|
||||
value,
|
||||
/* fields= */ NULL);
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Keep metrics ordered alphabetically */
|
||||
static const MetricFamily network_metric_family_table[] = {
|
||||
{
|
||||
@@ -143,6 +194,12 @@ static const MetricFamily network_metric_family_table[] = {
|
||||
.type = METRIC_FAMILY_TYPE_STRING,
|
||||
.generate = link_oper_state_build_json,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_NETWORK_PREFIX "RequiredForOnline",
|
||||
.description = "Per interface metric: required operational state for online, or 'no' if not required",
|
||||
.type = METRIC_FAMILY_TYPE_STRING,
|
||||
.generate = required_for_online_build_json,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
#include "varlink-idl-util.h"
|
||||
#include "verbs.h"
|
||||
|
||||
#define METRICS_OR_FACTS_MAX 1024U
|
||||
#define METRICS_OR_FACTS_MAX 4096U
|
||||
#define METRICS_OR_FACTS_LINKS_MAX 128U
|
||||
#define TIMEOUT_USEC (30 * USEC_PER_SEC) /* 30 seconds */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user