From b8f5403d1753e793d95a5134384aff1a937e6cec Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Mon, 23 Mar 2020 13:42:42 -0700 Subject: [PATCH 1/2] Save metadata to Disk Bug: 148280505 Test: bit statsd_test:* Change-Id: Ib9c6b9b4f22e7380717b480c7ae4a37bb3364619 --- cmds/statsd/Android.bp | 1 + cmds/statsd/src/StatsLogProcessor.cpp | 51 +++++++++ cmds/statsd/src/StatsLogProcessor.h | 19 ++++ cmds/statsd/src/StatsService.cpp | 12 ++- cmds/statsd/src/anomaly/AnomalyTracker.cpp | 38 ++++++- cmds/statsd/src/anomaly/AnomalyTracker.h | 7 ++ cmds/statsd/src/metadata_util.cpp | 73 +++++++++++++ cmds/statsd/src/metadata_util.h | 29 +++++ cmds/statsd/src/metrics/MetricsManager.cpp | 20 +++- cmds/statsd/src/metrics/MetricsManager.h | 7 ++ cmds/statsd/src/statsd_metadata.proto | 10 +- .../tests/e2e/Anomaly_count_e2e_test.cpp | 100 ++++++++++++++++-- 12 files changed, 351 insertions(+), 16 deletions(-) create mode 100644 cmds/statsd/src/metadata_util.cpp create mode 100644 cmds/statsd/src/metadata_util.h diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 45f21ae8e3e12..750b94264dbdd 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -78,6 +78,7 @@ cc_defaults { "src/matchers/EventMatcherWizard.cpp", "src/matchers/matcher_util.cpp", "src/matchers/SimpleLogMatchingTracker.cpp", + "src/metadata_util.cpp", "src/metrics/CountMetricProducer.cpp", "src/metrics/duration_helper/MaxDurationTracker.cpp", "src/metrics/duration_helper/OringDurationTracker.cpp", diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 69b9fc7ad9a09..45cb07b93eb99 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -79,6 +79,7 @@ constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS #define NS_PER_HOUR 3600 * NS_PER_SEC #define STATS_ACTIVE_METRIC_DIR "/data/misc/stats-active-metric" +#define STATS_METADATA_DIR "/data/misc/stats-metadata" // Cool down period for writing data to disk to avoid overwriting files. #define WRITE_DATA_COOL_DOWN_SEC 5 @@ -851,6 +852,56 @@ void StatsLogProcessor::SaveActiveConfigsToDisk(int64_t currentTimeNs) { proto.flush(fd.get()); } +void StatsLogProcessor::SaveMetadataToDisk(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs) { + std::lock_guard lock(mMetricsMutex); + // Do not write to disk if we already have in the last few seconds. + if (static_cast (systemElapsedTimeNs) < + mLastMetadataWriteNs + WRITE_DATA_COOL_DOWN_SEC * NS_PER_SEC) { + ALOGI("Statsd skipping writing metadata to disk. Already wrote data in last %d seconds", + WRITE_DATA_COOL_DOWN_SEC); + return; + } + mLastMetadataWriteNs = systemElapsedTimeNs; + + metadata::StatsMetadataList metadataList; + WriteMetadataToProtoLocked( + currentWallClockTimeNs, systemElapsedTimeNs, &metadataList); + + string file_name = StringPrintf("%s/metadata", STATS_METADATA_DIR); + StorageManager::deleteFile(file_name.c_str()); + + if (metadataList.stats_metadata_size() == 0) { + // Skip the write if we have nothing to write. + return; + } + + std::string data; + metadataList.SerializeToString(&data); + StorageManager::writeFile(file_name.c_str(), data.c_str(), data.size()); +} + +void StatsLogProcessor::WriteMetadataToProto(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::StatsMetadataList* metadataList) { + std::lock_guard lock(mMetricsMutex); + WriteMetadataToProtoLocked(currentWallClockTimeNs, systemElapsedTimeNs, metadataList); +} + +void StatsLogProcessor::WriteMetadataToProtoLocked(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::StatsMetadataList* metadataList) { + for (const auto& pair : mMetricsManagers) { + const sp& metricsManager = pair.second; + metadata::StatsMetadata* statsMetadata = metadataList->add_stats_metadata(); + bool metadataWritten = metricsManager->writeMetadataToProto(currentWallClockTimeNs, + systemElapsedTimeNs, statsMetadata); + if (!metadataWritten) { + metadataList->mutable_stats_metadata()->RemoveLast(); + } + } +} + void StatsLogProcessor::WriteActiveConfigsToProtoOutputStream( int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto) { std::lock_guard lock(mMetricsMutex); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 42e56760fb898..760785a12a636 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -24,6 +24,7 @@ #include "external/StatsPullerManager.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" #include #include @@ -89,6 +90,14 @@ public: /* Load configs containing metrics with active activations from disk. */ void LoadActiveConfigsFromDisk(); + /* Persist metadata for configs and metrics to disk. */ + void SaveMetadataToDisk(int64_t currentWallClockTimeNs, int64_t systemElapsedTimeNs); + + /* Writes the statsd metadata for all configs and metrics to StatsMetadataList. */ + void WriteMetadataToProto(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::StatsMetadataList* metadataList); + /* Sets the active status/ttl for all configs and metrics to the status in ActiveConfigList. */ void SetConfigsActiveState(const ActiveConfigList& activeConfigList, int64_t currentTimeNs); @@ -173,8 +182,13 @@ private: void SetConfigsActiveStateLocked(const ActiveConfigList& activeConfigList, int64_t currentTimeNs); + void WriteMetadataToProtoLocked(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::StatsMetadataList* metadataList); + void WriteDataToDiskLocked(const DumpReportReason dumpReportReason, const DumpLatency dumpLatency); + void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs, const DumpReportReason dumpReportReason, const DumpLatency dumpLatency); @@ -241,6 +255,9 @@ private: // Last time we wrote active metrics to disk. int64_t mLastActiveMetricsWriteNs = 0; + //Last time we wrote metadata to disk. + int64_t mLastMetadataWriteNs = 0; + #ifdef VERY_VERBOSE_PRINTING bool mPrintAllLogs = false; #endif @@ -278,6 +295,8 @@ private: FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); + FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written); + FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 812d10be4bf6b..03955bcb89f89 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -1007,6 +1007,7 @@ Status StatsService::informDeviceShutdown() { VLOG("StatsService::informDeviceShutdown"); mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST); mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); + mProcessor->SaveMetadataToDisk(getWallClockNs(), getElapsedRealtimeNs()); return Status::ok(); } @@ -1048,6 +1049,7 @@ void StatsService::Terminate() { if (mProcessor != nullptr) { mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST); mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); + mProcessor->SaveMetadataToDisk(getWallClockNs(), getElapsedRealtimeNs()); } } @@ -1280,15 +1282,17 @@ void StatsService::statsCompanionServiceDiedImpl() { if (mProcessor != nullptr) { ALOGW("Reset statsd upon system server restarts."); int64_t systemServerRestartNs = getElapsedRealtimeNs(); - ProtoOutputStream proto; + ProtoOutputStream activeConfigsProto; mProcessor->WriteActiveConfigsToProtoOutputStream(systemServerRestartNs, - STATSCOMPANION_DIED, &proto); - + STATSCOMPANION_DIED, &activeConfigsProto); + metadata::StatsMetadataList metadataList; + mProcessor->WriteMetadataToProto(getWallClockNs(), + systemServerRestartNs, &metadataList); mProcessor->WriteDataToDisk(STATSCOMPANION_DIED, FAST); mProcessor->resetConfigs(); std::string serializedActiveConfigs; - if (proto.serializeToString(&serializedActiveConfigs)) { + if (activeConfigsProto.serializeToString(&serializedActiveConfigs)) { ActiveConfigList activeConfigs; if (activeConfigs.ParseFromString(serializedActiveConfigs)) { mProcessor->SetConfigsActiveState(activeConfigs, systemServerRestartNs); diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index a21abbf042cba..2ff2589158be2 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -18,9 +18,11 @@ #include "Log.h" #include "AnomalyTracker.h" -#include "subscriber_util.h" #include "external/Perfetto.h" #include "guardrail/StatsdStats.h" +#include "metadata_util.h" +#include "stats_log_util.h" +#include "subscriber_util.h" #include "subscriber/IncidentdReporter.h" #include "subscriber/SubscriberReporter.h" @@ -262,6 +264,40 @@ void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t me triggerSubscribers(mAlert.id(), metric_id, key, metricValue, mConfigKey, mSubscriptions); } +bool AnomalyTracker::writeAlertMetadataToProto(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::AlertMetadata* alertMetadata) { + bool metadataWritten = false; + + if (mRefractoryPeriodEndsSec.empty()) { + return false; + } + + for (const auto& it: mRefractoryPeriodEndsSec) { + // Do not write the timestamp to disk if it has already expired + if (it.second < systemElapsedTimeNs / NS_PER_SEC) { + continue; + } + + metadataWritten = true; + if (alertMetadata->alert_dim_keyed_data_size() == 0) { + alertMetadata->set_alert_id(mAlert.id()); + } + + metadata::AlertDimensionKeyedData* keyedData = alertMetadata->add_alert_dim_keyed_data(); + // We convert and write the refractory_end_sec to wall clock time because we do not know + // when statsd will start again. + int32_t refractoryEndWallClockSec = (int32_t) ((currentWallClockTimeNs / NS_PER_SEC) + + (it.second - systemElapsedTimeNs / NS_PER_SEC)); + + keyedData->set_last_refractory_ends_sec(refractoryEndWallClockSec); + writeMetricDimensionKeyToMetadataDimensionKey( + it.first, keyedData->mutable_dimension_key()); + } + + return metadataWritten; +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h index 794ee988ef557..0daa535e3e533 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.h +++ b/cmds/statsd/src/anomaly/AnomalyTracker.h @@ -24,6 +24,7 @@ #include "AlarmMonitor.h" #include "config/ConfigKey.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert +#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" // AlertMetadata #include "stats_util.h" // HashableDimensionKey and DimToValMap namespace android { @@ -112,6 +113,12 @@ public: return; // The base AnomalyTracker class doesn't have alarms. } + // Writes metadata of the alert (refractory_period_end_sec) to AlertMetadata. + // Returns true if at least one element is written to alertMetadata. + bool writeAlertMetadataToProto( + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, metadata::AlertMetadata* alertMetadata); + protected: // For testing only. // Returns the alarm timestamp in seconds for the query dimension if it exists. Otherwise diff --git a/cmds/statsd/src/metadata_util.cpp b/cmds/statsd/src/metadata_util.cpp new file mode 100644 index 0000000000000..bfe850fb67c06 --- /dev/null +++ b/cmds/statsd/src/metadata_util.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FieldValue.h" +#include "metadata_util.h" + +namespace android { +namespace os { +namespace statsd { + +void writeValueToProto(metadata::FieldValue* metadataFieldValue, const Value& value) { + std::string storage_value; + switch (value.getType()) { + case INT: + metadataFieldValue->set_value_int(value.int_value); + break; + case LONG: + metadataFieldValue->set_value_long(value.long_value); + break; + case FLOAT: + metadataFieldValue->set_value_float(value.float_value); + break; + case DOUBLE: + metadataFieldValue->set_value_double(value.double_value); + break; + case STRING: + metadataFieldValue->set_value_str(value.str_value.c_str()); + break; + case STORAGE: // byte array + storage_value = ((char*) value.storage_value.data()); + metadataFieldValue->set_value_storage(storage_value); + break; + default: + break; + } +} + +void writeMetricDimensionKeyToMetadataDimensionKey( + const MetricDimensionKey& metricKey, + metadata::MetricDimensionKey* metadataMetricKey) { + for (const FieldValue& fieldValue : metricKey.getDimensionKeyInWhat().getValues()) { + metadata::FieldValue* metadataFieldValue = metadataMetricKey->add_dimension_key_in_what(); + metadata::Field* metadataField = metadataFieldValue->mutable_field(); + metadataField->set_tag(fieldValue.mField.getTag()); + metadataField->set_field(fieldValue.mField.getField()); + writeValueToProto(metadataFieldValue, fieldValue.mValue); + } + + for (const FieldValue& fieldValue : metricKey.getStateValuesKey().getValues()) { + metadata::FieldValue* metadataFieldValue = metadataMetricKey->add_state_values_key(); + metadata::Field* metadataField = metadataFieldValue->mutable_field(); + metadataField->set_tag(fieldValue.mField.getTag()); + metadataField->set_field(fieldValue.mField.getField()); + writeValueToProto(metadataFieldValue, fieldValue.mValue); + } +} + +} // namespace statsd +} // namespace os +} // namespace android \ No newline at end of file diff --git a/cmds/statsd/src/metadata_util.h b/cmds/statsd/src/metadata_util.h new file mode 100644 index 0000000000000..23e94b060c560 --- /dev/null +++ b/cmds/statsd/src/metadata_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "HashableDimensionKey.h" + +#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" // AlertMetadata + +namespace android { +namespace os { +namespace statsd { + +void writeMetricDimensionKeyToMetadataDimensionKey(const MetricDimensionKey& metricKey, + metadata::MetricDimensionKey* metadataMetricKey); + +} // namespace statsd +} // namespace os +} // namespace android \ No newline at end of file diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index fca48f96f56da..9e9b6ff8f7dfa 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -560,8 +560,24 @@ void MetricsManager::writeActiveConfigToProtoOutputStream( } } - - +bool MetricsManager::writeMetadataToProto(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::StatsMetadata* statsMetadata) { + bool metadataWritten = false; + metadata::ConfigKey* configKey = statsMetadata->mutable_config_key(); + configKey->set_config_id(mConfigKey.GetId()); + configKey->set_uid(mConfigKey.GetUid()); + for (const auto& anomalyTracker : mAllAnomalyTrackers) { + metadata::AlertMetadata* alertMetadata = statsMetadata->add_alert_metadata(); + bool alertWritten = anomalyTracker->writeAlertMetadataToProto(currentWallClockTimeNs, + systemElapsedTimeNs, alertMetadata); + if (!alertWritten) { + statsMetadata->mutable_alert_metadata()->RemoveLast(); + } + metadataWritten |= alertWritten; + } + return metadataWritten; +} } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 7500ec91ce307..1813957859bb2 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -23,6 +23,7 @@ #include "config/ConfigKey.h" #include "external/StatsPullerManager.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" #include "logd/LogEvent.h" #include "matchers/LogMatchingTracker.h" #include "metrics/MetricProducer.h" @@ -139,6 +140,10 @@ public: void writeActiveConfigToProtoOutputStream( int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto); + // Returns true if at least one piece of metadata is written. + bool writeMetadataToProto(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs, + metadata::StatsMetadata* statsMetadata); private: // For test only. inline int64_t getTtlEndNs() const { return mTtlEndNs; } @@ -263,6 +268,8 @@ private: FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); + FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written); + FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); diff --git a/cmds/statsd/src/statsd_metadata.proto b/cmds/statsd/src/statsd_metadata.proto index e00fe33655ca9..200b392f7542f 100644 --- a/cmds/statsd/src/statsd_metadata.proto +++ b/cmds/statsd/src/statsd_metadata.proto @@ -45,11 +45,15 @@ message MetricDimensionKey { repeated FieldValue state_values_key = 2; } +message AlertDimensionKeyedData { + // The earliest time the alert can be fired again in wall clock time. + optional int32 last_refractory_ends_sec = 1; + optional MetricDimensionKey dimension_key = 2; +} + message AlertMetadata { optional int64 alert_id = 1; - // The earliest time the alert can be fired again in wall clock time. - optional int32 last_refractory_ends_sec = 2; - optional MetricDimensionKey dimension_key = 3; + repeated AlertDimensionKeyedData alert_dim_keyed_data = 2; } // All metadata for a config in statsd diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp index 9c6965dc9e6cb..8e0687a598cd0 100644 --- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp @@ -14,6 +14,7 @@ #include +#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" #include "src/StatsLogProcessor.h" #include "src/stats_log_util.h" #include "tests/statsd_test_util.h" @@ -28,7 +29,7 @@ namespace statsd { namespace { -StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) { +StatsdConfig CreateStatsdConfig(int num_buckets, int threshold, int refractory_period_sec) { StatsdConfig config; config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher(); @@ -46,7 +47,7 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) { alert->set_id(StringToId("alert")); alert->set_metric_id(123456); alert->set_num_buckets(num_buckets); - alert->set_refractory_period_secs(10); + alert->set_refractory_period_secs(refractory_period_sec); alert->set_trigger_if_sum_gt(threshold); return config; } @@ -56,9 +57,9 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) { TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) { const int num_buckets = 1; const int threshold = 3; - auto config = CreateStatsdConfig(num_buckets, threshold); + const int refractory_period_sec = 10; + auto config = CreateStatsdConfig(num_buckets, threshold, refractory_period_sec); const uint64_t alert_id = config.alert(0).id(); - const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs(); int64_t bucketStartTimeNs = 10000000000; int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; @@ -173,9 +174,9 @@ TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) { TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) { const int num_buckets = 3; const int threshold = 3; - auto config = CreateStatsdConfig(num_buckets, threshold); + const int refractory_period_sec = 10; + auto config = CreateStatsdConfig(num_buckets, threshold, refractory_period_sec); const uint64_t alert_id = config.alert(0).id(); - const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs(); int64_t bucketStartTimeNs = 10000000000; int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; @@ -240,6 +241,93 @@ TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) { anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1)); } +TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written) { + const int num_buckets = 1; + const int threshold = 0; + const int refractory_period_sec = 86400 * 365; // 1 year + auto config = CreateStatsdConfig(num_buckets, threshold, refractory_period_sec); + const int64_t alert_id = config.alert(0).id(); + + int64_t bucketStartTimeNs = 10000000000; + + int configUid = 2000; + int64_t configId = 1000; + ConfigKey cfgKey(configUid, configId); + auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size()); + + metadata::StatsMetadataList result; + int64_t mockWallClockNs = 1584991200 * NS_PER_SEC; + int64_t mockElapsedTimeNs = bucketStartTimeNs + 5000 * NS_PER_SEC; + processor->WriteMetadataToProto(mockWallClockNs, mockElapsedTimeNs, &result); + + EXPECT_EQ(result.stats_metadata_size(), 0); +} + +TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk) { + const int num_buckets = 1; + const int threshold = 0; + const int refractory_period_sec = 86400 * 365; // 1 year + auto config = CreateStatsdConfig(num_buckets, threshold, refractory_period_sec); + const int64_t alert_id = config.alert(0).id(); + + int64_t bucketStartTimeNs = 10000000000; + + int configUid = 2000; + int64_t configId = 1000; + ConfigKey cfgKey(configUid, configId); + auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size()); + + sp anomalyTracker = + processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0]; + + std::vector attributionUids1 = {111}; + std::vector attributionTags1 = {"App1"}; + std::vector attributionUids2 = {111, 222}; + std::vector attributionTags2 = {"App1", "GMSCoreModule1"}; + + FieldValue fieldValue1(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101), + Value((int32_t)111)); + HashableDimensionKey whatKey1({fieldValue1}); + MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY); + + auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1, + attributionTags1, "wl1"); + processor->OnLogEvent(event.get()); + EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 2) / NS_PER_SEC + 1, + anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1)); + + metadata::StatsMetadataList result; + int64_t mockWallClockNs = 1584991200 * NS_PER_SEC; + int64_t mockElapsedTimeNs = bucketStartTimeNs + 5000 * NS_PER_SEC; + processor->WriteMetadataToProto(mockWallClockNs, mockElapsedTimeNs, &result); + + metadata::StatsMetadata statsMetadata = result.stats_metadata(0); + EXPECT_EQ(result.stats_metadata_size(), 1); + EXPECT_EQ(statsMetadata.config_key().config_id(), configId); + EXPECT_EQ(statsMetadata.config_key().uid(), configUid); + + metadata::AlertMetadata alertMetadata = statsMetadata.alert_metadata(0); + EXPECT_EQ(statsMetadata.alert_metadata_size(), 1); + EXPECT_EQ(alertMetadata.alert_id(), alert_id); + metadata::AlertDimensionKeyedData keyedData = alertMetadata.alert_dim_keyed_data(0); + EXPECT_EQ(alertMetadata.alert_dim_keyed_data_size(), 1); + EXPECT_EQ(keyedData.last_refractory_ends_sec(), + anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1) - + mockElapsedTimeNs / NS_PER_SEC + + mockWallClockNs / NS_PER_SEC); + + metadata::MetricDimensionKey metadataDimKey = keyedData.dimension_key(); + metadata::FieldValue dimKeyInWhat = metadataDimKey.dimension_key_in_what(0); + EXPECT_EQ(dimKeyInWhat.field().tag(), fieldValue1.mField.getTag()); + EXPECT_EQ(dimKeyInWhat.field().field(), fieldValue1.mField.getField()); + EXPECT_EQ(dimKeyInWhat.value_int(), fieldValue1.mValue.int_value); +} #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif From 475677e771f6f78d688607c3ef56a17625934dec Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Mon, 30 Mar 2020 19:52:07 -0700 Subject: [PATCH 2/2] Load Metadata from Disk Bug: 148280505 Test: bit statsd_test:* Test: Manual - Added Config, Tested System Server Crash Test: Manual - Added Config, Tested Device restart Change-Id: Icd1b1e57bbf24e4a5676820a2b955f2034d4b37d --- cmds/statsd/Android.bp | 1 + cmds/statsd/src/StatsLogProcessor.cpp | 54 +++++++++++++++ cmds/statsd/src/StatsLogProcessor.h | 14 ++++ cmds/statsd/src/StatsService.cpp | 2 + cmds/statsd/src/anomaly/AnomalyTracker.cpp | 18 +++++ cmds/statsd/src/anomaly/AnomalyTracker.h | 7 +- cmds/statsd/src/metadata_util.cpp | 49 +++++++++++++ cmds/statsd/src/metadata_util.h | 3 + cmds/statsd/src/metrics/MetricsManager.cpp | 16 +++++ cmds/statsd/src/metrics/MetricsManager.h | 5 ++ .../tests/e2e/Anomaly_count_e2e_test.cpp | 53 ++++++++++++++ cmds/statsd/tests/metadata_util_test.cpp | 69 +++++++++++++++++++ 12 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 cmds/statsd/tests/metadata_util_test.cpp diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 750b94264dbdd..ac537cc33f84a 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -340,6 +340,7 @@ cc_test { "tests/log_event/LogEventQueue_test.cpp", "tests/LogEntryMatcher_test.cpp", "tests/LogEvent_test.cpp", + "tests/metadata_util_test.cpp", "tests/metrics/CountMetricProducer_test.cpp", "tests/metrics/DurationMetricProducer_test.cpp", "tests/metrics/EventMetricProducer_test.cpp", diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 45cb07b93eb99..0a615724d1f1e 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -902,6 +902,60 @@ void StatsLogProcessor::WriteMetadataToProtoLocked(int64_t currentWallClockTimeN } } +void StatsLogProcessor::LoadMetadataFromDisk(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs) { + std::lock_guard lock(mMetricsMutex); + string file_name = StringPrintf("%s/metadata", STATS_METADATA_DIR); + int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); + if (-1 == fd) { + VLOG("Attempt to read %s but failed", file_name.c_str()); + StorageManager::deleteFile(file_name.c_str()); + return; + } + string content; + if (!android::base::ReadFdToString(fd, &content)) { + ALOGE("Attempt to read %s but failed", file_name.c_str()); + close(fd); + StorageManager::deleteFile(file_name.c_str()); + return; + } + + close(fd); + + metadata::StatsMetadataList statsMetadataList; + if (!statsMetadataList.ParseFromString(content)) { + ALOGE("Attempt to read %s but failed; failed to metadata", file_name.c_str()); + StorageManager::deleteFile(file_name.c_str()); + return; + } + SetMetadataStateLocked(statsMetadataList, currentWallClockTimeNs, systemElapsedTimeNs); + StorageManager::deleteFile(file_name.c_str()); +} + +void StatsLogProcessor::SetMetadataState(const metadata::StatsMetadataList& statsMetadataList, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs) { + std::lock_guard lock(mMetricsMutex); + SetMetadataStateLocked(statsMetadataList, currentWallClockTimeNs, systemElapsedTimeNs); +} + +void StatsLogProcessor::SetMetadataStateLocked( + const metadata::StatsMetadataList& statsMetadataList, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs) { + for (const metadata::StatsMetadata& metadata : statsMetadataList.stats_metadata()) { + ConfigKey key(metadata.config_key().uid(), metadata.config_key().config_id()); + auto it = mMetricsManagers.find(key); + if (it == mMetricsManagers.end()) { + ALOGE("No config found for configKey %s", key.ToString().c_str()); + continue; + } + VLOG("Setting metadata %s", key.ToString().c_str()); + it->second->loadMetadata(metadata, currentWallClockTimeNs, systemElapsedTimeNs); + } + VLOG("Successfully loaded %d metadata.", statsMetadataList.stats_metadata_size()); +} + void StatsLogProcessor::WriteActiveConfigsToProtoOutputStream( int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto) { std::lock_guard lock(mMetricsMutex); diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 760785a12a636..14585c3df8706 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -98,6 +98,15 @@ public: int64_t systemElapsedTimeNs, metadata::StatsMetadataList* metadataList); + /* Load stats metadata for configs and metrics from disk. */ + void LoadMetadataFromDisk(int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs); + + /* Sets the metadata for all configs and metrics */ + void SetMetadataState(const metadata::StatsMetadataList& statsMetadataList, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs); + /* Sets the active status/ttl for all configs and metrics to the status in ActiveConfigList. */ void SetConfigsActiveState(const ActiveConfigList& activeConfigList, int64_t currentTimeNs); @@ -182,6 +191,10 @@ private: void SetConfigsActiveStateLocked(const ActiveConfigList& activeConfigList, int64_t currentTimeNs); + void SetMetadataStateLocked(const metadata::StatsMetadataList& statsMetadataList, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs); + void WriteMetadataToProtoLocked(int64_t currentWallClockTimeNs, int64_t systemElapsedTimeNs, metadata::StatsMetadataList* metadataList); @@ -297,6 +310,7 @@ private: FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written); FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk); + FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 03955bcb89f89..f7e135a2ec935 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -1042,6 +1042,7 @@ Status StatsService::statsCompanionReady() { void StatsService::Startup() { mConfigManager->Startup(); mProcessor->LoadActiveConfigsFromDisk(); + mProcessor->LoadMetadataFromDisk(getWallClockNs(), getElapsedRealtimeNs()); } void StatsService::Terminate() { @@ -1298,6 +1299,7 @@ void StatsService::statsCompanionServiceDiedImpl() { mProcessor->SetConfigsActiveState(activeConfigs, systemServerRestartNs); } } + mProcessor->SetMetadataState(metadataList, getWallClockNs(), systemServerRestartNs); } mAnomalyAlarmMonitor->setStatsCompanionService(nullptr); mPeriodicAlarmMonitor->setStatsCompanionService(nullptr); diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index 2ff2589158be2..619752c7c44af 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -298,6 +298,24 @@ bool AnomalyTracker::writeAlertMetadataToProto(int64_t currentWallClockTimeNs, return metadataWritten; } +void AnomalyTracker::loadAlertMetadata( + const metadata::AlertMetadata& alertMetadata, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs) { + for (const metadata::AlertDimensionKeyedData& keyedData : + alertMetadata.alert_dim_keyed_data()) { + if ((uint64_t) keyedData.last_refractory_ends_sec() < currentWallClockTimeNs / NS_PER_SEC) { + // Do not update the timestamp if it has already expired. + continue; + } + MetricDimensionKey metricKey = loadMetricDimensionKeyFromProto( + keyedData.dimension_key()); + int32_t refractoryPeriodEndsSec = (int32_t) keyedData.last_refractory_ends_sec() - + currentWallClockTimeNs / NS_PER_SEC + systemElapsedTimeNs / NS_PER_SEC; + mRefractoryPeriodEndsSec[metricKey] = refractoryPeriodEndsSec; + } +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h index 0daa535e3e533..bf36a3bc89901 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.h +++ b/cmds/statsd/src/anomaly/AnomalyTracker.h @@ -24,7 +24,7 @@ #include "AlarmMonitor.h" #include "config/ConfigKey.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert -#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" // AlertMetadata +#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" // AlertMetadata #include "stats_util.h" // HashableDimensionKey and DimToValMap namespace android { @@ -119,6 +119,11 @@ public: int64_t currentWallClockTimeNs, int64_t systemElapsedTimeNs, metadata::AlertMetadata* alertMetadata); + void loadAlertMetadata( + const metadata::AlertMetadata& alertMetadata, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs); + protected: // For testing only. // Returns the alarm timestamp in seconds for the query dimension if it exists. Otherwise diff --git a/cmds/statsd/src/metadata_util.cpp b/cmds/statsd/src/metadata_util.cpp index bfe850fb67c06..27ee59b362425 100644 --- a/cmds/statsd/src/metadata_util.cpp +++ b/cmds/statsd/src/metadata_util.cpp @@ -21,6 +21,8 @@ namespace android { namespace os { namespace statsd { +using google::protobuf::RepeatedPtrField; + void writeValueToProto(metadata::FieldValue* metadataFieldValue, const Value& value) { std::string storage_value; switch (value.getType()) { @@ -68,6 +70,53 @@ void writeMetricDimensionKeyToMetadataDimensionKey( } } +void writeFieldValuesFromMetadata( + const RepeatedPtrField& repeatedFieldValueList, + std::vector* fieldValues) { + for (const metadata::FieldValue& metadataFieldValue : repeatedFieldValueList) { + Field field(metadataFieldValue.field().tag(), metadataFieldValue.field().field()); + Value value; + switch (metadataFieldValue.value_case()) { + case metadata::FieldValue::ValueCase::kValueInt: + value = Value(metadataFieldValue.value_int()); + break; + case metadata::FieldValue::ValueCase::kValueLong: + value = Value(metadataFieldValue.value_long()); + break; + case metadata::FieldValue::ValueCase::kValueFloat: + value = Value(metadataFieldValue.value_float()); + break; + case metadata::FieldValue::ValueCase::kValueDouble: + value = Value(metadataFieldValue.value_double()); + break; + case metadata::FieldValue::ValueCase::kValueStr: + value = Value(metadataFieldValue.value_str()); + break; + case metadata::FieldValue::ValueCase::kValueStorage: + value = Value(metadataFieldValue.value_storage()); + break; + default: + break; + } + FieldValue fieldValue(field, value); + fieldValues->emplace_back(field, value); + } +} + +MetricDimensionKey loadMetricDimensionKeyFromProto( + const metadata::MetricDimensionKey& metricDimensionKey) { + std::vector dimKeyInWhatFieldValues; + writeFieldValuesFromMetadata(metricDimensionKey.dimension_key_in_what(), + &dimKeyInWhatFieldValues); + std::vector stateValuesFieldValues; + writeFieldValuesFromMetadata(metricDimensionKey.state_values_key(), &stateValuesFieldValues); + + HashableDimensionKey dimKeyInWhat(dimKeyInWhatFieldValues); + HashableDimensionKey stateValues(stateValuesFieldValues); + MetricDimensionKey metricKey(dimKeyInWhat, stateValues); + return metricKey; +} + } // namespace statsd } // namespace os } // namespace android \ No newline at end of file diff --git a/cmds/statsd/src/metadata_util.h b/cmds/statsd/src/metadata_util.h index 23e94b060c560..84a39ff872b52 100644 --- a/cmds/statsd/src/metadata_util.h +++ b/cmds/statsd/src/metadata_util.h @@ -24,6 +24,9 @@ namespace statsd { void writeMetricDimensionKeyToMetadataDimensionKey(const MetricDimensionKey& metricKey, metadata::MetricDimensionKey* metadataMetricKey); +MetricDimensionKey loadMetricDimensionKeyFromProto( + const metadata::MetricDimensionKey& metricDimensionKey); + } // namespace statsd } // namespace os } // namespace android \ No newline at end of file diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp index 9e9b6ff8f7dfa..829ba21292b23 100644 --- a/cmds/statsd/src/metrics/MetricsManager.cpp +++ b/cmds/statsd/src/metrics/MetricsManager.cpp @@ -579,6 +579,22 @@ bool MetricsManager::writeMetadataToProto(int64_t currentWallClockTimeNs, return metadataWritten; } +void MetricsManager::loadMetadata(const metadata::StatsMetadata& metadata, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs) { + for (const metadata::AlertMetadata& alertMetadata : metadata.alert_metadata()) { + int64_t alertId = alertMetadata.alert_id(); + auto it = mAlertTrackerMap.find(alertId); + if (it == mAlertTrackerMap.end()) { + ALOGE("No anomalyTracker found for alertId %lld", (long long) alertId); + continue; + } + mAllAnomalyTrackers[it->second]->loadAlertMetadata(alertMetadata, + currentWallClockTimeNs, + systemElapsedTimeNs); + } +} + } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h index 1813957859bb2..3b63b0a86158f 100644 --- a/cmds/statsd/src/metrics/MetricsManager.h +++ b/cmds/statsd/src/metrics/MetricsManager.h @@ -144,6 +144,10 @@ public: bool writeMetadataToProto(int64_t currentWallClockTimeNs, int64_t systemElapsedTimeNs, metadata::StatsMetadata* statsMetadata); + + void loadMetadata(const metadata::StatsMetadata& metadata, + int64_t currentWallClockTimeNs, + int64_t systemElapsedTimeNs); private: // For test only. inline int64_t getTtlEndNs() const { return mTtlEndNs; } @@ -270,6 +274,7 @@ private: FRIEND_TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk_no_data_written); FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk); + FRIEND_TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets); FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period); diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp index 8e0687a598cd0..c2d70430afdf7 100644 --- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp @@ -328,6 +328,59 @@ TEST(AnomalyDetectionE2eTest, TestCountMetric_save_refractory_to_disk) { EXPECT_EQ(dimKeyInWhat.field().field(), fieldValue1.mField.getField()); EXPECT_EQ(dimKeyInWhat.value_int(), fieldValue1.mValue.int_value); } + +TEST(AnomalyDetectionE2eTest, TestCountMetric_load_refractory_from_disk) { + const int num_buckets = 1; + const int threshold = 0; + const int refractory_period_sec = 86400 * 365; // 1 year + auto config = CreateStatsdConfig(num_buckets, threshold, refractory_period_sec); + const int64_t alert_id = config.alert(0).id(); + + int64_t bucketStartTimeNs = 10000000000; + + int configUid = 2000; + int64_t configId = 1000; + ConfigKey cfgKey(configUid, configId); + auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + EXPECT_EQ(processor->mMetricsManagers.size(), 1u); + EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); + EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size()); + + sp anomalyTracker = + processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0]; + + std::vector attributionUids1 = {111}; + std::vector attributionTags1 = {"App1"}; + std::vector attributionUids2 = {111, 222}; + std::vector attributionTags2 = {"App1", "GMSCoreModule1"}; + + FieldValue fieldValue1(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101), + Value((int32_t)111)); + HashableDimensionKey whatKey1({fieldValue1}); + MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY); + + auto event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2, attributionUids1, + attributionTags1, "wl1"); + processor->OnLogEvent(event.get()); + EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 2) / NS_PER_SEC + 1, + anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1)); + + int64_t mockWallClockNs = 1584991200 * NS_PER_SEC; + int64_t mockElapsedTimeNs = bucketStartTimeNs + 5000 * NS_PER_SEC; + processor->SaveMetadataToDisk(mockWallClockNs, mockElapsedTimeNs); + + auto processor2 = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); + int64_t mockElapsedTimeSinceBoot = 10 * NS_PER_SEC; + processor2->LoadMetadataFromDisk(mockWallClockNs, mockElapsedTimeSinceBoot); + + sp anomalyTracker2 = + processor2->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0]; + EXPECT_EQ(anomalyTracker2->getRefractoryPeriodEndsSec(dimensionKey1) - + mockElapsedTimeSinceBoot / NS_PER_SEC, + anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1) - + mockElapsedTimeNs / NS_PER_SEC); +} + #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif diff --git a/cmds/statsd/tests/metadata_util_test.cpp b/cmds/statsd/tests/metadata_util_test.cpp new file mode 100644 index 0000000000000..7707890cbd0cc --- /dev/null +++ b/cmds/statsd/tests/metadata_util_test.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "metadata_util.h" +#include "tests/statsd_test_util.h" + +#ifdef __ANDROID__ + +namespace android { +namespace os { +namespace statsd { + +TEST(MetadataUtilTest, TestWriteAndReadMetricDimensionKey) { + HashableDimensionKey dim; + HashableDimensionKey dim2; + int pos1[] = {1, 1, 1}; + int pos2[] = {1, 1, 2}; + int pos3[] = {1, 1, 3}; + int pos4[] = {2, 0, 0}; + Field field1(10, pos1, 2); + Field field2(10, pos2, 2); + Field field3(10, pos3, 2); + Field field4(10, pos4, 0); + + Value value1((int32_t)10025); + Value value2("tag"); + Value value3((int32_t)987654); + Value value4((int32_t)99999); + + dim.addValue(FieldValue(field1, value1)); + dim.addValue(FieldValue(field2, value2)); + dim.addValue(FieldValue(field3, value3)); + dim.addValue(FieldValue(field4, value4)); + + dim2.addValue(FieldValue(field1, value1)); + dim2.addValue(FieldValue(field2, value2)); + + MetricDimensionKey dimKey(dim, dim2); + + metadata::MetricDimensionKey metadataDimKey; + writeMetricDimensionKeyToMetadataDimensionKey(dimKey, &metadataDimKey); + + MetricDimensionKey loadedDimKey = loadMetricDimensionKeyFromProto(metadataDimKey); + + ASSERT_EQ(loadedDimKey, dimKey); + ASSERT_EQ(std::hash{}(loadedDimKey), + std::hash{}(dimKey)); +} + +} // namespace statsd +} // namespace os +} // namespace android +#else +GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif