[forensics] Add Inspect budget Cobalt metric
* Enable logging event in cobalt with no dimensions.
Bug: 64072
Change-Id: I86f01a771693804ce6744459661bdd18578d862e
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/512146
Commit-Queue: Daniel Salazar Villarreal <villarreald@google.com>
Reviewed-by: Alex Pankhurst <pankhurst@google.com>
Reviewed-by: Francois Rousseau <frousseau@google.com>
diff --git a/src/developer/forensics/feedback_data/BUILD.gn b/src/developer/forensics/feedback_data/BUILD.gn
index 4e2e1d01..92d9560 100644
--- a/src/developer/forensics/feedback_data/BUILD.gn
+++ b/src/developer/forensics/feedback_data/BUILD.gn
@@ -260,6 +260,7 @@
"//sdk/lib/sys/inspect/cpp",
"//src/developer/forensics/utils:archive",
"//src/developer/forensics/utils:inspect_node_manager",
+ "//src/developer/forensics/utils/cobalt",
]
deps = [
diff --git a/src/developer/forensics/feedback_data/inspect_data_budget.cc b/src/developer/forensics/feedback_data/inspect_data_budget.cc
index f49f3c3..50dcca9 100644
--- a/src/developer/forensics/feedback_data/inspect_data_budget.cc
+++ b/src/developer/forensics/feedback_data/inspect_data_budget.cc
@@ -5,11 +5,13 @@
#include "src/developer/forensics/feedback_data/inspect_data_budget.h"
#include <lib/syslog/cpp/macros.h>
+#include <stdint.h>
#include <algorithm>
#include <filesystem>
#include "src/developer/forensics/feedback_data/constants.h"
+#include "src/developer/forensics/utils/cobalt/metrics.h"
namespace forensics::feedback_data {
namespace {
@@ -22,8 +24,9 @@
} // namespace
-InspectDataBudget::InspectDataBudget(const char* limit_data_flag_path, InspectNodeManager* node)
- : inspect_node_(node) {
+InspectDataBudget::InspectDataBudget(const char* limit_data_flag_path, InspectNodeManager* node,
+ cobalt::Logger* cobalt)
+ : inspect_node_(node), cobalt_(cobalt) {
limit_data_flag_ = std::filesystem::exists(limit_data_flag_path);
inspect_budget_enabled_ =
inspect_node_->Get("/inspect_budget")
@@ -79,6 +82,8 @@
if (inspect_last_ten_readings_.size() > 10) {
inspect_last_ten_readings_.pop_front();
}
+
+ cobalt_->LogEvent(cobalt::kInspectBudgetMetricId, data_budget_.value());
}
} // namespace forensics::feedback_data
diff --git a/src/developer/forensics/feedback_data/inspect_data_budget.h b/src/developer/forensics/feedback_data/inspect_data_budget.h
index f849c02..4a6673d 100644
--- a/src/developer/forensics/feedback_data/inspect_data_budget.h
+++ b/src/developer/forensics/feedback_data/inspect_data_budget.h
@@ -12,6 +12,7 @@
#include <optional>
#include "src/developer/forensics/utils/archive.h"
+#include "src/developer/forensics/utils/cobalt/logger.h"
#include "src/developer/forensics/utils/inspect_node_manager.h"
namespace forensics {
@@ -21,7 +22,8 @@
// 2.0 MB. If the file 'limit_data_flag_path' does not exist, prediction is disabled.
class InspectDataBudget {
public:
- InspectDataBudget(const char* limit_data_flag_path, InspectNodeManager* node);
+ InspectDataBudget(const char* limit_data_flag_path, InspectNodeManager* node,
+ cobalt::Logger* cobalt);
void UpdateBudget(const std::map<std::string, ArchiveFileStats>& file_size_stats);
@@ -40,6 +42,8 @@
inspect::UintProperty inspect_target_size_;
std::list<inspect::UintArray> inspect_last_ten_readings_;
size_t next_reading_idx_ = 0;
+
+ cobalt::Logger* cobalt_;
};
} // namespace feedback_data
diff --git a/src/developer/forensics/feedback_data/main_service.cc b/src/developer/forensics/feedback_data/main_service.cc
index c42c84c..37e2642 100644
--- a/src/developer/forensics/feedback_data/main_service.cc
+++ b/src/developer/forensics/feedback_data/main_service.cc
@@ -105,7 +105,7 @@
inspect_manager_(root_node),
cobalt_(std::move(cobalt)),
clock_(),
- inspect_data_budget_(kUserBuildFlagPath, inspect_manager_.GetNodeManager()),
+ inspect_data_budget_(kUserBuildFlagPath, inspect_manager_.GetNodeManager(), cobalt_.get()),
device_id_manager_(dispatcher_, kDeviceIdPath),
datastore_(dispatcher_, services, cobalt_.get(), config.annotation_allowlist,
config.attachment_allowlist, boot_id_file, build_version_file,
diff --git a/src/developer/forensics/feedback_data/tests/data_provider_unittest.cc b/src/developer/forensics/feedback_data/tests/data_provider_unittest.cc
index de998e1..0bb1694 100644
--- a/src/developer/forensics/feedback_data/tests/data_provider_unittest.cc
+++ b/src/developer/forensics/feedback_data/tests/data_provider_unittest.cc
@@ -137,12 +137,6 @@
// connecting through FIDL.
class DataProviderTest : public UnitTestFixture {
public:
- DataProviderTest() {
- inspect_node_manager_ = std::make_unique<InspectNodeManager>(&InspectRoot());
- inspect_data_budget_ =
- std::make_unique<InspectDataBudget>("non-existent_path", inspect_node_manager_.get());
- }
-
void SetUp() override {
// |cobalt_| owns the test clock through a unique_ptr so we need to allocate |clock_| on the
// heap and then give |cobalt_| ownership of it. This allows us to control the time perceived by
@@ -151,6 +145,10 @@
cobalt_ = std::make_unique<cobalt::Logger>(dispatcher(), services(),
std::unique_ptr<timekeeper::TestClock>(clock_));
SetUpCobaltServer(std::make_unique<stubs::CobaltLoggerFactory>());
+
+ inspect_node_manager_ = std::make_unique<InspectNodeManager>(&InspectRoot());
+ inspect_data_budget_ = std::make_unique<InspectDataBudget>(
+ "non-existent_path", inspect_node_manager_.get(), cobalt_.get());
}
protected:
diff --git a/src/developer/forensics/feedback_data/tests/datastore_unittest.cc b/src/developer/forensics/feedback_data/tests/datastore_unittest.cc
index 91049ba..6a26668 100644
--- a/src/developer/forensics/feedback_data/tests/datastore_unittest.cc
+++ b/src/developer/forensics/feedback_data/tests/datastore_unittest.cc
@@ -72,15 +72,15 @@
class DatastoreTest : public UnitTestFixture {
public:
- DatastoreTest() : executor_(dispatcher()) {
- inspect_node_manager_ = std::make_unique<InspectNodeManager>(&InspectRoot());
- inspect_data_budget_ =
- std::make_unique<InspectDataBudget>("non-existent_path", inspect_node_manager_.get());
- }
+ DatastoreTest() : executor_(dispatcher()) {}
void SetUp() override {
SetUpCobaltServer(std::make_unique<stubs::CobaltLoggerFactory>());
cobalt_ = std::make_unique<cobalt::Logger>(dispatcher(), services());
+
+ inspect_node_manager_ = std::make_unique<InspectNodeManager>(&InspectRoot());
+ inspect_data_budget_ = std::make_unique<InspectDataBudget>(
+ "non-existent_path", inspect_node_manager_.get(), cobalt_.get());
}
void TearDown() override {
diff --git a/src/developer/forensics/feedback_data/tests/inspect_data_budget_unittest.cc b/src/developer/forensics/feedback_data/tests/inspect_data_budget_unittest.cc
index ef737f8..b4477a4 100644
--- a/src/developer/forensics/feedback_data/tests/inspect_data_budget_unittest.cc
+++ b/src/developer/forensics/feedback_data/tests/inspect_data_budget_unittest.cc
@@ -10,7 +10,10 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "src/developer/forensics/testing/stubs/cobalt_logger_factory.h"
#include "src/developer/forensics/testing/unit_test_fixture.h"
+#include "src/developer/forensics/utils/cobalt/logger.h"
+#include "src/developer/forensics/utils/cobalt/metrics.h"
#include "src/lib/files/file.h"
#include "src/lib/files/path.h"
#include "src/lib/files/scoped_temp_dir.h"
@@ -37,10 +40,15 @@
class InspectDataBudgetTest : public UnitTestFixture {
public:
+ void SetUp() override {
+ SetUpCobaltServer(std::make_unique<stubs::CobaltLoggerFactory>());
+ cobalt_ = std::make_unique<cobalt::Logger>(dispatcher(), services());
+ }
+
void MakeUnlimitedBudget() {
inspect_node_manager_ = std::make_unique<InspectNodeManager>(&InspectRoot());
- inspect_data_budget_ =
- std::make_unique<InspectDataBudget>("non-existent_path", inspect_node_manager_.get());
+ inspect_data_budget_ = std::make_unique<InspectDataBudget>(
+ "non-existent_path", inspect_node_manager_.get(), cobalt_.get());
}
void MakeLimitedBudget() {
@@ -48,8 +56,8 @@
std::string limit_data_flag_path = files::JoinPath(tmp_dir_.path(), "limit_inspect_data");
files::WriteFile(limit_data_flag_path, " ");
- inspect_data_budget_ = std::make_unique<InspectDataBudget>(limit_data_flag_path.c_str(),
- inspect_node_manager_.get());
+ inspect_data_budget_ = std::make_unique<InspectDataBudget>(
+ limit_data_flag_path.c_str(), inspect_node_manager_.get(), cobalt_.get());
}
void CalcBudget(size_t zip_file_bytes) {
@@ -73,6 +81,8 @@
files::ScopedTempDir tmp_dir_;
std::unique_ptr<InspectDataBudget> inspect_data_budget_;
+
+ std::unique_ptr<cobalt::Logger> cobalt_;
};
TEST_F(InspectDataBudgetTest, TestUnlimitedBudget) {
@@ -231,6 +241,24 @@
EXPECT_THAT(InspectTree(), ChildrenMatch(UnorderedElementsAre(AllOf(node))));
}
+TEST_F(InspectDataBudgetTest, TestCobalt_BudgetEnabled) {
+ MakeLimitedBudget();
+ ASSERT_TRUE(GetSizeInBytes());
+ size_t initial_budget = GetSizeInBytes().value();
+
+ CalcBudget(1 * kMegabytes);
+ ASSERT_TRUE(GetSizeInBytes());
+ ASSERT_EQ(GetSizeInBytes().value(), initial_budget);
+
+ RunLoopUntilIdle();
+
+ EXPECT_THAT(ReceivedCobaltEvents(),
+ UnorderedElementsAreArray({
+ cobalt::Event(cobalt::EventType::kMultidimensionalEvent,
+ cobalt::kInspectBudgetMetricId, {}, 20971520),
+ }));
+}
+
} // namespace
} // namespace feedback_data
} // namespace forensics
diff --git a/src/developer/forensics/testing/stubs/cobalt_logger.cc b/src/developer/forensics/testing/stubs/cobalt_logger.cc
index 17b342e..1605d8f 100644
--- a/src/developer/forensics/testing/stubs/cobalt_logger.cc
+++ b/src/developer/forensics/testing/stubs/cobalt_logger.cc
@@ -41,7 +41,7 @@
void CobaltLoggerBase::SetLastEvent(uint32_t metric_id, std::vector<uint32_t> event_codes,
uint64_t count) {
events_.push_back(
- cobalt::Event(cobalt::EventType::kMultidimensionalOccurrence, metric_id, event_codes, count));
+ cobalt::Event(cobalt::EventType::kMultidimensionalEvent, metric_id, event_codes, count));
}
void CobaltLogger::LogEvent(uint32_t metric_id, uint32_t event_code, LogEventCallback callback) {
diff --git a/src/developer/forensics/utils/cobalt/event.cc b/src/developer/forensics/utils/cobalt/event.cc
index c8c5b7d..444d925 100644
--- a/src/developer/forensics/utils/cobalt/event.cc
+++ b/src/developer/forensics/utils/cobalt/event.cc
@@ -20,8 +20,7 @@
return false;
}
- if (lhs.type != EventType::kMultidimensionalOccurrence &&
- lhs.dimensions[0] != rhs.dimensions[0]) {
+ if (lhs.type != EventType::kMultidimensionalEvent && lhs.dimensions[0] != rhs.dimensions[0]) {
return false;
}
@@ -33,7 +32,7 @@
return lhs.count == rhs.count;
case EventType::kTimeElapsed:
return lhs.usecs_elapsed == rhs.usecs_elapsed;
- case EventType::kMultidimensionalOccurrence:
+ case EventType::kMultidimensionalEvent:
std::vector lhs_events = lhs.dimensions;
std::vector rhs_events = rhs.dimensions;
@@ -58,7 +57,7 @@
return fxl::StringPrintf(
"{type: time elapsed, metric_id: %u, dimension: %u, usecs elapsed: %lu}", metric_id,
dimensions[0], usecs_elapsed);
- case EventType::kMultidimensionalOccurrence:
+ case EventType::kMultidimensionalEvent:
std::string dimensions_str;
for (const auto& dimension : dimensions) {
dimensions_str += fxl::StringPrintf("%u, ", dimension);
diff --git a/src/developer/forensics/utils/cobalt/event.h b/src/developer/forensics/utils/cobalt/event.h
index 505c7eb..1b62cb9 100644
--- a/src/developer/forensics/utils/cobalt/event.h
+++ b/src/developer/forensics/utils/cobalt/event.h
@@ -41,7 +41,7 @@
template <typename DimensionTypesH, typename... DimensionTypesT,
typename = std::enable_if_t<(std::is_enum_v<DimensionTypesT> && ...)>>
explicit Event(DimensionTypesH dimensions_h, DimensionTypesT... dimensions_t)
- : type(EventType::kMultidimensionalOccurrence),
+ : type(EventType::kMultidimensionalEvent),
metric_id(MetricIDForEventCode(dimensions_h, dimensions_t...)),
dimensions(std::vector<uint32_t>({
static_cast<uint32_t>(dimensions_h),
diff --git a/src/developer/forensics/utils/cobalt/logger.cc b/src/developer/forensics/utils/cobalt/logger.cc
index 5f01ee6..f55a432 100644
--- a/src/developer/forensics/utils/cobalt/logger.cc
+++ b/src/developer/forensics/utils/cobalt/logger.cc
@@ -160,7 +160,7 @@
logger_->LogElapsedTime(event.metric_id, event.dimensions[0], /*component=*/"",
/*elapsed_micros=*/event.usecs_elapsed, std::move(cb));
break;
- case EventType::kMultidimensionalOccurrence:
+ case EventType::kMultidimensionalEvent:
fuchsia::cobalt::CobaltEvent cobalt_event;
cobalt_event.metric_id = event.metric_id;
cobalt_event.event_codes = event.dimensions;
diff --git a/src/developer/forensics/utils/cobalt/logger.h b/src/developer/forensics/utils/cobalt/logger.h
index fc05a58..4c0226b 100644
--- a/src/developer/forensics/utils/cobalt/logger.h
+++ b/src/developer/forensics/utils/cobalt/logger.h
@@ -31,6 +31,11 @@
Logger(async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
std::unique_ptr<timekeeper::Clock> clock = std::make_unique<timekeeper::SystemClock>());
+ // Log event with no dimensions.
+ void LogEvent(uint32_t metric_id, uint64_t count) {
+ LogEvent(Event(cobalt::EventType::kMultidimensionalEvent, metric_id, {}, count));
+ }
+
// Log an occurrence event with fuchsia.cobalt.Logger with the provided parameters. If the service
// is not accessible, keep the parameters to try again later.
template <typename... DimensionTypes>
diff --git a/src/developer/forensics/utils/cobalt/metrics.h b/src/developer/forensics/utils/cobalt/metrics.h
index 66e6184..48849b48 100644
--- a/src/developer/forensics/utils/cobalt/metrics.h
+++ b/src/developer/forensics/utils/cobalt/metrics.h
@@ -11,6 +11,7 @@
namespace cobalt {
constexpr auto kProjectId = cobalt_registry::kProjectId;
+constexpr auto kInspectBudgetMetricId = cobalt_registry::kMaxInputInspectBudgetMetricId;
enum class CrashState {
kUnknown = cobalt_registry::CrashMetricDimensionState::Unknown,
@@ -165,7 +166,7 @@
kOccurrence,
kCount,
kTimeElapsed,
- kMultidimensionalOccurrence,
+ kMultidimensionalEvent,
};
inline constexpr EventType EventTypeForEventCode(const SnapshotVersion version) {