Skip to content

Commit c402760

Browse files
committed
[metrics] Add basic CLI
1 parent e2c1002 commit c402760

6 files changed

Lines changed: 215 additions & 5 deletions

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
@@ -108,8 +108,9 @@ static int unit_types_total_build_json(sd_varlink *link, void *userdata, bool mo
108108
assert(manager);
109109

110110
UnitType *t, *previous_type = NULL;
111+
UnitType type;
111112
for (int i = 0; i < _UNIT_TYPE_MAX; i++) {
112-
UnitType type = (UnitType) i;
113+
type = (UnitType) i;
113114
t = &type;
114115

115116
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: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2+
3+
#include <getopt.h>
4+
5+
#include "alloc-util.h"
6+
#include "build.h"
7+
#include "dirent-util.h"
8+
#include "fd-util.h"
9+
#include "log.h"
10+
#include "main-func.h"
11+
#include "sd-varlink.h"
12+
13+
static int metrics_on_query_reply(
14+
sd_varlink *link,
15+
sd_json_variant *parameters,
16+
const char *error,
17+
sd_varlink_reply_flags_t flags,
18+
void *userdata) {
19+
20+
int *ret = ASSERT_PTR(userdata), r;
21+
22+
assert(link);
23+
24+
if (error) {
25+
/* If we can translate this to an errno, let's print that as errno and return it, otherwise, return a generic error code */
26+
r = sd_varlink_error_to_errno(error, parameters);
27+
if (r != -EBADR)
28+
*ret = log_error_errno(r, "Method call failed: %m");
29+
else
30+
r = *ret = log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call failed: %s", error);
31+
} else
32+
r = 0;
33+
34+
sd_json_variant_dump(parameters, SD_JSON_FORMAT_PRETTY_AUTO|SD_JSON_FORMAT_COLOR_AUTO, stdout, NULL);
35+
36+
return r;
37+
}
38+
39+
static int metrics_call(const char *path) {
40+
_cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
41+
int r;
42+
43+
assert(path);
44+
45+
r = sd_varlink_connect_address(&vl, path);
46+
if (r < 0)
47+
return log_debug_errno(r, "Unable to connect to %s: %m", path);
48+
49+
int ret = 0;
50+
sd_varlink_set_userdata(vl, &ret);
51+
52+
r = sd_varlink_bind_reply(vl, metrics_on_query_reply);
53+
if (r < 0)
54+
return log_debug_errno(r, "Failed to bind reply callback: %m");
55+
56+
r = sd_varlink_observe(vl, "io.systemd.Metrics.List", /* parameter */ NULL);
57+
if (r < 0)
58+
return log_debug_errno(r, "Failed to invoke varlink method: %m");
59+
60+
for (;;) {
61+
r = sd_varlink_is_idle(vl);
62+
63+
if (r < 0)
64+
return log_error_errno(r, "Failed to check if varlink connection is idle: %m");
65+
if (r > 0) {
66+
break;
67+
}
68+
69+
r = sd_varlink_process(vl);
70+
if (r < 0)
71+
return log_error_errno(r, "Failed to process varlink connection: %m");
72+
if (r != 0)
73+
continue;
74+
75+
r = sd_varlink_wait(vl, USEC_INFINITY);
76+
if (r < 0)
77+
return log_error_errno(r, "Failed to wait for varlink connection events: %m");
78+
}
79+
80+
return ret;
81+
}
82+
83+
static int metrics_start_query(void) {
84+
_cleanup_closedir_ DIR *d = NULL;
85+
int r;
86+
87+
d = opendir("/run/systemd/metrics/");
88+
if (!d) {
89+
if (errno == ENOENT)
90+
return -ESRCH;
91+
92+
return -errno;
93+
}
94+
95+
FOREACH_DIRENT(de, d, return -errno) {
96+
_cleanup_free_ char *p = NULL;
97+
98+
p = path_join("/run/systemd/metrics/", de->d_name);
99+
if (!p)
100+
return -ENOMEM;
101+
102+
r = metrics_call(p);
103+
if (r < 0)
104+
return r;
105+
}
106+
107+
return 0;
108+
}
109+
110+
static int help(void) {
111+
printf("%s [OPTIONS...]\n\n"
112+
"Print metrics for all systemd components .\n\n"
113+
" -h --help Show this help\n"
114+
" --version Show package version\n",
115+
program_invocation_short_name);
116+
117+
return 0;
118+
}
119+
120+
static int parse_argv(int argc, char *argv[]) {
121+
122+
enum {
123+
ARG_VERSION = 0x100
124+
};
125+
126+
static const struct option options[] = {
127+
{ "help", no_argument, NULL, 'h' },
128+
{ "version", no_argument, NULL, ARG_VERSION },
129+
{}
130+
};
131+
132+
int c;
133+
134+
assert(argc >= 0);
135+
assert(argv);
136+
137+
while ((c = getopt_long(argc, argv, "hp", options, NULL)) >= 0)
138+
139+
switch (c) {
140+
141+
case 'h':
142+
return help();
143+
144+
case ARG_VERSION:
145+
return version();
146+
147+
case '?':
148+
return -EINVAL;
149+
150+
default:
151+
assert_not_reached();
152+
}
153+
154+
if (optind < argc)
155+
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
156+
"%s takes no arguments.",
157+
program_invocation_short_name);
158+
159+
return 1;
160+
}
161+
162+
static int run(int argc, char *argv[]) {
163+
int r;
164+
165+
/* This is mostly intended to be used for scripts which want
166+
* to detect whether we are being run in a virtualized
167+
* environment or not */
168+
169+
log_setup();
170+
171+
r = parse_argv(argc, argv);
172+
if (r <= 0)
173+
return r;
174+
175+
r = metrics_start_query();
176+
if (r < 0)
177+
return r;
178+
179+
return 0;
180+
}
181+
182+
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);

src/shared/metrics.h

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

3-
#include "forward.h"
3+
#include "sd-json.h"
44
#include "sd-varlink.h"
55

6-
76
#include "forward.h"
87

98
typedef enum MetricFamilyType {
@@ -32,5 +31,20 @@ int metrics_setup_varlink_server(
3231
void *userdata);
3332

3433
int metrics_listen_varlink_address(sd_varlink_server *server, const char *address);
35-
36-
const char* metric_family_type_to_string(MetricFamilyType t) _const_;int metric_family_json_build(sd_json_variant **v, const MetricFamily *metric_family);#define METRIC_FAMILY(_name, _description, _type, _cb) \ { \ .name = _name, \ .description = _description, \ .type = _type, \ .cb = _cb, \ }#define METRIC_JSON_BUILD_UNSIGNED(_v, _name, _object, _value, ...) metric_json_build_unsigned(_v, _name, _object, _value, STRV_MAKE(__VA_ARGS__))#define METRIC_JSON_BUILD_INTEGER(_v, _name, object, value, ...) metric_json_build_integer(_v, _name, _object, _value, STRV_MAKE(__VA_ARGS__))#define METRIC_JSON_BUILD_STRING(_v, _name, object, value, ...) metric_json_build_string(_v, _name, _object, _value, STRV_MAKE(__VA_ARGS__))int metric_json_build_unsigned(sd_json_variant **v, const char *name, const char *object, uint64_t value, char **fields);int metric_json_build_integer(sd_json_variant **v, const char *name, const char *object, int64_t value, char **fields);int metric_json_build_string(sd_json_variant **v, const char *name, const char *object, const char *value, char **fields);
34+
const char* metric_family_type_to_string(MetricFamilyType t) _const_;
35+
int metric_family_json_build(sd_json_variant **v, const MetricFamily *metric_family);
36+
37+
#define METRIC_FAMILY(_name, _description, _type, _cb) \
38+
{ \
39+
.name = _name, \
40+
.description = _description, \
41+
.type = _type, \
42+
.cb = _cb, \
43+
}
44+
45+
#define METRIC_JSON_BUILD_UNSIGNED(_v, _name, _object, _value, ...) metric_json_build_unsigned(_v, _name, _object, _value, STRV_MAKE(__VA_ARGS__))
46+
#define METRIC_JSON_BUILD_INTEGER(_v, _name, object, value, ...) metric_json_build_integer(_v, _name, _object, _value, STRV_MAKE(__VA_ARGS__))
47+
#define METRIC_JSON_BUILD_STRING(_v, _name, object, value, ...) metric_json_build_string(_v, _name, _object, _value, STRV_MAKE(__VA_ARGS__))
48+
int metric_json_build_unsigned(sd_json_variant **v, const char *name, const char *object, uint64_t value, char **fields);
49+
int metric_json_build_integer(sd_json_variant **v, const char *name, const char *object, int64_t value, char **fields);
50+
int metric_json_build_string(sd_json_variant **v, const char *name, const char *object, const char *value, char **fields);

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)