#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;
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_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",