#include "verbs.h"
#include "web-util.h"
-#define METRICS_OR_FACTS_MAX 4096U
-#define METRICS_OR_FACTS_LINKS_MAX 128U
+#define METRICS_MAX 4096U
+#define METRICS_LINKS_MAX 128U
#define TIMEOUT_USEC (30 * USEC_PER_SEC) /* 30 seconds */
static PagerFlags arg_pager_flags = 0;
static const char* const action_method_table[] = {
[ACTION_LIST_METRICS] = "io.systemd.Metrics.List",
[ACTION_DESCRIBE_METRICS] = "io.systemd.Metrics.Describe",
- [ACTION_LIST_FACTS] = "io.systemd.Facts.List",
- [ACTION_DESCRIBE_FACTS] = "io.systemd.Facts.Describe",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(action_method, Action);
goto finish;
}
- if (context->n_metrics >= METRICS_OR_FACTS_MAX) {
+ if (context->n_metrics >= METRICS_MAX) {
context->n_skipped_metrics++;
goto finish;
}
return 0;
}
-static int facts_output_list(Context *context, Table **ret) {
- int r;
-
- assert(context);
- assert(ret);
-
- _cleanup_(table_unrefp) Table *table = table_new("family", "object", "value");
- if (!table)
- return log_oom();
-
- table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
- table_set_sort(table, (size_t) 0, (size_t) 1, (size_t) 2);
-
- FOREACH_ARRAY(m, context->metrics, context->n_metrics) {
- struct {
- const char *name;
- const char *object;
- sd_json_variant *value;
- } d = {};
-
- static const sd_json_dispatch_field dispatch_table[] = {
- { "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(d, name), SD_JSON_MANDATORY },
- { "object", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(d, object), 0 },
- { "value", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_variant_noref, voffsetof(d, value), SD_JSON_MANDATORY },
- {}
- };
-
- r = sd_json_dispatch(*m, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &d);
- if (r < 0) {
- _cleanup_free_ char *t = NULL;
- int k = sd_json_variant_format(*m, /* flags= */ 0, &t);
- if (k < 0)
- return log_error_errno(k, "Failed to format JSON: %m");
-
- log_warning_errno(r, "Cannot parse fact, skipping: %s", t);
- continue;
- }
-
- r = table_add_many(
- table,
- TABLE_STRING, d.name,
- TABLE_STRING, d.object,
- TABLE_JSON, d.value,
- TABLE_SET_WEIGHT, 50U);
- if (r < 0)
- return table_log_add_error(r);
- }
-
- *ret = TAKE_PTR(table);
- return 0;
-}
-
-static int facts_output_describe(Context *context, Table **ret) {
- int r;
-
- assert(context);
- assert(ret);
-
- _cleanup_(table_unrefp) Table *table = table_new("family", "description");
- if (!table)
- return log_oom();
-
- table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
- table_set_sort(table, (size_t) 0, (size_t) 1);
-
- FOREACH_ARRAY(m, context->metrics, context->n_metrics) {
- struct {
- const char *name;
- const char *description;
- } d = {};
-
- static const sd_json_dispatch_field dispatch_table[] = {
- { "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(d, name), SD_JSON_MANDATORY },
- { "description", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(d, description), 0 },
- {}
- };
-
- r = sd_json_dispatch(*m, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &d);
- if (r < 0) {
- _cleanup_free_ char *t = NULL;
- int k = sd_json_variant_format(*m, /* flags= */ 0, &t);
- if (k < 0)
- return log_error_errno(k, "Failed to format JSON: %m");
-
- log_warning_errno(r, "Cannot parse fact description, skipping: %s", t);
- continue;
- }
-
- r = table_add_many(
- table,
- TABLE_STRING, d.name,
- TABLE_STRING, d.description,
- TABLE_SET_WEIGHT, 50U);
- if (r < 0)
- return table_log_add_error(r);
- }
-
- *ret = TAKE_PTR(table);
- return 0;
-}
-
static int output_collected(Context *context) {
int r;
return log_error_errno(r, "Failed to write JSON: %m");
}
- if (context->n_metrics == 0 && arg_legend) {
- if (IN_SET(context->action, ACTION_LIST_FACTS, ACTION_DESCRIBE_FACTS))
- log_info("No facts collected.");
- else
- log_info("No metrics collected.");
- }
-
+ if (context->n_metrics == 0 && arg_legend)
+ log_info("No metrics collected.");
return 0;
}
r = output_collected_describe(context, &table);
break;
- case ACTION_LIST_FACTS:
- r = facts_output_list(context, &table);
- break;
-
- case ACTION_DESCRIBE_FACTS:
- r = facts_output_describe(context, &table);
- break;
-
default:
assert_not_reached();
}
}
if (arg_legend && !sd_json_format_enabled(arg_json_format_flags)) {
- const char *type = IN_SET(context->action, ACTION_LIST_FACTS, ACTION_DESCRIBE_FACTS) ? "facts" : "metrics";
-
if (table_isempty(table))
- printf("No %s available.\n", type);
+ printf("No metrics available.\n");
else
- printf("\n%zu %s listed.\n", table_get_rows(table) - 1, type);
+ printf("\n%zu metrics listed.\n", table_get_rows(table) - 1);
}
return 0;
VERB_FULL(verb_metrics, "metrics", "[MATCH…]", VERB_ANY, VERB_ANY, 0, ACTION_LIST_METRICS,
"Acquire list of metrics and their values");
-VERB_FULL(verb_metrics, "describe-metrics", "[MATCH…]", VERB_ANY, VERB_ANY, 0, ACTION_DESCRIBE_METRICS,
+VERB_FULL(verb_metrics, "describe", "[MATCH…]", VERB_ANY, VERB_ANY, 0, ACTION_DESCRIBE_METRICS,
"Describe available metrics");
static int verb_metrics(int argc, char *argv[], uintptr_t data, void *userdata) {
Action action = data;
FOREACH_ARRAY(i, de->entries, de->n_entries) {
struct dirent *d = *i;
- if (set_size(context.link_infos) >= METRICS_OR_FACTS_LINKS_MAX) {
+ if (set_size(context.link_infos) >= METRICS_LINKS_MAX) {
n_skipped_sources++;
break;
}
return 0;
}
-VERB_FULL(verb_facts, "facts", "[MATCH…]", VERB_ANY, VERB_ANY, 0, ACTION_LIST_FACTS,
- "Acquire list of facts and their values");
-VERB_FULL(verb_facts, "describe-facts", "[MATCH…]", VERB_ANY, VERB_ANY, 0, ACTION_DESCRIBE_FACTS,
- "Describe available facts");
-static int verb_facts(int argc, char *argv[], uintptr_t data, void *userdata) {
- Action action = data;
- int r;
-
- assert(argc >= 1);
- assert(argv);
- assert(IN_SET(action, ACTION_LIST_FACTS, ACTION_DESCRIBE_FACTS));
-
- /* Enable JSON-SEQ mode here, since we'll dump a large series of JSON objects */
- arg_json_format_flags |= SD_JSON_FORMAT_SEQ;
-
- r = parse_metrics_matches(argv + 1);
- if (r < 0)
- return r;
-
- _cleanup_(context_done) Context context = {
- .action = action,
- };
- size_t n_skipped_sources = 0;
-
- _cleanup_free_ DirectoryEntries *de = NULL;
- _cleanup_free_ char *sources_path = NULL;
- r = readdir_sources(&sources_path, &de);
- if (r < 0)
- return r;
- if (r > 0) {
- r = sd_event_default(&context.event);
- if (r < 0)
- return log_error_errno(r, "Failed to get event loop: %m");
-
- r = sd_event_set_signal_exit(context.event, true);
- if (r < 0)
- return log_error_errno(r, "Failed to enable exit on SIGINT/SIGTERM: %m");
-
- FOREACH_ARRAY(i, de->entries, de->n_entries) {
- struct dirent *d = *i;
-
- if (set_size(context.link_infos) >= METRICS_OR_FACTS_LINKS_MAX) {
- n_skipped_sources++;
- break;
- }
-
- _cleanup_free_ char *p = path_join(sources_path, d->d_name);
- if (!p)
- return log_oom();
-
- (void) call_collect(&context, d->d_name, p);
- }
- }
-
- if (set_isempty(context.link_infos)) {
- if (arg_legend)
- log_info("No facts sources found.");
- } else {
- assert(context.event);
-
- r = sd_event_loop(context.event);
- if (r < 0)
- return log_error_errno(r, "Failed to run event loop: %m");
-
- if (arg_url)
- r = upload_collected(&context);
- else
- r = output_collected(&context);
- if (r < 0)
- return r;
- }
-
- if (n_skipped_sources > 0)
- return log_warning_errno(SYNTHETIC_ERRNO(EUCLEAN),
- "Too many facts sources, only %u sources contacted, %zu sources skipped.",
- set_size(context.link_infos), n_skipped_sources);
- if (context.n_invalid_metrics > 0)
- return log_warning_errno(SYNTHETIC_ERRNO(EUCLEAN),
- "%zu facts are not valid.",
- context.n_invalid_metrics);
- if (context.n_skipped_metrics > 0)
- return log_warning_errno(SYNTHETIC_ERRNO(EUCLEAN),
- "Too many facts, only %zu facts collected, %zu facts skipped.",
- context.n_metrics, context.n_skipped_metrics);
- return 0;
-}
-
VERB_NOARG(verb_list_sources, "list-sources", "Show list of known metrics sources");
static int verb_list_sources(int argc, char *argv[], uintptr_t _data, void *userdata) {
int r;
(void) table_sync_column_widths(0, options, verbs);
printf("%s [OPTIONS...] COMMAND ...\n"
- "\n%sAcquire metrics and facts from local sources.%s\n"
+ "\n%sAcquire metrics from local sources.%s\n"
"\n%sCommands:%s\n",
program_invocation_short_name,
ansi_highlight(),
"$REPORT" metrics
"$REPORT" metrics -j
"$REPORT" metrics --no-legend
-"$REPORT" describe-metrics
-"$REPORT" describe-metrics -j
-"$REPORT" describe-metrics --no-legend
+"$REPORT" describe
+"$REPORT" describe -j
+"$REPORT" describe --no-legend
"$REPORT" list-sources
"$REPORT" list-sources -j
"$REPORT" list-sources --no-legend
"$REPORT" metrics io
"$REPORT" metrics io.systemd piff
"$REPORT" metrics piff
-"$REPORT" describe-metrics io
-"$REPORT" describe-metrics io.systemd piff
-"$REPORT" describe-metrics piff
+"$REPORT" describe io
+"$REPORT" describe io.systemd piff
+"$REPORT" describe piff
# test io.systemd.CGroup Metrics
systemctl start systemd-report-cgroup.socket
# Make sure the service for "system facts" is enabled
systemctl start systemd-report-basic.socket
-# Test facts verbs
-"$REPORT" facts
-"$REPORT" facts -j
-"$REPORT" facts --no-legend
-"$REPORT" describe-facts
-"$REPORT" describe-facts -j
-"$REPORT" describe-facts --no-legend
-
-# Test facts with match filters
-"$REPORT" facts io
-"$REPORT" facts io.systemd piff
-"$REPORT" facts piff
-"$REPORT" describe-facts io
-"$REPORT" describe-facts io.systemd piff
-"$REPORT" describe-facts piff
-
-# Test facts via direct Varlink call on existing socket
-varlinkctl --more call /run/systemd/report/io.systemd.Basic io.systemd.Facts.List {}
-varlinkctl --more call /run/systemd/report/io.systemd.Basic io.systemd.Facts.Describe {}
-
# Test HTTP upload (plain http)
FAKE_SERVER=/usr/lib/systemd/tests/integration-tests/TEST-74-AUX-UTILS/TEST-74-AUX-UTILS.units/fake-report-server.py
CERTDIR=$(mktemp -d)
systemctl status fake-report-server
"$REPORT" metrics --url=http://localhost:8089/
-"$REPORT" facts --url=http://localhost:8089/
# Test HTTPS upload with generated TLS certificates
openssl req -x509 -newkey rsa:2048 -keyout "$CERTDIR/server.key" -out "$CERTDIR/server.crt" \
"$FAKE_SERVER" --cert="$CERTDIR/server.crt" --key="$CERTDIR/server.key" --port=8090
systemctl status fake-report-server-tls
-"$REPORT" metrics --url=https://localhost:8090/ --key=- --trust="$CERTDIR/server.crt"
-"$REPORT" facts --url=https://localhost:8090/ --key=- --trust="$CERTDIR/server.crt" \
+"$REPORT" metrics --url=https://localhost:8090/ --key=- --trust="$CERTDIR/server.crt" \
--extra-header='Authorization: Bearer magic string'