From: Lennart Poettering Date: Sun, 14 Jun 2026 05:48:36 +0000 (+0200) Subject: report: separate report generation from upload X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d9026c736141db7c1bb99d573fc67f99cb48b1d;p=thirdparty%2Fsystemd.git report: separate report generation from upload Let's split report generation from uploading, as prepatory step for adding signing for reports. No real code changes, just moving things around. --- diff --git a/src/report/meson.build b/src/report/meson.build index 5f05382999e..e64f74ee4ef 100644 --- a/src/report/meson.build +++ b/src/report/meson.build @@ -6,6 +6,7 @@ executables += [ 'public' : true, 'sources' : files( 'report.c', + 'report-generate.c', 'report-upload.c', ), }, diff --git a/src/report/report-generate.c b/src/report/report-generate.c new file mode 100644 index 00000000000..edac44a0eaa --- /dev/null +++ b/src/report/report-generate.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-json.h" + +#include "log.h" +#include "report.h" +#include "report-generate.h" +#include "time-util.h" + +int context_build_report(Context *context, sd_json_variant **ret) { + int r; + + /* Convert the variant array to a JSON report. */ + + assert(context); + assert(ret); + + usec_t ts = now(CLOCK_REALTIME); + + _cleanup_(sd_json_variant_unrefp) sd_json_variant *report = NULL; + r = sd_json_buildo(&report, + SD_JSON_BUILD_PAIR_STRING("mediaType", "application/vnd.io.systemd.report"), + SD_JSON_BUILD_PAIR("timestamp", + SD_JSON_BUILD_STRING(FORMAT_TIMESTAMP_STYLE(ts, TIMESTAMP_UTC))), + SD_JSON_BUILD_PAIR("metrics", + SD_JSON_BUILD_VARIANT_ARRAY(context->metrics, context->n_metrics))); + if (r < 0) + return log_error_errno(r, "Failed to build JSON data: %m"); + + *ret = TAKE_PTR(report); + return 0; +} + +int context_generate_report(Context *context) { + int r; + + assert(context); + + /* Make a structured report and either print it or upload it. */ + + _cleanup_(sd_json_variant_unrefp) sd_json_variant *report = NULL; + r = context_build_report(context, &report); + if (r < 0) + return r; + + r = sd_json_variant_dump(report, arg_json_format_flags, /* f= */ NULL, /* prefix= */ NULL); + if (r < 0) + return log_error_errno(r, "Failed to dump json object: %m"); + + return 0; +} diff --git a/src/report/report-generate.h b/src/report/report-generate.h new file mode 100644 index 00000000000..acde3db14c3 --- /dev/null +++ b/src/report/report-generate.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "report.h" + +int context_build_report(Context *context, sd_json_variant **ret); + +int context_generate_report(Context *context); diff --git a/src/report/report-upload.c b/src/report/report-upload.c index 02f15cba610..17ef327db01 100644 --- a/src/report/report-upload.c +++ b/src/report/report-upload.c @@ -6,6 +6,8 @@ #include "errno-util.h" #include "log.h" #include "report.h" +#include "report-generate.h" +#include "report-upload.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -13,11 +15,12 @@ #include "varlink-util.h" #include "version.h" +#define REPORT_UPLOAD_DIR "/run/systemd/report.upload" +#define SERVER_ANSWER_MAX (1U * 1024U * 1024U) + #if HAVE_LIBCURL #include "curl-util.h" -#define SERVER_ANSWER_MAX (1*1024*1024u) - static size_t output_callback(char *buf, size_t size, size_t nmemb, @@ -54,26 +57,6 @@ static size_t output_callback(char *buf, } #endif -static int build_json_report(Context *context, sd_json_variant **ret) { - /* Convert the variant array to a JSON report. */ - - assert(context); - assert(ret); - - usec_t ts = now(CLOCK_REALTIME); - int r; - - r = sd_json_buildo(ret, - SD_JSON_BUILD_PAIR_STRING("mediaType", "application/vnd.io.systemd.report"), - SD_JSON_BUILD_PAIR("timestamp", - SD_JSON_BUILD_STRING(FORMAT_TIMESTAMP_STYLE(ts, TIMESTAMP_UTC))), - SD_JSON_BUILD_PAIR("metrics", - SD_JSON_BUILD_VARIANT_ARRAY(context->metrics, context->n_metrics))); - if (r < 0) - return log_error_errno(r, "Failed to build JSON data: %m"); - return 0; -} - static int http_upload_collected(Context *context, sd_json_variant *report) { #if HAVE_LIBCURL _cleanup_(curl_slist_free_allp) struct curl_slist *header = NULL; @@ -235,9 +218,14 @@ static int execute_dir_reply( return 0; } -static int upload_collected(Context *context, sd_json_variant *report) { +int context_upload_report(Context *context) { int r; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *report = NULL; + r = context_build_report(context, &report); + if (r < 0) + return r; + if (arg_url) return http_upload_collected(context, report); @@ -267,23 +255,3 @@ static int upload_collected(Context *context, sd_json_variant *report) { log_debug("Upload via %s finished successfully.", REPORT_UPLOAD_DIR); return 0; } - -/* Make a structured report and either print it or upload it. */ -int report_collected(Context *context) { - _cleanup_(sd_json_variant_unrefp) sd_json_variant *report = NULL; - int r; - - r = build_json_report(context, &report); - if (r < 0) - return r; - - if (context->action == ACTION_UPLOAD) - return upload_collected(context, report); - - /* Just print the report for now. */ - assert(context->action == ACTION_GENERATE); - r = sd_json_variant_dump(report, arg_json_format_flags, /* f= */ NULL, /* prefix= */ NULL); - if (r < 0) - return log_error_errno(r, "Failed to dump json object: %m"); - return 0; -} diff --git a/src/report/report-upload.h b/src/report/report-upload.h new file mode 100644 index 00000000000..eb4cb87f231 --- /dev/null +++ b/src/report/report-upload.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "report.h" + +int context_upload_report(Context *context); diff --git a/src/report/report.c b/src/report/report.c index 9c951f98323..c3af61f01dd 100644 --- a/src/report/report.c +++ b/src/report/report.c @@ -16,6 +16,8 @@ #include "path-lookup.h" #include "recurse-dir.h" #include "report.h" +#include "report-generate.h" +#include "report-upload.h" #include "runtime-scope.h" #include "set.h" #include "sort-util.h" @@ -656,10 +658,24 @@ static int verb_metrics(int argc, char *argv[], uintptr_t data, void *userdata) if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - if (IN_SET(action, ACTION_GENERATE, ACTION_UPLOAD)) - r = report_collected(&context); - else + switch (action) { + + case ACTION_LIST_METRICS: + case ACTION_DESCRIBE_METRICS: r = output_collected(&context); + break; + + case ACTION_GENERATE: + r = context_generate_report(&context); + break; + + case ACTION_UPLOAD: + r = context_upload_report(&context); + break; + + default: + assert_not_reached(); + } if (r < 0) return r; } diff --git a/src/report/report.h b/src/report/report.h index 34317552337..51d55344f96 100644 --- a/src/report/report.h +++ b/src/report/report.h @@ -9,8 +9,6 @@ #define REPORT_CERT_FILE CERTIFICATE_ROOT "/certs/systemd-report.pem" #define REPORT_TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" -#define REPORT_UPLOAD_DIR "/run/systemd/report.upload" - extern sd_json_format_flags_t arg_json_format_flags; extern char *arg_url, *arg_key, *arg_cert, *arg_trust; extern char **arg_extra_headers; @@ -36,5 +34,3 @@ typedef struct Context { int upload_result; struct iovec_wrapper upload_answer; } Context; - -int report_collected(Context *context);