JDevlieghere created this revision.
JDevlieghere added reviewers: clayborg, jingham, labath.
Herald added a subscriber: mgorny.
JDevlieghere requested review of this revision.

Refactor LLDB's current statistics into a single class named Analytics which 
consists of different metrics.


https://reviews.llvm.org/D110893

Files:
  lldb/include/lldb/Target/Target.h
  lldb/include/lldb/Utility/Analytics.h
  lldb/include/lldb/Utility/Metrics.def
  lldb/include/lldb/lldb-private-enumerations.h
  lldb/include/lldb/module.modulemap
  lldb/source/API/SBTarget.cpp
  lldb/source/Commands/CommandObjectExpression.cpp
  lldb/source/Commands/CommandObjectFrame.cpp
  lldb/source/Commands/CommandObjectStats.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Utility/Analytics.cpp
  lldb/source/Utility/CMakeLists.txt
  lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py

Index: lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py
===================================================================
--- lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py
+++ lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py
@@ -27,7 +27,7 @@
         stream = lldb.SBStream()
         res = stats.GetAsJSON(stream)
         stats_json = sorted(json.loads(stream.GetData()))
-        self.assertEqual(len(stats_json), 4)
+        self.assertEqual(len(stats_json), 4, stream.GetData())
         self.assertIn("Number of expr evaluation failures", stats_json)
         self.assertIn("Number of expr evaluation successes", stats_json)
         self.assertIn("Number of frame var failures", stats_json)
Index: lldb/source/Utility/CMakeLists.txt
===================================================================
--- lldb/source/Utility/CMakeLists.txt
+++ lldb/source/Utility/CMakeLists.txt
@@ -24,6 +24,7 @@
 endif()
 
 add_lldb_library(lldbUtility
+  Analytics.cpp
   ArchSpec.cpp
   Args.cpp
   Baton.cpp
Index: lldb/source/Utility/Analytics.cpp
===================================================================
--- /dev/null
+++ lldb/source/Utility/Analytics.cpp
@@ -0,0 +1,70 @@
+//===-- Analytics.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Analytics.h"
+
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StructuredData.h"
+
+#include <cassert>
+#include <memory>
+#include <utility>
+
+namespace lldb_private {
+
+static unsigned GetNumberOfMetrics() {
+  return static_cast<unsigned>(Metric::MaxID);
+}
+
+static unsigned GetCounterIndexForMetric(Metric S) {
+  assert(S != Metric::MaxID && "invalid metric");
+  return static_cast<unsigned>(S);
+}
+
+static Metric GetMetricForCounterIndex(unsigned index) {
+  assert(index < GetNumberOfMetrics() && "invalid metric");
+  return static_cast<Metric>(index);
+}
+
+static const char *GetMetricDescription(Metric S) {
+  switch (S) {
+#define LLDB_METRIC_DEF(EnumName, Desc)                                        \
+  case Metric::EnumName:                                                       \
+    return Desc;
+#include "lldb/Utility/Metrics.def"
+  case Metric::MaxID:
+    llvm_unreachable("invalid metric");
+  }
+}
+
+Analytics::Analytics() { m_counters.resize(GetNumberOfMetrics()); }
+
+void Analytics::Record(Metric metric) {
+  if (!m_collecting_analytics)
+    return;
+  ++m_counters[GetCounterIndexForMetric(metric)];
+}
+
+void Analytics::Print(Stream &stream) const {
+  for (unsigned metric_id = 0; metric_id < GetNumberOfMetrics(); ++metric_id) {
+    Metric s = GetMetricForCounterIndex(metric_id);
+    stream.Printf("%s : %u\n", GetMetricDescription(s), m_counters[metric_id]);
+  }
+}
+
+std::unique_ptr<StructuredData::Dictionary>
+Analytics::GetAsStructuredData() const {
+  auto metrics_up = std::make_unique<StructuredData::Dictionary>();
+  for (unsigned metric_id = 0; metric_id < GetNumberOfMetrics(); ++metric_id) {
+    Metric s = GetMetricForCounterIndex(metric_id);
+    metrics_up->AddIntegerItem(GetMetricDescription(s), m_counters[metric_id]);
+  }
+  return metrics_up;
+}
+
+} // namespace lldb_private
Index: lldb/source/Target/Target.cpp
===================================================================
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -95,14 +95,10 @@
       m_watchpoint_list(), m_process_sp(), m_search_filter_sp(),
       m_image_search_paths(ImageSearchPathsChanged, this),
       m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
-      m_latest_stop_hook_id(0),
-      m_valid(true), m_suppress_stop_hooks(false),
+      m_latest_stop_hook_id(0), m_valid(true), m_suppress_stop_hooks(false),
       m_is_dummy_target(is_dummy_target),
       m_frame_recognizer_manager_up(
-          std::make_unique<StackFrameRecognizerManager>()),
-      m_stats_storage(static_cast<int>(StatisticKind::StatisticMax))
-
-{
+          std::make_unique<StackFrameRecognizerManager>()) {
   SetEventName(eBroadcastBitBreakpointChanged, "breakpoint-changed");
   SetEventName(eBroadcastBitModulesLoaded, "modules-loaded");
   SetEventName(eBroadcastBitModulesUnloaded, "modules-unloaded");
Index: lldb/source/Commands/CommandObjectStats.cpp
===================================================================
--- lldb/source/Commands/CommandObjectStats.cpp
+++ lldb/source/Commands/CommandObjectStats.cpp
@@ -72,17 +72,7 @@
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
     Target &target = GetSelectedOrDummyTarget();
-
-    uint32_t i = 0;
-    for (auto &stat : target.GetStatistics()) {
-      result.AppendMessageWithFormat(
-          "%s : %u\n",
-          lldb_private::GetStatDescription(
-              static_cast<lldb_private::StatisticKind>(i))
-              .c_str(),
-          stat);
-      i += 1;
-    }
+    target.GetAnalytics().Print(result.GetOutputStream());
     result.SetStatus(eReturnStatusSuccessFinishResult);
     return true;
   }
Index: lldb/source/Commands/CommandObjectFrame.cpp
===================================================================
--- lldb/source/Commands/CommandObjectFrame.cpp
+++ lldb/source/Commands/CommandObjectFrame.cpp
@@ -709,10 +709,8 @@
     // Increment statistics.
     bool res = result.Succeeded();
     Target &target = GetSelectedOrDummyTarget();
-    if (res)
-      target.IncrementStats(StatisticKind::FrameVarSuccess);
-    else
-      target.IncrementStats(StatisticKind::FrameVarFailure);
+    Analytics &telemetry = target.GetAnalytics();
+    telemetry.Record(res ? Metric::FrameVarSuccess : Metric::FrameVarFailure);
     return res;
   }
 
Index: lldb/source/Commands/CommandObjectExpression.cpp
===================================================================
--- lldb/source/Commands/CommandObjectExpression.cpp
+++ lldb/source/Commands/CommandObjectExpression.cpp
@@ -642,6 +642,7 @@
   }
 
   Target &target = GetSelectedOrDummyTarget();
+  Analytics &telemetry = target.GetAnalytics();
   if (EvaluateExpression(expr, result.GetOutputStream(),
                          result.GetErrorStream(), result)) {
 
@@ -659,13 +660,11 @@
         fixed_command.append(m_fixed_expression);
       history.AppendString(fixed_command);
     }
-    // Increment statistics to record this expression evaluation success.
-    target.IncrementStats(StatisticKind::ExpressionSuccessful);
+    telemetry.Record(Metric::ExpressionSuccess);
     return true;
   }
 
-  // Increment statistics to record this expression evaluation failure.
-  target.IncrementStats(StatisticKind::ExpressionFailure);
+  telemetry.Record(Metric::ExpressionFailure);
   result.SetStatus(eReturnStatusFailed);
   return false;
 }
Index: lldb/source/API/SBTarget.cpp
===================================================================
--- lldb/source/API/SBTarget.cpp
+++ lldb/source/API/SBTarget.cpp
@@ -218,16 +218,7 @@
   if (!target_sp)
     return LLDB_RECORD_RESULT(data);
 
-  auto stats_up = std::make_unique<StructuredData::Dictionary>();
-  int i = 0;
-  for (auto &Entry : target_sp->GetStatistics()) {
-    std::string Desc = lldb_private::GetStatDescription(
-        static_cast<lldb_private::StatisticKind>(i));
-    stats_up->AddIntegerItem(Desc, Entry);
-    i += 1;
-  }
-
-  data.m_impl_up->SetObjectSP(std::move(stats_up));
+  data.m_impl_up->SetObjectSP(target_sp->GetAnalytics().GetAsStructuredData());
   return LLDB_RECORD_RESULT(data);
 }
 
Index: lldb/include/lldb/module.modulemap
===================================================================
--- lldb/include/lldb/module.modulemap
+++ lldb/include/lldb/module.modulemap
@@ -130,6 +130,8 @@
   umbrella "Utility"
   module * { export * }
 
+  textual header "Utility/Statistics.def"
+
   module lldb_defines { header "lldb-defines.h" export * }
   module lldb_enumerations { header "lldb-enumerations.h" export * }
   module lldb_forward { header "lldb-forward.h" export * }
Index: lldb/include/lldb/lldb-private-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-private-enumerations.h
+++ lldb/include/lldb/lldb-private-enumerations.h
@@ -212,33 +212,6 @@
   AnyType = Any | Class | Struct | Union | Enum | Typedef
 };
 
-// Enumerations that can be used to specify the kind of metric we're looking at
-// when collecting stats.
-enum StatisticKind {
-  ExpressionSuccessful = 0,
-  ExpressionFailure = 1,
-  FrameVarSuccess = 2,
-  FrameVarFailure = 3,
-  StatisticMax = 4
-};
-
-
-inline std::string GetStatDescription(lldb_private::StatisticKind K) {
-   switch (K) {
-   case StatisticKind::ExpressionSuccessful:
-     return "Number of expr evaluation successes";
-   case StatisticKind::ExpressionFailure:
-     return "Number of expr evaluation failures";
-   case StatisticKind::FrameVarSuccess:
-     return "Number of frame var successes";
-   case StatisticKind::FrameVarFailure:
-     return "Number of frame var failures";
-   case StatisticKind::StatisticMax:
-     return "";
-   }
-   llvm_unreachable("Statistic not registered!");
-}
-
 } // namespace lldb_private
 
 namespace llvm {
Index: lldb/include/lldb/Utility/Metrics.def
===================================================================
--- /dev/null
+++ lldb/include/lldb/Utility/Metrics.def
@@ -0,0 +1,18 @@
+//===-- Statistics.def ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_METRIC_DEF
+#error "Must define LLDB_METRIC_DEF(EnumName, Desc)."
+#endif
+
+LLDB_METRIC_DEF(ExpressionSuccess, "Number of expr evaluation successes")
+LLDB_METRIC_DEF(ExpressionFailure, "Number of expr evaluation failures")
+LLDB_METRIC_DEF(FrameVarSuccess, "Number of frame var successes")
+LLDB_METRIC_DEF(FrameVarFailure, "Number of frame var failures")
+
+#undef LLDB_METRIC_DEF
Index: lldb/include/lldb/Utility/Analytics.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Utility/Analytics.h
@@ -0,0 +1,49 @@
+//===-- Analytics.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_TELEMETRY_H
+#define LLDB_UTILITY_TELEMETRY_H
+
+#include "lldb/Utility/StructuredData.h"
+
+#include <vector>
+
+namespace lldb_private {
+
+class Stream;
+
+/// A kind of metric to collect.
+enum class Metric : unsigned {
+#define LLDB_METRIC_DEF(EnumName, Desc) EnumName,
+#include "lldb/Utility/Metrics.def"
+  MaxID
+};
+
+/// Keep track of statistics. Data collection is off by default.
+class Analytics {
+public:
+  Analytics();
+
+  void SetEnabled(bool v) { m_collecting_analytics = v; }
+
+  bool IsEnabled() const { return m_collecting_analytics; }
+
+  void Record(Metric stat);
+
+  void Print(Stream &stream) const;
+
+  std::unique_ptr<StructuredData::Dictionary> GetAsStructuredData() const;
+
+private:
+  std::vector<unsigned> m_counters;
+  bool m_collecting_analytics = false;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_TELEMETRY_H
Index: lldb/include/lldb/Target/Target.h
===================================================================
--- lldb/include/lldb/Target/Target.h
+++ lldb/include/lldb/Target/Target.h
@@ -29,6 +29,7 @@
 #include "lldb/Target/PathMappingList.h"
 #include "lldb/Target/SectionLoadHistory.h"
 #include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/Analytics.h"
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/Broadcaster.h"
 #include "lldb/Utility/LLDBAssert.h"
@@ -1451,23 +1452,14 @@
 
   // Utilities for `statistics` command.
 private:
-  std::vector<uint32_t> m_stats_storage;
-  bool m_collecting_stats = false;
+  Analytics m_telemetry;
 
 public:
-  void SetCollectingStats(bool v) { m_collecting_stats = v; }
+  void SetCollectingStats(bool v) { m_telemetry.SetEnabled(v); }
 
-  bool GetCollectingStats() { return m_collecting_stats; }
+  bool GetCollectingStats() { return m_telemetry.IsEnabled(); }
 
-  void IncrementStats(lldb_private::StatisticKind key) {
-    if (!GetCollectingStats())
-      return;
-    lldbassert(key < lldb_private::StatisticKind::StatisticMax &&
-               "invalid statistics!");
-    m_stats_storage[key] += 1;
-  }
-
-  std::vector<uint32_t> GetStatistics() { return m_stats_storage; }
+  Analytics &GetAnalytics() { return m_telemetry; }
 
 private:
   /// Construct with optional file and arch.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to