diff options
20 files changed, 231 insertions, 74 deletions
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp index 80ed80776829..13f5c8ae5fd8 100644 --- a/cmds/statsd/src/FieldValue.cpp +++ b/cmds/statsd/src/FieldValue.cpp @@ -19,6 +19,7 @@ #include "FieldValue.h" #include "HashableDimensionKey.h" #include "math.h" +#include "statslog.h" namespace android { namespace os { @@ -122,6 +123,24 @@ bool isAttributionUidField(const FieldValue& value) { return false; } +int32_t getUidIfExists(const FieldValue& value) { + bool isUid = false; + // the field is uid field if the field is the uid field in attribution node or marked as + // is_uid in atoms.proto + if (isAttributionUidField(value)) { + isUid = true; + } else { + auto it = android::util::AtomsInfo::kAtomsWithUidField.find(value.mField.getTag()); + if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) { + int uidField = it->second; // uidField is the field number in proto + isUid = value.mField.getDepth() == 0 && value.mField.getPosAtDepth(0) == uidField && + value.mValue.getType() == INT; + } + } + + return isUid ? value.mValue.int_value : -1; +} + bool isAttributionUidField(const Field& field, const Value& value) { int f = field.getField() & 0xff007f; if (f == 0x10001 && value.getType() == INT) { diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h index a5d00ac4e72b..6729e052b5ee 100644 --- a/cmds/statsd/src/FieldValue.h +++ b/cmds/statsd/src/FieldValue.h @@ -386,6 +386,9 @@ bool HasPositionALL(const FieldMatcher& matcher); bool isAttributionUidField(const FieldValue& value); +/* returns uid if the field is uid field, or -1 if the field is not a uid field */ +int getUidIfExists(const FieldValue& value); + void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output); bool isAttributionUidField(const Field& field, const Value& value); diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index fb603b9ce163..c542b6215c88 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -159,7 +159,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper) } })) { - mUidMap = new UidMap(); + mUidMap = UidMap::getInstance(); mPullerManager = new StatsPullerManager(); StatsPuller::SetUidMap(mUidMap); mConfigManager = new ConfigManager(); diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp index 8d7369935ea4..019a9f7e5f9a 100644 --- a/cmds/statsd/src/anomaly/AlarmTracker.cpp +++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp @@ -78,8 +78,8 @@ void AlarmTracker::informAlarmsFired( } if (!mSubscriptions.empty()) { VLOG("AlarmTracker triggers the subscribers."); - triggerSubscribers(mAlarmConfig.id(), DEFAULT_METRIC_DIMENSION_KEY, mConfigKey, - mSubscriptions); + triggerSubscribers(mAlarmConfig.id(), 0 /*metricId N/A*/, DEFAULT_METRIC_DIMENSION_KEY, + 0 /* metricValue N/A */, mConfigKey, mSubscriptions); } firedAlarms.erase(mInternalAlarm); mAlarmSec = findNextAlarmSec((timestampNs-1) / NS_PER_SEC + 1); // round up diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index ee111cddcfd7..d1dcb5df7838 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -207,7 +207,8 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); } -void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key) { +void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, int64_t metricId, + const MetricDimensionKey& key, int64_t metricValue) { // TODO(b/110563466): Why receive timestamp? RefractoryPeriod should always be based on // real time right now. if (isInRefractoryPeriod(timestampNs, key)) { @@ -225,7 +226,7 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDime if (!mSubscriptions.empty()) { ALOGI("An anomaly (%lld) %s has occurred! Informing subscribers.", mAlert.id(), key.toString().c_str()); - informSubscribers(key); + informSubscribers(key, metricId, metricValue); } else { ALOGI("An anomaly has occurred! (But no subscriber for that alert.)"); } @@ -238,11 +239,11 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDime } void AnomalyTracker::detectAndDeclareAnomaly(const int64_t& timestampNs, - const int64_t& currBucketNum, + const int64_t& currBucketNum, int64_t metricId, const MetricDimensionKey& key, const int64_t& currentBucketValue) { if (detectAnomaly(currBucketNum, key, currentBucketValue)) { - declareAnomaly(timestampNs, key); + declareAnomaly(timestampNs, metricId, key, currentBucketValue); } } @@ -255,8 +256,9 @@ bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs, return false; } -void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) { - triggerSubscribers(mAlert.id(), key, mConfigKey, mSubscriptions); +void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t metric_id, + int64_t metricValue) { + triggerSubscribers(mAlert.id(), metric_id, key, metricValue, mConfigKey, mSubscriptions); } } // namespace statsd diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h index 927e2df1b53a..e9414735b82b 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.h +++ b/cmds/statsd/src/anomaly/AnomalyTracker.h @@ -67,14 +67,16 @@ public: const int64_t& currentBucketValue); // Informs incidentd about the detected alert. - void declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key); + void declareAnomaly(const int64_t& timestampNs, int64_t metricId, const MetricDimensionKey& key, + int64_t metricValue); // Detects if, based on past buckets plus the new currentBucketValue (which generally // represents the partially-filled current bucket), an anomaly has happened, and if so, // declares an anomaly and informs relevant subscribers. // Also advances to currBucketNum-1. void detectAndDeclareAnomaly(const int64_t& timestampNs, const int64_t& currBucketNum, - const MetricDimensionKey& key, const int64_t& currentBucketValue); + int64_t metricId, const MetricDimensionKey& key, + const int64_t& currentBucketValue); // Init the AlarmMonitor which is shared across anomaly trackers. virtual void setAlarmMonitor(const sp<AlarmMonitor>& alarmMonitor) { @@ -176,7 +178,7 @@ protected: virtual void resetStorage(); // Informs the subscribers (incidentd, perfetto, broadcasts, etc) that an anomaly has occurred. - void informSubscribers(const MetricDimensionKey& key); + void informSubscribers(const MetricDimensionKey& key, int64_t metricId, int64_t metricValue); FRIEND_TEST(AnomalyTrackerTest, TestConsecutiveBuckets); FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets); diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp index 3acfd171848e..2b56810170e5 100644 --- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp @@ -65,7 +65,9 @@ void DurationAnomalyTracker::stopAlarm(const MetricDimensionKey& dimensionKey, // If the alarm is set in the past but hasn't fired yet (due to lag), catch it now. if (itr->second != nullptr && timestampNs >= (int64_t)NS_PER_SEC * itr->second->timestampSec) { - declareAnomaly(timestampNs, dimensionKey); + declareAnomaly(timestampNs, mAlert.metric_id(), dimensionKey, + mAlert.trigger_if_sum_gt() + (timestampNs / NS_PER_SEC) - + itr->second->timestampSec); } if (mAlarmMonitor != nullptr) { mAlarmMonitor->remove(itr->second); @@ -100,7 +102,9 @@ void DurationAnomalyTracker::informAlarmsFired(const int64_t& timestampNs, // Now declare each of these alarms to have fired. for (const auto& kv : matchedAlarms) { - declareAnomaly(timestampNs, kv.first); + declareAnomaly( + timestampNs, mAlert.metric_id(), kv.first, + mAlert.trigger_if_sum_gt() + (timestampNs / NS_PER_SEC) - kv.second->timestampSec); mAlarms.erase(kv.first); firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it. } diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp index 6b46b8b3b900..548a6869436d 100644 --- a/cmds/statsd/src/anomaly/subscriber_util.cpp +++ b/cmds/statsd/src/anomaly/subscriber_util.cpp @@ -30,9 +30,8 @@ namespace android { namespace os { namespace statsd { -void triggerSubscribers(const int64_t rule_id, - const MetricDimensionKey& dimensionKey, - const ConfigKey& configKey, +void triggerSubscribers(int64_t ruleId, int64_t metricId, const MetricDimensionKey& dimensionKey, + int64_t metricValue, const ConfigKey& configKey, const std::vector<Subscription>& subscriptions) { VLOG("informSubscribers called."); if (subscriptions.empty()) { @@ -50,13 +49,14 @@ void triggerSubscribers(const int64_t rule_id, } switch (subscription.subscriber_information_case()) { case Subscription::SubscriberInformationCase::kIncidentdDetails: - if (!GenerateIncidentReport(subscription.incidentd_details(), rule_id, configKey)) { + if (!GenerateIncidentReport(subscription.incidentd_details(), ruleId, metricId, + dimensionKey, metricValue, configKey)) { ALOGW("Failed to generate incident report."); } break; case Subscription::SubscriberInformationCase::kPerfettoDetails: if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details(), - subscription.id(), rule_id, configKey)) { + subscription.id(), ruleId, configKey)) { ALOGW("Failed to generate perfetto traces."); } break; @@ -66,7 +66,7 @@ void triggerSubscribers(const int64_t rule_id, break; case Subscription::SubscriberInformationCase::kPerfprofdDetails: if (!CollectPerfprofdTraceAndUploadToDropbox(subscription.perfprofd_details(), - rule_id, configKey)) { + ruleId, configKey)) { ALOGW("Failed to generate perfprofd traces."); } break; @@ -76,7 +76,6 @@ void triggerSubscribers(const int64_t rule_id, } } - } // namespace statsd } // namespace os } // namespace android diff --git a/cmds/statsd/src/anomaly/subscriber_util.h b/cmds/statsd/src/anomaly/subscriber_util.h index dba8981a72aa..1df3c8991f94 100644 --- a/cmds/statsd/src/anomaly/subscriber_util.h +++ b/cmds/statsd/src/anomaly/subscriber_util.h @@ -24,10 +24,9 @@ namespace android { namespace os { namespace statsd { -void triggerSubscribers(const int64_t rule_id, - const MetricDimensionKey& dimensionKey, - const ConfigKey& configKey, - const std::vector<Subscription>& subscriptions); +void triggerSubscribers(const int64_t ruleId, const int64_t metricId, + const MetricDimensionKey& dimensionKey, int64_t metricValue, + const ConfigKey& configKey, const std::vector<Subscription>& subscriptions); } // namespace statsd } // namespace os diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp index 5707de544648..e84f88d407d3 100644 --- a/cmds/statsd/src/metrics/CountMetricProducer.cpp +++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp @@ -303,7 +303,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked( if (prev != mCurrentFullCounters->end()) { countWholeBucket += prev->second; } - tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey, + tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, eventKey, countWholeBucket); } diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 837d532f7e09..63017936b1db 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -485,8 +485,8 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked( gaugeVal = value.long_value; } for (auto& tracker : mAnomalyTrackers) { - tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey, - gaugeVal); + tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, + eventKey, gaugeVal); } } } diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index bc7c8727284f..3cf378d7d7ce 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -697,8 +697,8 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn wholeBucketVal += prev->second; } for (auto& tracker : mAnomalyTrackers) { - tracker->detectAndDeclareAnomaly( - eventTimeNs, mCurrentBucketNum, eventKey, wholeBucketVal); + tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, eventKey, + wholeBucketVal); } } } diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h index ccb1d4359e89..081e61ed21fa 100644 --- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h +++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h @@ -155,8 +155,8 @@ protected: const int64_t& currentBucketValue) { for (auto& anomalyTracker : mAnomalyTrackers) { if (anomalyTracker != nullptr) { - anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mEventKey, - currentBucketValue); + anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mTrackerId, + mEventKey, currentBucketValue); } } } diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp index 5cf012638dce..d4b57dd68134 100644 --- a/cmds/statsd/src/packages/UidMap.cpp +++ b/cmds/statsd/src/packages/UidMap.cpp @@ -73,6 +73,11 @@ UidMap::UidMap() : mBytesUsed(0) {} UidMap::~UidMap() {} +sp<UidMap> UidMap::getInstance() { + static sp<UidMap> sInstance = new UidMap(); + return sInstance; +} + bool UidMap::hasApp(int uid, const string& packageName) const { lock_guard<mutex> lock(mMutex); @@ -336,6 +341,61 @@ size_t UidMap::getBytesUsed() const { return mBytesUsed; } +void UidMap::writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings, + bool includeInstaller, const std::set<int32_t>& interestingUids, + std::set<string>* str_set, ProtoOutputStream* proto) { + lock_guard<mutex> lock(mMutex); + + writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller, interestingUids, + str_set, proto); +} + +void UidMap::writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings, + bool includeInstaller, + const std::set<int32_t>& interestingUids, + std::set<string>* str_set, ProtoOutputStream* proto) { + proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp); + for (const auto& kv : mMap) { + if (!interestingUids.empty() && + interestingUids.find(kv.first.first) == interestingUids.end()) { + continue; + } + uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | + FIELD_ID_SNAPSHOT_PACKAGE_INFO); + if (str_set != nullptr) { + str_set->insert(kv.first.second); + proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH, + (long long)Hash64(kv.first.second)); + if (includeVersionStrings) { + str_set->insert(kv.second.versionString); + proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH, + (long long)Hash64(kv.second.versionString)); + } + if (includeInstaller) { + str_set->insert(kv.second.installer); + proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH, + (long long)Hash64(kv.second.installer)); + } + } else { + proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second); + if (includeVersionStrings) { + proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING, + kv.second.versionString); + } + if (includeInstaller) { + proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER, + kv.second.installer); + } + } + + proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION, + (long long)kv.second.versionCode); + proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first); + proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted); + proto->end(token); + } +} + void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set, bool includeVersionStrings, bool includeInstaller, ProtoOutputStream* proto) { @@ -381,43 +441,9 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::s // Write snapshot from current uid map state. uint64_t snapshotsToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS); - proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp); - for (const auto& kv : mMap) { - uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | - FIELD_ID_SNAPSHOT_PACKAGE_INFO); - - if (str_set != nullptr) { - str_set->insert(kv.first.second); - proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH, - (long long)Hash64(kv.first.second)); - if (includeVersionStrings) { - str_set->insert(kv.second.versionString); - proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH, - (long long)Hash64(kv.second.versionString)); - } - if (includeInstaller) { - str_set->insert(kv.second.installer); - proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH, - (long long)Hash64(kv.second.installer)); - } - } else { - proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second); - if (includeVersionStrings) { - proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING, - kv.second.versionString); - } - if (includeInstaller) { - proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER, - kv.second.installer); - } - } - - proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION, - (long long)kv.second.versionCode); - proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first); - proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted); - proto->end(token); - } + writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller, + std::set<int32_t>() /*empty uid set means including every uid*/, + str_set, proto); proto->end(snapshotsToken); int64_t prevMin = getMinimumTimestampNs(); diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h index 75ff507ef09a..a7c5fb27375c 100644 --- a/cmds/statsd/src/packages/UidMap.h +++ b/cmds/statsd/src/packages/UidMap.h @@ -91,6 +91,8 @@ public: UidMap(); ~UidMap(); static const std::map<std::string, uint32_t> sAidToUidMapping; + + static sp<UidMap> getInstance(); /* * All three inputs must be the same size, and the jth element in each array refers to the same * tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j]. @@ -152,12 +154,25 @@ public: std::set<int32_t> getAppUid(const string& package) const; + // Write current PackageInfoSnapshot to ProtoOutputStream. + // interestingUids: If not empty, only write the package info for these uids. If empty, write + // package info for all uids. + // str_set: if not null, add new string to the set and write str_hash to proto + // if null, write string to proto. + void writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings, bool includeInstaller, + const std::set<int32_t>& interestingUids, std::set<string>* str_set, + ProtoOutputStream* proto); + private: std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const; string normalizeAppName(const string& appName) const; void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output); + void writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings, + bool includeInstaller, const std::set<int32_t>& interestingUids, + std::set<string>* str_set, ProtoOutputStream* proto); + mutable mutex mMutex; mutable mutex mIsolatedMutex; diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto index 09b8fed60dcc..623d8bc06e38 100644 --- a/cmds/statsd/src/stats_log.proto +++ b/cmds/statsd/src/stats_log.proto @@ -457,3 +457,17 @@ message StatsdStatsReport { } repeated LogLossStats detected_log_loss = 16; } + +message AlertTriggerDetails { + message MetricValue { + optional int64 metric_id = 1; + optional DimensionsValue dimension_in_what = 2; + optional DimensionsValue dimension_in_condition = 3; + optional int64 value = 4; + } + oneof value { + MetricValue trigger_metric = 1; + EventMetricData trigger_event = 2; + } + optional UidMapping.PackageInfoSnapshot package_info = 3; +} diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp index 42cac0cc4122..0ed2d75802da 100644 --- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp +++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp @@ -16,7 +16,10 @@ #define DEBUG false #include "Log.h" +#include "FieldValue.h" #include "IncidentdReporter.h" +#include "packages/UidMap.h" +#include "stats_log_util.h" #include <android/os/IIncidentManager.h> #include <android/os/IncidentReportArgs.h> @@ -43,8 +46,18 @@ const int FIELD_ID_CONFIG_KEY = 3; const int FIELD_ID_CONFIG_KEY_UID = 1; const int FIELD_ID_CONFIG_KEY_ID = 2; +const int FIELD_ID_TRIGGER_DETAILS = 4; +const int FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC = 1; +const int FIELD_ID_METRIC_VALUE_METRIC_ID = 1; +const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT = 2; +const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION = 3; +const int FIELD_ID_METRIC_VALUE_VALUE = 4; + +const int FIELD_ID_PACKAGE_INFO = 3; + namespace { -void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uint8_t>* protoData) { +void getProtoData(const int64_t& rule_id, int64_t metricId, const MetricDimensionKey& dimensionKey, + int64_t metricValue, const ConfigKey& configKey, vector<uint8_t>* protoData) { ProtoOutputStream headerProto; headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id); uint64_t token = @@ -53,6 +66,58 @@ void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uin headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_KEY_ID, (long long)configKey.GetId()); headerProto.end(token); + token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS); + + // MetricValue trigger_metric = 1; + uint64_t metricToken = + headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC); + // message MetricValue { + // optional int64 metric_id = 1; + headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_METRIC_ID, (long long)metricId); + // optional DimensionsValue dimension_in_what = 2; + uint64_t dimToken = + headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT); + writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), nullptr, &headerProto); + headerProto.end(dimToken); + + // optional DimensionsValue dimension_in_condition = 3; + dimToken = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION); + writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), nullptr, &headerProto); + headerProto.end(dimToken); + + // optional int64 value = 4; + headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_VALUE, (long long)metricValue); + + // } + headerProto.end(metricToken); + + // write relevant uid package info + std::set<int32_t> uids; + + for (const auto& dim : dimensionKey.getDimensionKeyInWhat().getValues()) { + int uid = getUidIfExists(dim); + // any uid <= 2000 are predefined AID_* + if (uid > 2000) { + uids.insert(uid); + } + } + + for (const auto& dim : dimensionKey.getDimensionKeyInCondition().getValues()) { + int uid = getUidIfExists(dim); + if (uid > 2000) { + uids.insert(uid); + } + } + + if (!uids.empty()) { + uint64_t token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PACKAGE_INFO); + UidMap::getInstance()->writeUidMapSnapshot(getElapsedRealtimeNs(), true, true, uids, + nullptr /*string set*/, &headerProto); + headerProto.end(token); + } + + headerProto.end(token); + protoData->resize(headerProto.size()); size_t pos = 0; auto iter = headerProto.data(); @@ -65,7 +130,8 @@ void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uin } } // namespace -bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id, +bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId, + const MetricDimensionKey& dimensionKey, int64_t metricValue, const ConfigKey& configKey) { if (config.section_size() == 0) { VLOG("The alert %lld contains zero section in config(%d,%lld)", (unsigned long long)rule_id, @@ -76,7 +142,7 @@ bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_ IncidentReportArgs incidentReport; vector<uint8_t> protoData; - getProtoData(rule_id, configKey, &protoData); + getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey, &protoData); incidentReport.addHeader(protoData); for (int i = 0; i < config.section_size(); i++) { diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.h b/cmds/statsd/src/subscriber/IncidentdReporter.h index 1b83fe23de8f..e78a4d98dcd8 100644 --- a/cmds/statsd/src/subscriber/IncidentdReporter.h +++ b/cmds/statsd/src/subscriber/IncidentdReporter.h @@ -16,6 +16,7 @@ #pragma once +#include "HashableDimensionKey.h" #include "config/ConfigKey.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert, IncidentdDetails @@ -26,7 +27,8 @@ namespace statsd { /** * Calls incidentd to trigger an incident report and put in dropbox for uploading. */ -bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id, +bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId, + const MetricDimensionKey& dimensionKey, int64_t metricValue, const ConfigKey& configKey); } // namespace statsd diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp index 960fbdab1c15..c10703c36b98 100644 --- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp +++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp @@ -90,7 +90,8 @@ void detectAndDeclareAnomalies(AnomalyTracker& tracker, const std::shared_ptr<DimToValMap>& bucket, const int64_t& eventTimestamp) { for (const auto& kv : *bucket) { - tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, kv.first, kv.second); + tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, 0 /*metric_id*/, kv.first, + kv.second); } } diff --git a/libs/incident/proto/android/os/header.proto b/libs/incident/proto/android/os/header.proto index a84dc48b8b34..d463f87055b3 100644 --- a/libs/incident/proto/android/os/header.proto +++ b/libs/incident/proto/android/os/header.proto @@ -37,4 +37,9 @@ message IncidentHeaderProto { optional int64 id = 2; // The unique id of the statsd config. } optional StatsdConfigKey config_key = 3; + + // Details about the trigger. com.android.os.AlertTriggerDetails + // Only use bytes type here to avoid indirect dependency on atoms.proto + // And this header passes through incidentd without incidentd parsing it. + optional bytes trigger_details = 4; } |