Skip to content

Commit b39439c

Browse files
committed
[metrics] Add basic CLI
1 parent 5de43f9 commit b39439c

7 files changed

Lines changed: 213 additions & 1 deletion

File tree

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,7 @@ subdir('src/random-seed')
23832383
subdir('src/rc-local-generator')
23842384
subdir('src/remount-fs')
23852385
subdir('src/repart')
2386+
subdir('src/report')
23862387
subdir('src/reply-password')
23872388
subdir('src/resolve')
23882389
subdir('src/rfkill')

src/core/varlink-metrics.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,9 @@ static int unit_types_total_build_json(sd_varlink *link, void *userdata, bool mo
109109
assert(manager);
110110

111111
UnitType *t, *previous_type = NULL;
112+
UnitType type;
112113
for (int i = 0; i < _UNIT_TYPE_MAX; i++) {
113-
UnitType type = (UnitType) i;
114+
type = (UnitType) i;
114115
t = &type;
115116

116117
if (previous_type) {

src/report/meson.build

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: LGPL-2.1-or-later
2+
3+
executables += [
4+
executable_template + {
5+
'name' : 'systemd-report',
6+
'public' : true,
7+
'sources' : files('report.c'),
8+
},
9+
]

src/report/report.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2+
3+
#include <getopt.h>
4+
5+
#include "build.h"
6+
#include "log.h"
7+
#include "main-func.h"
8+
#include "metrics.h"
9+
10+
static int help(void) {
11+
printf("%s [OPTIONS...]\n\n"
12+
"Print metrics for all systemd components .\n\n"
13+
" -h --help Show this help\n"
14+
" --version Show package version\n",
15+
program_invocation_short_name);
16+
17+
return 0;
18+
}
19+
20+
static int parse_argv(int argc, char *argv[]) {
21+
22+
enum {
23+
ARG_VERSION = 0x100
24+
};
25+
26+
static const struct option options[] = {
27+
{ "help", no_argument, NULL, 'h' },
28+
{ "version", no_argument, NULL, ARG_VERSION },
29+
{}
30+
};
31+
32+
int c;
33+
34+
assert(argc >= 0);
35+
assert(argv);
36+
37+
while ((c = getopt_long(argc, argv, "hp", options, NULL)) >= 0)
38+
39+
switch (c) {
40+
41+
case 'h':
42+
return help();
43+
44+
case ARG_VERSION:
45+
return version();
46+
47+
case '?':
48+
return -EINVAL;
49+
50+
default:
51+
assert_not_reached();
52+
}
53+
54+
if (optind < argc)
55+
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
56+
"%s takes no arguments.",
57+
program_invocation_short_name);
58+
59+
return 1;
60+
}
61+
62+
static int run(int argc, char *argv[]) {
63+
_cleanup_(sd_json_variant_unrefp) sd_json_variant *ret = NULL;
64+
int r;
65+
66+
/* This is mostly intended to be used for scripts which want
67+
* to detect whether we are being run in a virtualized
68+
* environment or not */
69+
70+
log_setup();
71+
72+
r = parse_argv(argc, argv);
73+
if (r <= 0)
74+
return r;
75+
76+
r = metrics_query_all(&ret);
77+
if (r < 0)
78+
return r;
79+
80+
return 0;
81+
}
82+
83+
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);

src/shared/metrics.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include <assert.h>
22

3+
#include "alloc-util.h"
4+
#include "dirent-util.h"
5+
#include "fd-util.h"
36
#include "log.h"
47
#include "metrics.h"
58
#include "varlink-serialize.h"
@@ -72,3 +75,112 @@ const char* metric_type_to_string(MetricType t) {
7275
return "UNKNOWN";
7376
}
7477
}
78+
79+
static int metrics_on_query_reply(
80+
sd_varlink *link,
81+
sd_json_variant *parameters,
82+
const char *error,
83+
sd_varlink_reply_flags_t flags,
84+
void *userdata) {
85+
86+
int *ret = ASSERT_PTR(userdata), r;
87+
88+
assert(link);
89+
90+
if (error) {
91+
/* If we can translate this to an errno, let's print that as errno and return it, otherwise, return a generic error code */
92+
r = sd_varlink_error_to_errno(error, parameters);
93+
if (r != -EBADR)
94+
*ret = log_error_errno(r, "Method call failed: %m");
95+
else
96+
r = *ret = log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call failed: %s", error);
97+
} else
98+
r = 0;
99+
100+
sd_json_variant_dump(parameters, SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO, stdout, NULL);
101+
102+
return r;
103+
}
104+
105+
static int metrics_call(const char *path) {
106+
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
107+
int r;
108+
109+
assert(path);
110+
111+
r = sd_varlink_connect_address(&vl, path);
112+
if (r < 0)
113+
return log_debug_errno(r, "Unable to connect to %s: %m", path);
114+
115+
int ret = 0;
116+
sd_varlink_set_userdata(vl, &ret);
117+
118+
r = sd_varlink_bind_reply(vl, metrics_on_query_reply);
119+
if (r < 0)
120+
return log_debug_errno(r, "Failed to bind reply callback: %m");
121+
122+
sd_varlink_observe(vl, "io.systemd.Metrics.List", /* parameter */ NULL);
123+
if (r < 0)
124+
return log_debug_errno(r, "Failed to invoke varlink method: %m");
125+
126+
for (;;) {
127+
r = sd_varlink_is_idle(vl);
128+
129+
if (r < 0)
130+
return log_error_errno(r, "Failed to check if varlink connection is idle: %m");
131+
if (r > 0) {
132+
break;
133+
}
134+
135+
r = sd_varlink_process(vl);
136+
if (r < 0)
137+
return log_error_errno(r, "Failed to process varlink connection: %m");
138+
if (r != 0)
139+
continue;
140+
141+
r = sd_varlink_wait(vl, USEC_INFINITY);
142+
if (r < 0)
143+
return log_error_errno(r, "Failed to wait for varlink connection events: %m");
144+
}
145+
146+
return ret;
147+
}
148+
149+
static int metrics_start_query(void) {
150+
_cleanup_closedir_ DIR *d = NULL;
151+
int r;
152+
153+
d = opendir("/run/systemd/metrics/");
154+
if (!d) {
155+
if (errno == ENOENT)
156+
return -ESRCH;
157+
158+
return -errno;
159+
}
160+
161+
FOREACH_DIRENT(de, d, return -errno) {
162+
_cleanup_free_ char *p = NULL;
163+
164+
p = path_join("/run/systemd/metrics/", de->d_name);
165+
if (!p)
166+
return -ENOMEM;
167+
168+
r = metrics_call(p);
169+
if (r < 0)
170+
return r;
171+
}
172+
173+
return 0;
174+
}
175+
176+
int metrics_query_all(sd_json_variant **ret) {
177+
int r;
178+
179+
assert(ret);
180+
181+
r = metrics_start_query();
182+
if (r < 0)
183+
return r;
184+
185+
return 0;
186+
}

src/shared/metrics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#pragma once
22

33
#include "forward.h"
4+
#include "sd-json.h"
45
#include "sd-varlink.h"
56

7+
int metrics_query_all(sd_json_variant **ret);
8+
69
int metrics_setup_varlink_server(
710
sd_varlink_server **server, /* in and out param */
811
sd_varlink_server_flags_t flags,

test/units/TEST-74-AUX-UTILS.varlinkctl.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ systemd-run --wait --pipe --user --machine testuser@ \
210210
systemd-run --wait --pipe --user --machine testuser@ \
211211
varlinkctl call "/run/user/$testuser_uid/systemd/io.systemd.Manager" io.systemd.Manager.Describe '{}'
212212

213+
# test report in user manager
214+
systemd-report
215+
213216
# test io.systemd.Unit in user manager
214217
systemd-run --wait --pipe --user --machine testuser@ \
215218
varlinkctl --more call "/run/user/$testuser_uid/systemd/io.systemd.Manager" io.systemd.Unit.List '{}'

0 commit comments

Comments
 (0)