]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
feat: Add `--print-stats` format selection, JSON format (#1382)
authorKaspar Schleiser <kaspar@schleiser.de>
Mon, 22 Jan 2024 19:22:06 +0000 (20:22 +0100)
committerGitHub <noreply@github.com>
Mon, 22 Jan 2024 19:22:06 +0000 (20:22 +0100)
doc/MANUAL.adoc
src/core/Statistic.hpp
src/core/Statistics.cpp
src/core/Statistics.hpp
src/core/mainoptions.cpp

index 572eb0a275f6eda844b1e121f0f6547997c1cd42..0e9710ff7f003997a881fafbfdd75dbb41175bfc 100644 (file)
@@ -258,6 +258,18 @@ directory to a certain size, use `CCACHE_MAXSIZE=_SIZE_ ccache -c`.
     working directory. This option is only useful when debugging ccache and its
     behavior.
 
+*--format* _FORMAT_::
+
+    Specify format for `--print-log-stats` and `--print-stats`. Possible values
+    are:
++
+--
+*tab*::
+    Tab separated. This is the default.
+*json*::
+    JSON formatted.
+--
+
 *-k* _KEY_, *--get-config* _KEY_::
 
     Print the value of configuration option _KEY_. See _<<Configuration>>_ for
@@ -279,12 +291,13 @@ directory to a certain size, use `CCACHE_MAXSIZE=_SIZE_ ccache -c`.
 *--print-log-stats*::
 
     Print statistics counters from the stats log in machine-parseable
-    (tab-separated) format. See <<config_stats_log,*stats_log*>>.
+    (tab-separated or JSON) format. See <<config_stats_log,*stats_log*>> and
+    `--format`.
 
 *--print-stats*::
 
     Print statistics counter IDs and corresponding values in machine-parsable
-    (tab-separated) format.
+    (tab-separated or JSON) format. See `--format`.
 
 
 
index 22b5fe71d66d4630d5acda371d4d0bd165c35675..26926fc028c636f9bc9f93fa33512df1ea5990c1 100644 (file)
@@ -84,4 +84,9 @@ enum class Statistic {
   END = 84
 };
 
+enum class StatisticFormat {
+  Tab,
+  Json,
+};
+
 } // namespace core
index c2fefba2be46049a2c3b863ad3da0d8e7b282833..3ae77ae4e075235764113b1127746e1533010af9 100644 (file)
@@ -525,7 +525,22 @@ Statistics::format_human_readable(const Config& config,
 
 std::string
 Statistics::format_machine_readable(const Config& config,
-                                    const util::TimePoint& last_updated) const
+                                    const util::TimePoint& last_updated,
+                                    const StatisticFormat format) const
+{
+  switch (format) {
+  case StatisticFormat::Json:
+    return Statistics::format_json(config, last_updated);
+  case StatisticFormat::Tab:
+    /* fall through */
+  default:
+    return Statistics::format_tab_separated(config, last_updated);
+  }
+}
+
+std::string
+Statistics::format_tab_separated(const Config& config,
+                                 const util::TimePoint& last_updated) const
 {
   std::vector<std::string> lines;
 
@@ -548,6 +563,32 @@ Statistics::format_machine_readable(const Config& config,
   return util::join(lines, "");
 }
 
+std::string
+Statistics::format_json(const Config& config,
+                        const util::TimePoint& last_updated) const
+{
+  std::vector<std::string> lines;
+
+  auto add_line = [&](auto id, auto value) {
+    lines.push_back(FMT("\"{}\": {}", id, value));
+  };
+
+  add_line("stats_updated_timestamp", last_updated.sec());
+
+  for (const auto& field : k_statistics_fields) {
+    if (!(field.flags & FLAG_NEVER)) {
+      add_line(field.id, m_counters.get(field.statistic));
+    }
+  }
+
+  add_line("max_cache_size_kibibyte", config.max_size() / 1024);
+  add_line("max_files_in_cache", config.max_files());
+
+  std::sort(lines.begin(), lines.end());
+  std::string result = "{\n  " + util::join(lines, ",\n  ") + "\n}\n";
+  return result;
+}
+
 std::unordered_map<std::string, Statistic>
 Statistics::get_id_map()
 {
index b2deab712785d39b422f07c8fab4a1aa2fad3562..f0951ed2857bbaa14e311f64d4361ed7a8197cb8 100644 (file)
@@ -46,9 +46,9 @@ public:
                                     bool from_log) const;
 
   // Format cache statistics in machine-readable format.
-  std::string
-  format_machine_readable(const Config& config,
-                          const util::TimePoint& last_updated) const;
+  std::string format_machine_readable(const Config& config,
+                                      const util::TimePoint& last_updated,
+                                      const StatisticFormat format) const;
 
   const StatisticsCounters& counters() const;
 
@@ -62,6 +62,12 @@ private:
   uint64_t count_stats(unsigned flags) const;
   std::vector<std::pair<std::string, uint64_t>> get_stats(unsigned flags,
                                                           bool all) const;
+  // Format cache statistics in tab-separated format.
+  std::string format_tab_separated(const Config& config,
+                                   const util::TimePoint& last_updated) const;
+  // Format cache statistics in JSON format.
+  std::string format_json(const Config& config,
+                          const util::TimePoint& last_updated) const;
 };
 
 // --- Inline implementations ---
index d11e6c43c74078f1238e4ba835651848f0ed5a7a..371a272fa63ec4af1928ff1f4f0c3ce92d711182 100644 (file)
@@ -168,6 +168,8 @@ Options for scripting or debugging:
                                PATH
         --extract-result PATH  extract file data stored in result file at PATH
                                to the current working directory
+        --format FORMAT        specify format for --print-log-stats and
+                               --print-stats (tab, json); default: tab
     -k, --get-config KEY       print the value of configuration key KEY
         --hash-file PATH       print the hash (160 bit BLAKE3) of the file at
                                PATH
@@ -423,6 +425,7 @@ enum {
   EVICT_NAMESPACE,
   EVICT_OLDER_THAN,
   EXTRACT_RESULT,
+  FORMAT,
   HASH_FILE,
   INSPECT,
   PRINT_LOG_STATS,
@@ -449,6 +452,7 @@ const option long_options[] = {
   {"evict-namespace", required_argument, nullptr, EVICT_NAMESPACE},
   {"evict-older-than", required_argument, nullptr, EVICT_OLDER_THAN},
   {"extract-result", required_argument, nullptr, EXTRACT_RESULT},
+  {"format", required_argument, nullptr, FORMAT},
   {"get-config", required_argument, nullptr, 'k'},
   {"hash-file", required_argument, nullptr, HASH_FILE},
   {"help", no_argument, nullptr, 'h'},
@@ -484,6 +488,7 @@ process_main_options(int argc, const char* const* argv)
 
   uint8_t verbosity = 0;
 
+  StatisticFormat format = StatisticFormat::Tab;
   std::optional<uint64_t> trim_max_size;
   std::optional<util::SizeUnitPrefixType> trim_suffix_type;
   bool trim_lru_mtime = false;
@@ -508,6 +513,16 @@ process_main_options(int argc, const char* const* argv)
     case 'd': // --dir
       util::setenv("CCACHE_DIR", arg);
       break;
+    case FORMAT:
+      if (arg == "tab") {
+        format = StatisticFormat::Tab;
+      } else if (arg == "json") {
+        format = StatisticFormat::Json;
+      } else {
+        PRINT(stderr, "Error: unknown format \"{}\"\n", arg);
+        return EXIT_FAILURE;
+      }
+      break;
 
     case CONFIG_PATH:
       util::setenv("CCACHE_CONFIGPATH", arg);
@@ -569,6 +584,7 @@ process_main_options(int argc, const char* const* argv)
     switch (c) {
     case CONFIG_PATH:
     case 'd': // --dir
+    case FORMAT:
     case RECOMPRESS_THREADS:
     case TRIM_MAX_SIZE:
     case TRIM_METHOD:
@@ -647,8 +663,9 @@ process_main_options(int argc, const char* const* argv)
       const auto [counters, last_updated] =
         storage::local::LocalStorage(config).get_all_statistics();
       Statistics statistics(counters);
-      PRINT_RAW(stdout,
-                statistics.format_machine_readable(config, last_updated));
+      PRINT_RAW(
+        stdout,
+        statistics.format_machine_readable(config, last_updated, format));
       break;
     }
 
@@ -745,7 +762,8 @@ process_main_options(int argc, const char* const* argv)
       Statistics statistics(StatsLog(config.stats_log()).read());
       const auto timestamp =
         DirEntry(config.stats_log(), DirEntry::LogOnError::yes).mtime();
-      PRINT_RAW(stdout, statistics.format_machine_readable(config, timestamp));
+      PRINT_RAW(stdout,
+                statistics.format_machine_readable(config, timestamp, format));
       break;
     }