Merge "Further reduce statsd memory usage."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0630ad6d15
@@ -317,7 +317,7 @@ void AnomalyTracker::informAlarmsFired(const uint64_t& timestampNs,
|
||||
for (const auto& kv : matchedAlarms) {
|
||||
declareAnomaly(timestampNs /* TODO: , kv.first */);
|
||||
mAlarms.erase(kv.first);
|
||||
firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
|
||||
firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,12 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
#define STATS_SERVICE_DIR "/data/misc/stats-service"
|
||||
|
||||
using android::base::StringPrintf;
|
||||
@@ -41,8 +47,14 @@ ConfigManager::~ConfigManager() {
|
||||
}
|
||||
|
||||
void ConfigManager::Startup() {
|
||||
StorageManager::readConfigFromDisk(mConfigs);
|
||||
|
||||
map<ConfigKey, StatsdConfig> configsFromDisk;
|
||||
StorageManager::readConfigFromDisk(configsFromDisk);
|
||||
// TODO(b/70667694): Make the configs from disk be used. And remove the fake config,
|
||||
// and tests shouldn't call this Startup(), maybe call StartupForTest() so we don't read
|
||||
// configs from disk for tests.
|
||||
// for (const auto& pair : configsFromDisk) {
|
||||
// UpdateConfig(pair.first, pair.second);
|
||||
//}
|
||||
// this should be called from StatsService when it receives a statsd_config
|
||||
UpdateConfig(ConfigKey(1000, "fake"), build_fake_config());
|
||||
}
|
||||
@@ -52,9 +64,8 @@ void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
|
||||
}
|
||||
|
||||
void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
|
||||
// Add to map
|
||||
mConfigs[key] = config;
|
||||
// Why doesn't this work? mConfigs.insert({key, config});
|
||||
// Add to set
|
||||
mConfigs.insert(key);
|
||||
|
||||
// Save to disk
|
||||
update_saved_configs(key, config);
|
||||
@@ -74,7 +85,7 @@ void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
|
||||
}
|
||||
|
||||
void ConfigManager::RemoveConfig(const ConfigKey& key) {
|
||||
unordered_map<ConfigKey, StatsdConfig>::iterator it = mConfigs.find(key);
|
||||
auto it = mConfigs.find(key);
|
||||
if (it != mConfigs.end()) {
|
||||
// Remove from map
|
||||
mConfigs.erase(it);
|
||||
@@ -100,9 +111,9 @@ void ConfigManager::RemoveConfigs(int uid) {
|
||||
|
||||
for (auto it = mConfigs.begin(); it != mConfigs.end();) {
|
||||
// Remove from map
|
||||
if (it->first.GetUid() == uid) {
|
||||
removed.push_back(it->first);
|
||||
mConfigReceivers.erase(it->first);
|
||||
if (it->GetUid() == uid) {
|
||||
removed.push_back(*it);
|
||||
mConfigReceivers.erase(*it);
|
||||
it = mConfigs.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
@@ -123,10 +134,10 @@ void ConfigManager::RemoveAllConfigs() {
|
||||
|
||||
for (auto it = mConfigs.begin(); it != mConfigs.end();) {
|
||||
// Remove from map
|
||||
removed.push_back(it->first);
|
||||
auto receiverIt = mConfigReceivers.find(it->first);
|
||||
removed.push_back(*it);
|
||||
auto receiverIt = mConfigReceivers.find(*it);
|
||||
if (receiverIt != mConfigReceivers.end()) {
|
||||
mConfigReceivers.erase(it->first);
|
||||
mConfigReceivers.erase(*it);
|
||||
}
|
||||
it = mConfigs.erase(it);
|
||||
}
|
||||
@@ -143,7 +154,7 @@ void ConfigManager::RemoveAllConfigs() {
|
||||
vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
|
||||
vector<ConfigKey> ret;
|
||||
for (auto it = mConfigs.cbegin(); it != mConfigs.cend(); ++it) {
|
||||
ret.push_back(it->first);
|
||||
ret.push_back(*it);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -160,15 +171,13 @@ const pair<string, string> ConfigManager::GetConfigReceiver(const ConfigKey& key
|
||||
void ConfigManager::Dump(FILE* out) {
|
||||
fprintf(out, "CONFIGURATIONS (%d)\n", (int)mConfigs.size());
|
||||
fprintf(out, " uid name\n");
|
||||
for (unordered_map<ConfigKey, StatsdConfig>::const_iterator it = mConfigs.begin();
|
||||
it != mConfigs.end(); it++) {
|
||||
fprintf(out, " %6d %s\n", it->first.GetUid(), it->first.GetName().c_str());
|
||||
auto receiverIt = mConfigReceivers.find(it->first);
|
||||
for (const auto& key : mConfigs) {
|
||||
fprintf(out, " %6d %s\n", key.GetUid(), key.GetName().c_str());
|
||||
auto receiverIt = mConfigReceivers.find(key);
|
||||
if (receiverIt != mConfigReceivers.end()) {
|
||||
fprintf(out, " -> received by %s, %s\n", receiverIt->second.first.c_str(),
|
||||
receiverIt->second.second.c_str());
|
||||
}
|
||||
// TODO: Print the contents of the config too.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +236,8 @@ StatsdConfig build_fake_config() {
|
||||
metric->mutable_bucket()->set_bucket_size_millis(30 * 1000L);
|
||||
|
||||
// Anomaly threshold for screen-on count.
|
||||
Alert* alert = config.add_alert();
|
||||
// TODO(b/70627390): Uncomment once the bug is fixed.
|
||||
/*Alert* alert = config.add_alert();
|
||||
alert->set_name("ALERT_1");
|
||||
alert->set_metric_name("METRIC_1");
|
||||
alert->set_number_of_buckets(6);
|
||||
@@ -235,7 +245,7 @@ StatsdConfig build_fake_config() {
|
||||
alert->set_refractory_period_secs(30);
|
||||
Alert::IncidentdDetails* details = alert->mutable_incidentd_details();
|
||||
details->add_section(12);
|
||||
details->add_section(13);
|
||||
details->add_section(13);*/
|
||||
|
||||
// Count process state changes, slice by uid.
|
||||
metric = config.add_count_metric();
|
||||
@@ -246,6 +256,8 @@ StatsdConfig build_fake_config() {
|
||||
keyMatcher->set_key(UID_PROCESS_STATE_UID_KEY);
|
||||
|
||||
// Anomaly threshold for background count.
|
||||
// TODO(b/70627390): Uncomment once the bug is fixed.
|
||||
/*
|
||||
alert = config.add_alert();
|
||||
alert->set_name("ALERT_2");
|
||||
alert->set_metric_name("METRIC_2");
|
||||
@@ -254,7 +266,7 @@ StatsdConfig build_fake_config() {
|
||||
alert->set_refractory_period_secs(20);
|
||||
details = alert->mutable_incidentd_details();
|
||||
details->add_section(14);
|
||||
details->add_section(15);
|
||||
details->add_section(15);*/
|
||||
|
||||
// Count process state changes, slice by uid, while SCREEN_IS_OFF
|
||||
metric = config.add_count_metric();
|
||||
@@ -326,6 +338,8 @@ StatsdConfig build_fake_config() {
|
||||
durationMetric->set_what("SCREEN_IS_ON");
|
||||
|
||||
// Anomaly threshold for background count.
|
||||
// TODO(b/70627390): Uncomment once the bug is fixed.
|
||||
/*
|
||||
alert = config.add_alert();
|
||||
alert->set_name("ALERT_8");
|
||||
alert->set_metric_name("METRIC_8");
|
||||
@@ -333,7 +347,7 @@ StatsdConfig build_fake_config() {
|
||||
alert->set_trigger_if_sum_gt(2000000000); // 2 seconds
|
||||
alert->set_refractory_period_secs(120);
|
||||
details = alert->mutable_incidentd_details();
|
||||
details->add_section(-1);
|
||||
details->add_section(-1);*/
|
||||
|
||||
// Value metric to count KERNEL_WAKELOCK when screen turned on
|
||||
ValueMetric* valueMetric = config.add_value_metric();
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#include "config/ConfigKey.h"
|
||||
#include "config/ConfigListener.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -28,13 +29,7 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
using android::RefBase;
|
||||
using std::string;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
// Util function to Hard code a test metric for counting screen on events.
|
||||
// Util function to build a hard coded config with test metrics.
|
||||
StatsdConfig build_fake_config();
|
||||
|
||||
/**
|
||||
@@ -43,7 +38,7 @@ StatsdConfig build_fake_config();
|
||||
* TODO: Store the configs persistently too.
|
||||
* TODO: Dump method for debugging.
|
||||
*/
|
||||
class ConfigManager : public virtual RefBase {
|
||||
class ConfigManager : public virtual android::RefBase {
|
||||
public:
|
||||
ConfigManager();
|
||||
virtual ~ConfigManager();
|
||||
@@ -68,17 +63,17 @@ public:
|
||||
/**
|
||||
* Sets the broadcast receiver for a configuration key.
|
||||
*/
|
||||
void SetConfigReceiver(const ConfigKey& key, const string& pkg, const string& cls);
|
||||
void SetConfigReceiver(const ConfigKey& key, const std::string& pkg, const std::string& cls);
|
||||
|
||||
/**
|
||||
* Returns the package name and class name representing the broadcast receiver for this config.
|
||||
*/
|
||||
const pair<string, string> GetConfigReceiver(const ConfigKey& key) const;
|
||||
const std::pair<std::string, std::string> GetConfigReceiver(const ConfigKey& key) const;
|
||||
|
||||
/**
|
||||
* Returns all config keys registered.
|
||||
*/
|
||||
vector<ConfigKey> GetAllConfigKeys() const;
|
||||
std::vector<ConfigKey> GetAllConfigKeys() const;
|
||||
|
||||
/**
|
||||
* Erase any broadcast receiver associated with this config key.
|
||||
@@ -121,18 +116,18 @@ private:
|
||||
/**
|
||||
* The Configs that have been set. Each config should
|
||||
*/
|
||||
unordered_map<ConfigKey, StatsdConfig> mConfigs;
|
||||
std::set<ConfigKey> mConfigs;
|
||||
|
||||
/**
|
||||
* Each config key can be subscribed by up to one receiver, specified as the package name and
|
||||
* class name.
|
||||
*/
|
||||
unordered_map<ConfigKey, pair<string, string>> mConfigReceivers;
|
||||
std::map<ConfigKey, std::pair<std::string, std::string>> mConfigReceivers;
|
||||
|
||||
/**
|
||||
* The ConfigListeners that will be told about changes.
|
||||
*/
|
||||
vector<sp<ConfigListener>> mListeners;
|
||||
std::vector<sp<ConfigListener>> mListeners;
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
@@ -66,7 +66,7 @@ CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(key, startTimeNs, conditionIndex, wizard), mMetric(metric) {
|
||||
: MetricProducer(metric.name(), key, startTimeNs, conditionIndex, wizard) {
|
||||
// TODO: evaluate initial conditions. and set mConditionMet.
|
||||
if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
|
||||
mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
@@ -92,18 +92,18 @@ CountMetricProducer::~CountMetricProducer() {
|
||||
}
|
||||
|
||||
void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mMetric.name().c_str());
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mName.c_str());
|
||||
}
|
||||
|
||||
void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mMetric.name());
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mName);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
|
||||
long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_COUNT_METRICS);
|
||||
|
||||
VLOG("metric %s dump report now...", mMetric.name().c_str());
|
||||
VLOG("metric %s dump report now...", mName.c_str());
|
||||
|
||||
for (const auto& counter : mPastBuckets) {
|
||||
const HashableDimensionKey& hashableKey = counter.first;
|
||||
@@ -160,7 +160,7 @@ void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
|
||||
void CountMetricProducer::onConditionChangedLocked(const bool conditionMet,
|
||||
const uint64_t eventTime) {
|
||||
VLOG("Metric %s onConditionChanged", mMetric.name().c_str());
|
||||
VLOG("Metric %s onConditionChanged", mName.c_str());
|
||||
mCondition = conditionMet;
|
||||
}
|
||||
|
||||
@@ -172,11 +172,10 @@ bool CountMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey)
|
||||
// 1. Report the tuple count if the tuple count > soft limit
|
||||
if (mCurrentSlicedCounter->size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
|
||||
size_t newTupleCount = mCurrentSlicedCounter->size() + 1;
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetric.name(),
|
||||
newTupleCount);
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mName, newTupleCount);
|
||||
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
|
||||
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
|
||||
ALOGE("CountMetric %s dropping data for dimension key %s", mMetric.name().c_str(),
|
||||
ALOGE("CountMetric %s dropping data for dimension key %s", mName.c_str(),
|
||||
newKey.c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -218,7 +217,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked(
|
||||
mCurrentSlicedCounter->find(eventKey)->second);
|
||||
}
|
||||
|
||||
VLOG("metric %s %s->%lld", mMetric.name().c_str(), eventKey.c_str(),
|
||||
VLOG("metric %s %s->%lld", mName.c_str(), eventKey.c_str(),
|
||||
(long long)(*mCurrentSlicedCounter)[eventKey]);
|
||||
}
|
||||
|
||||
@@ -237,7 +236,7 @@ void CountMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
|
||||
info.mCount = counter.second;
|
||||
auto& bucketList = mPastBuckets[counter.first];
|
||||
bucketList.push_back(info);
|
||||
VLOG("metric %s, dump key value: %s -> %lld", mMetric.name().c_str(), counter.first.c_str(),
|
||||
VLOG("metric %s, dump key value: %s -> %lld", mName.c_str(), counter.first.c_str(),
|
||||
(long long)counter.second);
|
||||
}
|
||||
|
||||
@@ -250,7 +249,7 @@ void CountMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
|
||||
uint64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
|
||||
mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
|
||||
mCurrentBucketNum += numBucketsForward;
|
||||
VLOG("metric %s: new bucket start time: %lld", mMetric.name().c_str(),
|
||||
VLOG("metric %s: new bucket start time: %lld", mName.c_str(),
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,8 +76,6 @@ private:
|
||||
// Util function to flush the old packet.
|
||||
void flushIfNeededLocked(const uint64_t& newEventTime);
|
||||
|
||||
const CountMetric mMetric;
|
||||
|
||||
// TODO: Add a lock to mPastBuckets.
|
||||
std::unordered_map<HashableDimensionKey, std::vector<CountBucket>> mPastBuckets;
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const Durat
|
||||
const sp<ConditionWizard>& wizard,
|
||||
const vector<KeyMatcher>& internalDimension,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(key, startTimeNs, conditionIndex, wizard),
|
||||
mMetric(metric),
|
||||
: MetricProducer(metric.name(), key, startTimeNs, conditionIndex, wizard),
|
||||
mAggregationType(metric.aggregation_type()),
|
||||
mStartIndex(startIndex),
|
||||
mStopIndex(stopIndex),
|
||||
mStopAllIndex(stopAllIndex),
|
||||
@@ -114,20 +114,20 @@ sp<AnomalyTracker> DurationMetricProducer::createAnomalyTracker(const Alert &ale
|
||||
|
||||
unique_ptr<DurationTracker> DurationMetricProducer::createDurationTracker(
|
||||
const HashableDimensionKey& eventKey) const {
|
||||
switch (mMetric.aggregation_type()) {
|
||||
switch (mAggregationType) {
|
||||
case DurationMetric_AggregationType_SUM:
|
||||
return make_unique<OringDurationTracker>(
|
||||
mConfigKey, mMetric.name(), eventKey, mWizard, mConditionTrackerIndex, mNested,
|
||||
mConfigKey, mName, eventKey, mWizard, mConditionTrackerIndex, mNested,
|
||||
mCurrentBucketStartTimeNs, mBucketSizeNs, mAnomalyTrackers);
|
||||
case DurationMetric_AggregationType_MAX_SPARSE:
|
||||
return make_unique<MaxDurationTracker>(
|
||||
mConfigKey, mMetric.name(), eventKey, mWizard, mConditionTrackerIndex, mNested,
|
||||
mConfigKey, mName, eventKey, mWizard, mConditionTrackerIndex, mNested,
|
||||
mCurrentBucketStartTimeNs, mBucketSizeNs, mAnomalyTrackers);
|
||||
}
|
||||
}
|
||||
|
||||
void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mMetric.name().c_str());
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mName.c_str());
|
||||
flushIfNeededLocked(eventTime);
|
||||
// Now for each of the on-going event, check if the condition has changed for them.
|
||||
for (auto& pair : mCurrentSlicedDuration) {
|
||||
@@ -137,7 +137,7 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eve
|
||||
|
||||
void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
|
||||
const uint64_t eventTime) {
|
||||
VLOG("Metric %s onConditionChanged", mMetric.name().c_str());
|
||||
VLOG("Metric %s onConditionChanged", mName.c_str());
|
||||
mCondition = conditionMet;
|
||||
flushIfNeededLocked(eventTime);
|
||||
// TODO: need to populate the condition change time from the event which triggers the condition
|
||||
@@ -151,11 +151,11 @@ void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mMetric.name());
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mName);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
|
||||
long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DURATION_METRICS);
|
||||
|
||||
VLOG("metric %s dump report now...", mMetric.name().c_str());
|
||||
VLOG("metric %s dump report now...", mName.c_str());
|
||||
|
||||
for (const auto& pair : mPastBuckets) {
|
||||
const HashableDimensionKey& hashableKey = pair.first;
|
||||
@@ -236,11 +236,10 @@ bool DurationMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newK
|
||||
// 1. Report the tuple count if the tuple count > soft limit
|
||||
if (mCurrentSlicedDuration.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
|
||||
size_t newTupleCount = mCurrentSlicedDuration.size() + 1;
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetric.name(),
|
||||
newTupleCount);
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mName, newTupleCount);
|
||||
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
|
||||
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
|
||||
ALOGE("DurationMetric %s dropping data for dimension key %s", mMetric.name().c_str(),
|
||||
ALOGE("DurationMetric %s dropping data for dimension key %s", mName.c_str(),
|
||||
newKey.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ private:
|
||||
// Util function to flush the old packet.
|
||||
void flushIfNeededLocked(const uint64_t& eventTime);
|
||||
|
||||
const DurationMetric mMetric;
|
||||
const DurationMetric_AggregationType mAggregationType;
|
||||
|
||||
// Index of the SimpleAtomMatcher which defines the start.
|
||||
const size_t mStartIndex;
|
||||
|
||||
@@ -55,7 +55,7 @@ EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard,
|
||||
const uint64_t startTimeNs)
|
||||
: MetricProducer(key, startTimeNs, conditionIndex, wizard), mMetric(metric) {
|
||||
: MetricProducer(metric.name(), key, startTimeNs, conditionIndex, wizard) {
|
||||
if (metric.links().size() > 0) {
|
||||
mConditionLinks.insert(mConditionLinks.begin(), metric.links().begin(),
|
||||
metric.links().end());
|
||||
@@ -98,12 +98,12 @@ std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& pr
|
||||
|
||||
void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mMetric.name());
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mName);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
|
||||
|
||||
size_t bufferSize = mProto->size();
|
||||
VLOG("metric %s dump report now... proto size: %zu ", mMetric.name().c_str(), bufferSize);
|
||||
VLOG("metric %s dump report now... proto size: %zu ", mName.c_str(), bufferSize);
|
||||
std::unique_ptr<std::vector<uint8_t>> buffer = serializeProtoLocked(*mProto);
|
||||
|
||||
protoOutput->write(FIELD_TYPE_MESSAGE | FIELD_ID_EVENT_METRICS,
|
||||
@@ -115,7 +115,7 @@ void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
|
||||
void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
|
||||
const uint64_t eventTime) {
|
||||
VLOG("Metric %s onConditionChanged", mMetric.name().c_str());
|
||||
VLOG("Metric %s onConditionChanged", mName.c_str());
|
||||
mCondition = conditionMet;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,6 @@ private:
|
||||
// Internal function to calculate the current used bytes.
|
||||
size_t byteSizeLocked() const override;
|
||||
|
||||
const EventMetric mMetric;
|
||||
|
||||
// Maps to a EventMetricDataWrapper. Storing atom events in ProtoOutputStream
|
||||
// is more space efficient than storing LogEvent.
|
||||
std::unique_ptr<android::util::ProtoOutputStream> mProto;
|
||||
|
||||
@@ -67,8 +67,8 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric
|
||||
const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const int64_t startTimeNs)
|
||||
: MetricProducer(key, startTimeNs, conditionIndex, wizard),
|
||||
mMetric(metric),
|
||||
: MetricProducer(metric.name(), key, startTimeNs, conditionIndex, wizard),
|
||||
mGaugeField(metric.gauge_field()),
|
||||
mPullTagId(pullTagId) {
|
||||
if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
|
||||
mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
@@ -104,11 +104,11 @@ GaugeMetricProducer::~GaugeMetricProducer() {
|
||||
|
||||
void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
VLOG("gauge metric %s dump report now...", mMetric.name().c_str());
|
||||
VLOG("gauge metric %s dump report now...", mName.c_str());
|
||||
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mMetric.name());
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mName);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
|
||||
long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_GAUGE_METRICS);
|
||||
|
||||
@@ -166,7 +166,7 @@ void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
|
||||
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
|
||||
const uint64_t eventTime) {
|
||||
VLOG("Metric %s onConditionChanged", mMetric.name().c_str());
|
||||
VLOG("Metric %s onConditionChanged", mName.c_str());
|
||||
flushIfNeededLocked(eventTime);
|
||||
mCondition = conditionMet;
|
||||
|
||||
@@ -193,12 +193,12 @@ void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
|
||||
}
|
||||
|
||||
void GaugeMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mMetric.name().c_str());
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mName.c_str());
|
||||
}
|
||||
|
||||
int64_t GaugeMetricProducer::getGauge(const LogEvent& event) {
|
||||
status_t err = NO_ERROR;
|
||||
int64_t val = event.GetLong(mMetric.gauge_field(), &err);
|
||||
int64_t val = event.GetLong(mGaugeField, &err);
|
||||
if (err == NO_ERROR) {
|
||||
return val;
|
||||
} else {
|
||||
@@ -222,11 +222,10 @@ bool GaugeMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey)
|
||||
// 1. Report the tuple count if the tuple count > soft limit
|
||||
if (mCurrentSlicedBucket->size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
|
||||
size_t newTupleCount = mCurrentSlicedBucket->size() + 1;
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetric.name(),
|
||||
newTupleCount);
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mName, newTupleCount);
|
||||
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
|
||||
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
|
||||
ALOGE("GaugeMetric %s dropping data for dimension key %s", mMetric.name().c_str(),
|
||||
ALOGE("GaugeMetric %s dropping data for dimension key %s", mName.c_str(),
|
||||
newKey.c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -289,8 +288,8 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
|
||||
info.mGauge = slice.second;
|
||||
auto& bucketList = mPastBuckets[slice.first];
|
||||
bucketList.push_back(info);
|
||||
VLOG("gauge metric %s, dump key value: %s -> %lld", mMetric.name().c_str(),
|
||||
slice.first.c_str(), (long long)slice.second);
|
||||
VLOG("gauge metric %s, dump key value: %s -> %lld", mName.c_str(), slice.first.c_str(),
|
||||
(long long)slice.second);
|
||||
}
|
||||
|
||||
// Reset counters
|
||||
@@ -304,7 +303,7 @@ void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
|
||||
int64_t numBucketsForward = (eventTimeNs - mCurrentBucketStartTimeNs) / mBucketSizeNs;
|
||||
mCurrentBucketStartTimeNs = mCurrentBucketStartTimeNs + numBucketsForward * mBucketSizeNs;
|
||||
mCurrentBucketNum += numBucketsForward;
|
||||
VLOG("metric %s: new bucket start time: %lld", mMetric.name().c_str(),
|
||||
VLOG("metric %s: new bucket start time: %lld", mName.c_str(),
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
// The default bucket size for gauge metric is 1 second.
|
||||
static const uint64_t kDefaultGaugemBucketSizeNs = 1000 * 1000 * 1000;
|
||||
|
||||
const GaugeMetric mMetric;
|
||||
const int32_t mGaugeField;
|
||||
|
||||
StatsPullerManager mStatsPullerManager;
|
||||
// tagId for pulled data. -1 if this is not pulled
|
||||
|
||||
@@ -38,9 +38,10 @@ namespace statsd {
|
||||
// be a no-op.
|
||||
class MetricProducer : public virtual PackageInfoListener {
|
||||
public:
|
||||
MetricProducer(const ConfigKey& key, const int64_t startTimeNs, const int conditionIndex,
|
||||
const sp<ConditionWizard>& wizard)
|
||||
: mConfigKey(key),
|
||||
MetricProducer(const std::string& name, const ConfigKey& key, const int64_t startTimeNs,
|
||||
const int conditionIndex, const sp<ConditionWizard>& wizard)
|
||||
: mName(name),
|
||||
mConfigKey(key),
|
||||
mStartTimeNs(startTimeNs),
|
||||
mCurrentBucketStartTimeNs(startTimeNs),
|
||||
mCurrentBucketNum(0),
|
||||
@@ -108,6 +109,8 @@ protected:
|
||||
android::util::ProtoOutputStream* protoOutput) = 0;
|
||||
virtual size_t byteSizeLocked() const = 0;
|
||||
|
||||
const std::string mName;
|
||||
|
||||
const ConfigKey mConfigKey;
|
||||
|
||||
// The start time for the current in memory metrics data.
|
||||
|
||||
@@ -50,11 +50,6 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config)
|
||||
mAllMetricProducers, mAllAnomalyTrackers, mConditionToMetricMap,
|
||||
mTrackerToMetricMap, mTrackerToConditionMap);
|
||||
|
||||
// TODO: add alert size.
|
||||
// no matter whether this config is valid, log it in the stats.
|
||||
StatsdStats::getInstance().noteConfigReceived(key, mAllMetricProducers.size(),
|
||||
mAllConditionTrackers.size(),
|
||||
mAllAtomMatchers.size(), 0, mConfigValid);
|
||||
// Guardrail. Reject the config if it's too big.
|
||||
if (mAllMetricProducers.size() > StatsdStats::kMaxMetricCountPerConfig ||
|
||||
mAllConditionTrackers.size() > StatsdStats::kMaxConditionCountPerConfig ||
|
||||
@@ -62,6 +57,12 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config)
|
||||
ALOGE("This config is too big! Reject!");
|
||||
mConfigValid = false;
|
||||
}
|
||||
|
||||
// TODO: add alert size.
|
||||
// no matter whether this config is valid, log it in the stats.
|
||||
StatsdStats::getInstance().noteConfigReceived(key, mAllMetricProducers.size(),
|
||||
mAllConditionTrackers.size(),
|
||||
mAllAtomMatchers.size(), 0, mConfigValid);
|
||||
}
|
||||
|
||||
MetricsManager::~MetricsManager() {
|
||||
|
||||
@@ -73,13 +73,13 @@ ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric
|
||||
const sp<ConditionWizard>& wizard, const int pullTagId,
|
||||
const uint64_t startTimeNs,
|
||||
shared_ptr<StatsPullerManager> statsPullerManager)
|
||||
: MetricProducer(key, startTimeNs, conditionIndex, wizard),
|
||||
mMetric(metric),
|
||||
: MetricProducer(metric.name(), key, startTimeNs, conditionIndex, wizard),
|
||||
mValueField(metric.value_field()),
|
||||
mStatsPullerManager(statsPullerManager),
|
||||
mPullTagId(pullTagId) {
|
||||
// TODO: valuemetric for pushed events may need unlimited bucket length
|
||||
if (metric.has_bucket() && metric.bucket().has_bucket_size_millis()) {
|
||||
mBucketSizeNs = mMetric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
mBucketSizeNs = metric.bucket().bucket_size_millis() * 1000 * 1000;
|
||||
} else {
|
||||
mBucketSizeNs = kDefaultBucketSizeMillis * 1000 * 1000;
|
||||
}
|
||||
@@ -118,14 +118,14 @@ ValueMetricProducer::~ValueMetricProducer() {
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mMetric.name().c_str());
|
||||
VLOG("Metric %s onSlicedConditionMayChange", mName.c_str());
|
||||
}
|
||||
|
||||
void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
ProtoOutputStream* protoOutput) {
|
||||
VLOG("metric %s dump report now...", mMetric.name().c_str());
|
||||
VLOG("metric %s dump report now...", mName.c_str());
|
||||
flushIfNeededLocked(dumpTimeNs);
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mMetric.name());
|
||||
protoOutput->write(FIELD_TYPE_STRING | FIELD_ID_NAME, mName);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_START_REPORT_NANOS, (long long)mStartTimeNs);
|
||||
long long protoToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_VALUE_METRICS);
|
||||
|
||||
@@ -175,7 +175,7 @@ void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
|
||||
protoOutput->end(protoToken);
|
||||
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_END_REPORT_NANOS, (long long)dumpTimeNs);
|
||||
|
||||
VLOG("metric %s dump report now...", mMetric.name().c_str());
|
||||
VLOG("metric %s dump report now...", mName.c_str());
|
||||
mPastBuckets.clear();
|
||||
mStartTimeNs = mCurrentBucketStartTimeNs;
|
||||
// TODO: Clear mDimensionKeyMap once the report is dumped.
|
||||
@@ -194,8 +194,7 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition, const u
|
||||
|
||||
if (mPullTagId != -1) {
|
||||
if (mCondition == true) {
|
||||
mStatsPullerManager->RegisterReceiver(mPullTagId, this,
|
||||
mMetric.bucket().bucket_size_millis());
|
||||
mStatsPullerManager->RegisterReceiver(mPullTagId, this, mBucketSizeNs / 1000 / 1000);
|
||||
} else if (mCondition == false) {
|
||||
mStatsPullerManager->UnRegisterReceiver(mPullTagId, this);
|
||||
}
|
||||
@@ -216,7 +215,7 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition, const u
|
||||
void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
if (mCondition == true || !mMetric.has_condition()) {
|
||||
if (mCondition == true || mConditionTrackerIndex < 0) {
|
||||
if (allData.size() == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -247,11 +246,10 @@ bool ValueMetricProducer::hitGuardRailLocked(const HashableDimensionKey& newKey)
|
||||
}
|
||||
if (mCurrentSlicedBucket.size() > StatsdStats::kDimensionKeySizeSoftLimit - 1) {
|
||||
size_t newTupleCount = mCurrentSlicedBucket.size() + 1;
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetric.name(),
|
||||
newTupleCount);
|
||||
StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mName, newTupleCount);
|
||||
// 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
|
||||
if (newTupleCount > StatsdStats::kDimensionKeySizeHardLimit) {
|
||||
ALOGE("ValueMetric %s dropping data for dimension key %s", mMetric.name().c_str(),
|
||||
ALOGE("ValueMetric %s dropping data for dimension key %s", mName.c_str(),
|
||||
newKey.c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -300,7 +298,7 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(
|
||||
|
||||
long ValueMetricProducer::get_value(const LogEvent& event) {
|
||||
status_t err = NO_ERROR;
|
||||
long val = event.GetLong(mMetric.value_field(), &err);
|
||||
long val = event.GetLong(mValueField, &err);
|
||||
if (err == NO_ERROR) {
|
||||
return val;
|
||||
} else {
|
||||
@@ -342,7 +340,7 @@ void ValueMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
|
||||
if (numBucketsForward > 1) {
|
||||
VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
|
||||
}
|
||||
VLOG("metric %s: new bucket start time: %lld", mMetric.name().c_str(),
|
||||
VLOG("metric %s: new bucket start time: %lld", mName.c_str(),
|
||||
(long long)mCurrentBucketStartTimeNs);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
// Util function to flush the old packet.
|
||||
void flushIfNeededLocked(const uint64_t& eventTime);
|
||||
|
||||
const ValueMetric mMetric;
|
||||
const int32_t mValueField;
|
||||
|
||||
std::shared_ptr<StatsPullerManager> mStatsPullerManager;
|
||||
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
#include <android-base/file.h>
|
||||
#include <dirent.h>
|
||||
|
||||
using android::util::FIELD_COUNT_REPEATED;
|
||||
using android::util::FIELD_TYPE_MESSAGE;
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
using android::util::FIELD_COUNT_REPEATED;
|
||||
using android::util::FIELD_TYPE_MESSAGE;
|
||||
using std::map;
|
||||
|
||||
#define STATS_SERVICE_DIR "/data/misc/stats-service"
|
||||
|
||||
// for ConfigMetricsReportList
|
||||
@@ -170,7 +171,7 @@ void StorageManager::appendConfigMetricsReport(const char* path, ProtoOutputStre
|
||||
}
|
||||
}
|
||||
|
||||
void StorageManager::readConfigFromDisk(unordered_map<ConfigKey, StatsdConfig>& configsMap) {
|
||||
void StorageManager::readConfigFromDisk(map<ConfigKey, StatsdConfig>& configsMap) {
|
||||
unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir);
|
||||
if (dir == NULL) {
|
||||
VLOG("no default config on disk");
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
/**
|
||||
* Call to load the saved configs from disk.
|
||||
*/
|
||||
static void readConfigFromDisk(unordered_map<ConfigKey, StatsdConfig>& configsMap);
|
||||
static void readConfigFromDisk(std::map<ConfigKey, StatsdConfig>& configsMap);
|
||||
};
|
||||
|
||||
} // namespace statsd
|
||||
|
||||
Reference in New Issue
Block a user