Add more alert details to incidentd header.

+ Add metric_id, dimension, metric_value in the incident report header
  to make it easier to identify an anomaly.
+ In case there is a uid in the dimension, put the its package info in the header too

Test: statsd_test && tested locally with a config

Change-Id: I762a1a4b0563fb3104e0d32b616b4a2367485e48
This commit is contained in:
Yao Chen
2019-02-13 13:06:36 -08:00
parent a99c4f30ee
commit 4ce07298e0
20 changed files with 231 additions and 74 deletions

View File

@@ -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) {

View File

@@ -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);

View File

@@ -160,7 +160,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
}
})) {
mUidMap = new UidMap();
mUidMap = UidMap::getInstance();
mPullerManager = new StatsPullerManager();
StatsPuller::SetUidMap(mUidMap);
mConfigManager = new ConfigManager();

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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.
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -693,8 +693,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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -456,3 +456,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;
}

View File

@@ -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++) {

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;
}