Don't generate observations for metrics/reports in earlier release stages.
Bug: b/280897137
Change-Id: Iba5da796512b9c2d5a20daa8247e8c276b79092d
Reviewed-on: https://fuchsia-review.googlesource.com/c/cobalt/+/853096
Fuchsia-Auto-Submit: Cameron Dale <camrdale@google.com>
Reviewed-by: Steve Fung <stevefung@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
diff --git a/src/local_aggregation/observation_generator.cc b/src/local_aggregation/observation_generator.cc
index 272ffdf..ea121a7 100644
--- a/src/local_aggregation/observation_generator.cc
+++ b/src/local_aggregation/observation_generator.cc
@@ -124,6 +124,11 @@
for (lib::MetricIdentifier metric_identifier : project->ListMetrics()) {
const MetricDefinition* metric = project->GetMetric(metric_identifier);
+ if (system_data_.release_stage() > metric->meta_data().max_release_stage()) {
+ // Quietly ignore metric not collected in this device's release stage.
+ continue;
+ }
+
lib::statusor::StatusOr<LocalAggregateStorage::MetricAggregateRef> aggregate_or =
aggregate_storage_.GetMetricAggregate(metric_identifier);
if (!aggregate_or.ok()) {
@@ -134,6 +139,12 @@
logger::MetricRef metric_ref = project->RefMetric(metric);
for (const ReportDefinition& report : metric->reports()) {
+ if (report.max_release_stage() != ReleaseStage::RELEASE_STAGE_NOT_SET &&
+ system_data_.release_stage() > report.max_release_stage()) {
+ // Quietly ignore report not collected in this device's release stage.
+ continue;
+ }
+
lib::statusor::StatusOr<util::NotNullUniquePtr<AggregationProcedure>> not_null_procedure =
AggregationProcedure::Get(*metric, report);
if (!not_null_procedure.ok()) {
diff --git a/src/local_aggregation/observation_generator_test.cc b/src/local_aggregation/observation_generator_test.cc
index 0a1d169..0183c41 100644
--- a/src/local_aggregation/observation_generator_test.cc
+++ b/src/local_aggregation/observation_generator_test.cc
@@ -1857,4 +1857,122 @@
}
}
+TEST_F(PrivacyObservationGeneratorTest, SkipsReportsNotInTheReleaseStage) {
+ const MetricDefinition* metric =
+ project_context_->GetMetric(privacy::kOccurrenceMetricPrivacyMetricId);
+ std::unique_ptr<util::UtcTimeConverter> converter = std::make_unique<util::UtcTimeConverter>();
+ CB_ASSERT_OK_AND_ASSIGN(uint32_t start_day_index,
+ util::TimePointToDayIndex(starting_time_, *converter, *metric));
+
+ SystemProfile system_profile;
+ system_profile.set_os(SystemProfile::FUCHSIA);
+ system_profile.set_system_version("100");
+ uint64_t system_profile_hash = util::Farmhash64(system_profile.SerializeAsString());
+ {
+ MetricAggregateRef aggregate = GetMetricAggregate(privacy::kOccurrenceMetricPrivacyMetricId);
+ ReportAggregate* report =
+ &(*aggregate.aggregate()->mutable_by_report_id())
+ [privacy::kOccurrenceMetricPrivacyNotCollectedDebugReportReportId];
+ report->mutable_daily()->set_last_day_index(start_day_index - 1);
+ SystemProfileAggregate* system_profile_agg =
+ (*report->mutable_daily()->mutable_by_day_index())[start_day_index]
+ .add_system_profile_aggregates();
+ system_profile_agg->set_system_profile_hash(system_profile_hash);
+ system_profile_agg->add_by_event_code()
+ ->mutable_data()
+ ->mutable_at_least_once()
+ ->set_at_least_once(true);
+ aggregate.StoreFilteredSystemProfile(system_profile_hash, system_profile);
+ ASSERT_TRUE(aggregate.Save().ok());
+ }
+
+ std::vector<Observation> observations;
+ std::vector<ObservationMetadata> metadatas;
+ int contribution_count = 0;
+ TestObservationStoreWriter test_writer(
+ [&observations, &metadatas, &contribution_count](
+ std::unique_ptr<observation_store::StoredObservation> observation,
+ std::unique_ptr<ObservationMetadata> metadata) {
+ if (metadata->metric_id() == privacy::kOccurrenceMetricPrivacyMetricId &&
+ metadata->report_id() ==
+ privacy::kOccurrenceMetricPrivacyNotCollectedDebugReportReportId) {
+ metadatas.push_back(*metadata);
+ if (observation->has_unencrypted()) {
+ observations.push_back(observation->unencrypted());
+ }
+ if (!observation->contribution_id().empty()) {
+ contribution_count++;
+ }
+ }
+ });
+
+ logger::ObservationWriter observation_writer(test_writer, nullptr);
+ ConstructObservationGenerator(observation_writer, *converter);
+ GenerateObservationsOnce(util::FromUnixSeconds(util::DayIndexToUnixSeconds(start_day_index + 1)));
+
+ // No observations should be generated for the DEBUG report on the GA device.
+ EXPECT_EQ(observations.size(), 0);
+ EXPECT_EQ(contribution_count, 0);
+ EXPECT_EQ(metadatas.size(), 0);
+}
+
+TEST_F(PrivacyObservationGeneratorTest, SkipsMetricsNotInTheReleaseStage) {
+ const MetricDefinition* metric =
+ project_context_->GetMetric(privacy::kNotCollectedDebugMetricMetricId);
+ std::unique_ptr<util::UtcTimeConverter> converter = std::make_unique<util::UtcTimeConverter>();
+ CB_ASSERT_OK_AND_ASSIGN(uint32_t start_day_index,
+ util::TimePointToDayIndex(starting_time_, *converter, *metric));
+
+ SystemProfile system_profile;
+ system_profile.set_os(SystemProfile::FUCHSIA);
+ system_profile.set_system_version("100");
+ uint64_t system_profile_hash = util::Farmhash64(system_profile.SerializeAsString());
+ {
+ MetricAggregateRef aggregate = GetMetricAggregate(privacy::kNotCollectedDebugMetricMetricId);
+ ReportAggregate* report =
+ &(*aggregate.aggregate()->mutable_by_report_id())
+ [privacy::kNotCollectedDebugMetricUniqueDeviceCountsReport1DayReportId];
+ report->mutable_daily()->set_last_day_index(start_day_index - 1);
+ SystemProfileAggregate* system_profile_agg =
+ (*report->mutable_daily()->mutable_by_day_index())[start_day_index]
+ .add_system_profile_aggregates();
+ system_profile_agg->set_system_profile_hash(system_profile_hash);
+ system_profile_agg->add_by_event_code()
+ ->mutable_data()
+ ->mutable_at_least_once()
+ ->set_at_least_once(true);
+ aggregate.StoreFilteredSystemProfile(system_profile_hash, system_profile);
+ ASSERT_TRUE(aggregate.Save().ok());
+ }
+
+ std::vector<Observation> observations;
+ std::vector<ObservationMetadata> metadatas;
+ int contribution_count = 0;
+ TestObservationStoreWriter test_writer(
+ [&observations, &metadatas, &contribution_count](
+ std::unique_ptr<observation_store::StoredObservation> observation,
+ std::unique_ptr<ObservationMetadata> metadata) {
+ if (metadata->metric_id() == privacy::kNotCollectedDebugMetricMetricId &&
+ metadata->report_id() ==
+ privacy::kNotCollectedDebugMetricUniqueDeviceCountsReport1DayReportId) {
+ metadatas.push_back(*metadata);
+ if (observation->has_unencrypted()) {
+ observations.push_back(observation->unencrypted());
+ }
+ if (!observation->contribution_id().empty()) {
+ contribution_count++;
+ }
+ }
+ });
+
+ logger::ObservationWriter observation_writer(test_writer, nullptr);
+ ConstructObservationGenerator(observation_writer, *converter);
+ GenerateObservationsOnce(util::FromUnixSeconds(util::DayIndexToUnixSeconds(start_day_index + 1)));
+
+ // No observations should be generated for the DEBUG metric on the GA device.
+ EXPECT_EQ(observations.size(), 0);
+ EXPECT_EQ(contribution_count, 0);
+ EXPECT_EQ(metadatas.size(), 0);
+}
+
} // namespace cobalt::local_aggregation
diff --git a/src/local_aggregation/testing/test_privacy_registry/CustomerA/ProjectA1/metrics.yaml b/src/local_aggregation/testing/test_privacy_registry/CustomerA/ProjectA1/metrics.yaml
index 1c1745e..da60b02 100644
--- a/src/local_aggregation/testing/test_privacy_registry/CustomerA/ProjectA1/metrics.yaml
+++ b/src/local_aggregation/testing/test_privacy_registry/CustomerA/ProjectA1/metrics.yaml
@@ -26,3 +26,32 @@
event_vector_buffer_max: 100
system_profile_field: [OS, SYSTEM_VERSION]
system_profile_selection: SELECT_LAST
+ - id: 3
+ report_name: "not_collected_debug_report"
+ report_type: UNIQUE_DEVICE_COUNTS
+ local_aggregation_procedure: AT_LEAST_ONCE
+ local_aggregation_period: WINDOW_1_DAY
+ privacy_level: LOW_PRIVACY
+ event_vector_buffer_max: 100
+ system_profile_field: [OS, SYSTEM_VERSION]
+ system_profile_selection: SELECT_LAST
+ max_release_stage: DEBUG
+
+ - id: 2
+ metric_name: "not_collected_debug_metric"
+ metric_type: OCCURRENCE
+ metric_semantics: [NETWORK_COMMUNICATION]
+ time_zone_policy: UTC
+ meta_data:
+ expiration_date: "2023/01/01"
+ max_release_stage: DEBUG
+ reports:
+ - id: 1
+ report_name: "unique_device_counts_report_1_day"
+ report_type: UNIQUE_DEVICE_COUNTS
+ local_aggregation_procedure: AT_LEAST_ONCE
+ local_aggregation_period: WINDOW_1_DAY
+ privacy_level: LOW_PRIVACY
+ event_vector_buffer_max: 100
+ system_profile_field: [OS, SYSTEM_VERSION]
+ system_profile_selection: SELECT_LAST