Flush the bucket when creating the metric producer.
Use int64 for value field.
E2e test for gauge/value metric.
BUG: b/74445671
Test: statsd test.
Change-Id: I823a0bade8f89834bdfb9cf48864852a47d7b63b
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 90ce735..efcb1fe 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -72,13 +72,13 @@
StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor,
- const long timeBaseSec,
+ const int64_t timeBaseNs,
const std::function<void(const ConfigKey&)>& sendBroadcast)
: mUidMap(uidMap),
mAnomalyAlarmMonitor(anomalyAlarmMonitor),
mPeriodicAlarmMonitor(periodicAlarmMonitor),
mSendBroadcast(sendBroadcast),
- mTimeBaseSec(timeBaseSec),
+ mTimeBaseNs(timeBaseNs),
mLastLogTimestamp(0) {
}
@@ -210,7 +210,7 @@
const int64_t timestampNs, const ConfigKey& key, const StatsdConfig& config) {
VLOG("Updated configuration for key %s", key.ToString().c_str());
sp<MetricsManager> newMetricsManager =
- new MetricsManager(key, config, mTimeBaseSec, (timestampNs - 1) / NS_PER_SEC + 1, mUidMap,
+ new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
@@ -438,6 +438,10 @@
WriteDataToDiskLocked();
}
+void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) {
+ mStatsPullerManager.OnAlarmFired(timestampNs);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 1e82b1e..0e1d4ba 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -36,7 +36,7 @@
public:
StatsLogProcessor(const sp<UidMap>& uidMap, const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& subscriberTriggerAlarmMonitor,
- const long timeBaseSec,
+ const int64_t timeBaseNs,
const std::function<void(const ConfigKey&)>& sendBroadcast);
virtual ~StatsLogProcessor();
@@ -70,6 +70,7 @@
void dumpStates(FILE* out, bool verbose);
+ void informPullAlarmFired(const int64_t timestampNs);
private:
// For testing only.
@@ -125,7 +126,7 @@
// to retrieve the stored data.
std::function<void(const ConfigKey& key)> mSendBroadcast;
- const long mTimeBaseSec;
+ const int64_t mTimeBaseNs;
int64_t mLastLogTimestamp;
@@ -145,6 +146,12 @@
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
+ FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
+ FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
+ FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
+ FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
+ FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
+
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index d3cda63..86a3a78 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -81,7 +81,7 @@
StatsPuller::SetUidMap(mUidMap);
mConfigManager = new ConfigManager();
mProcessor = new StatsLogProcessor(mUidMap, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
- getElapsedRealtimeSec(), [this](const ConfigKey& key) {
+ getElapsedRealtimeNs(), [this](const ConfigKey& key) {
sp<IStatsCompanionService> sc = getStatsCompanionService();
auto receiver = mConfigManager->GetConfigReceiver(key);
if (sc == nullptr) {
@@ -745,7 +745,7 @@
"Only system uid can call informPollAlarmFired");
}
- mStatsPullerManager.OnAlarmFired();
+ mProcessor->informPullAlarmFired(getElapsedRealtimeNs());
VLOG("StatsService::informPollAlarmFired succeeded");
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 83d59c0..50ffe17 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -40,8 +40,8 @@
return mPullerManager.PullerForMatcherExists(tagId);
}
- void OnAlarmFired() {
- mPullerManager.OnAlarmFired();
+ void OnAlarmFired(const int64_t currentTimeNs) {
+ mPullerManager.OnAlarmFired(currentTimeNs);
}
virtual bool Pull(const int tagId, const int64_t timesNs,
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index 2f0e885..610faad 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -275,11 +275,9 @@
}
}
-void StatsPullerManagerImpl::OnAlarmFired() {
+void StatsPullerManagerImpl::OnAlarmFired(const int64_t currentTimeNs) {
AutoMutex _l(mLock);
- int64_t currentTimeNs = getElapsedRealtimeNs();
-
int64_t minNextPullTimeNs = LONG_MAX;
vector<pair<int, vector<ReceiverInfo*>>> needToPull =
@@ -288,7 +286,7 @@
vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>();
if (pair.second.size() != 0) {
for (ReceiverInfo& receiverInfo : pair.second) {
- if (receiverInfo.nextPullTimeNs < currentTimeNs) {
+ if (receiverInfo.nextPullTimeNs <= currentTimeNs) {
receivers.push_back(&receiverInfo);
} else {
if (receiverInfo.nextPullTimeNs < minNextPullTimeNs) {
@@ -311,10 +309,9 @@
receiverPtr->onDataPulled(data);
// we may have just come out of a coma, compute next pull time
receiverInfo->nextPullTimeNs =
- ceil((double_t)(currentTimeNs - receiverInfo->nextPullTimeNs) /
- receiverInfo->intervalNs) *
- receiverInfo->intervalNs +
- receiverInfo->nextPullTimeNs;
+ (currentTimeNs - receiverInfo->nextPullTimeNs) /
+ receiverInfo->intervalNs * receiverInfo->intervalNs +
+ receiverInfo->intervalNs + receiverInfo->nextPullTimeNs;
if (receiverInfo->nextPullTimeNs < minNextPullTimeNs) {
minNextPullTimeNs = receiverInfo->nextPullTimeNs;
}
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.h b/cmds/statsd/src/external/StatsPullerManagerImpl.h
index 8c771f3..56d04b4 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.h
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.h
@@ -58,7 +58,7 @@
// Verify if we know how to pull for this matcher
bool PullerForMatcherExists(int tagId) const;
- void OnAlarmFired();
+ void OnAlarmFired(const int64_t timeNs);
bool Pull(const int tagId, const int64_t timeNs, vector<std::shared_ptr<LogEvent>>* data);
@@ -90,6 +90,11 @@
void updateAlarmLocked();
int64_t mNextPullTimeNs;
+
+ FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
+ FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
+ FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
+ FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
};
} // namespace statsd
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index b589d0d..c342aa5 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -395,6 +395,14 @@
}
}
+string buildTimeString(int64_t timeSec) {
+ time_t t = timeSec;
+ struct tm* tm = localtime(&t);
+ char timeBuffer[80];
+ strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
+ return string(timeBuffer);
+}
+
void StatsdStats::dumpStats(FILE* out) const {
lock_guard<std::mutex> lock(mLock);
time_t t = mStartTimeSec;
@@ -437,15 +445,19 @@
}
for (const auto& broadcastTime : configStats->broadcast_sent_time_sec) {
- fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
+ fprintf(out, "\tbroadcast time: %s(%lld)\n",
+ buildTimeString(broadcastTime).c_str(), (long long)broadcastTime);
}
for (const auto& dataDropTime : configStats->data_drop_time_sec) {
- fprintf(out, "\tdata drop time: %d\n", dataDropTime);
+ fprintf(out, "\tdata drop time: %s(%lld)\n",
+ buildTimeString(dataDropTime).c_str(), (long long)dataDropTime);
}
for (const auto& dump : configStats->dump_report_stats) {
- fprintf(out, "\tdump report time: %d bytes: %lld\n", dump.first, (long long)dump.second);
+ fprintf(out, "\tdump report time: %s(%lld) bytes: %lld\n",
+ buildTimeString(dump.first).c_str(), (long long)dump.first,
+ (long long)dump.second);
}
for (const auto& stats : pair.second->matcher_stats) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index c77e07b..e21392c 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -92,7 +92,7 @@
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
- (long long)mBucketSizeNs, (long long)mStartTimeNs);
+ (long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
CountMetricProducer::~CountMetricProducer() {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 3125fa7..3661b31 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -122,7 +122,7 @@
}
}
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
- (long long)mBucketSizeNs, (long long)mStartTimeNs);
+ (long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
DurationMetricProducer::~DurationMetricProducer() {
@@ -154,13 +154,13 @@
return make_unique<OringDurationTracker>(
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
- mStartTimeNs, mBucketSizeNs, mConditionSliced,
+ mTimeBaseNs, mBucketSizeNs, mConditionSliced,
mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
case DurationMetric_AggregationType_MAX_SPARSE:
return make_unique<MaxDurationTracker>(
mConfigKey, mMetricId, eventKey, mWizard, mConditionTrackerIndex,
mDimensionsInCondition, mNested, mCurrentBucketStartTimeNs, mCurrentBucketNum,
- mStartTimeNs, mBucketSizeNs, mConditionSliced,
+ mTimeBaseNs, mBucketSizeNs, mConditionSliced,
mHasLinksToAllConditionDimensionsInTracker, mAnomalyTrackers);
}
}
@@ -650,7 +650,7 @@
void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
const LogEvent& event) {
int64_t eventTimeNs = event.GetElapsedTimestampNs();
- if (eventTimeNs < mStartTimeNs) {
+ if (eventTimeNs < mTimeBaseNs) {
return;
}
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 33ab9aa..2f2679e 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -68,7 +68,7 @@
}
mProto = std::make_unique<ProtoOutputStream>();
VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
- (long long)mBucketSizeNs, (long long)mStartTimeNs);
+ (long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
EventMetricProducer::~EventMetricProducer() {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 3c77aae..6886f7c 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -61,9 +61,9 @@
GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const int64_t startTimeNs,
+ const int64_t timeBaseNs, const int64_t startTimeNs,
shared_ptr<StatsPullerManager> statsPullerManager)
- : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
+ : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
mStatsPullerManager(statsPullerManager),
mPullTagId(pullTagId),
mDimensionSoftLimit(StatsdStats::kAtomDimensionKeySizeLimitMap.find(pullTagId) !=
@@ -110,14 +110,15 @@
}
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
+ flushIfNeededLocked(startTimeNs);
// Kicks off the puller immediately.
if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
mStatsPullerManager->RegisterReceiver(
- mPullTagId, this, mCurrentBucketStartTimeNs + mBucketSizeNs, mBucketSizeNs);
+ mPullTagId, this, getCurrentBucketEndTimeNs(), mBucketSizeNs);
}
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
- (long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs,
+ (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
mConditionSliced);
}
@@ -125,14 +126,14 @@
GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const int64_t startTimeNs)
- : GaugeMetricProducer(key, metric, conditionIndex, wizard, pullTagId, startTimeNs,
+ const int64_t timeBaseNs, const int64_t startTimeNs)
+ : GaugeMetricProducer(key, metric, conditionIndex, wizard, pullTagId, timeBaseNs, startTimeNs,
make_shared<StatsPullerManager>()) {
}
GaugeMetricProducer::~GaugeMetricProducer() {
VLOG("~GaugeMetricProducer() called");
- if (mPullTagId != -1) {
+ if (mPullTagId != -1 && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
mStatsPullerManager->UnRegisterReceiver(mPullTagId, this);
}
}
@@ -214,18 +215,20 @@
android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(
mTagId) ==
android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
- const int64_t wall_clock_ns = truncateTimestamp ?
- truncateTimestampNsToFiveMinutes(getWallClockNs()) : getWallClockNs();
for (const auto& atom : bucket.mGaugeAtoms) {
- int64_t timestampNs = truncateTimestamp ?
- truncateTimestampNsToFiveMinutes(atom.mTimestamps) : atom.mTimestamps;
+ const int64_t elapsedTimestampNs = truncateTimestamp ?
+ truncateTimestampNsToFiveMinutes(atom.mElapsedTimestamps) :
+ atom.mElapsedTimestamps;
+ const int64_t wallClockNs = truncateTimestamp ?
+ truncateTimestampNsToFiveMinutes(atom.mWallClockTimestampNs) :
+ atom.mWallClockTimestampNs;
protoOutput->write(
FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
- (long long)timestampNs);
+ (long long)elapsedTimestampNs);
protoOutput->write(
FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED |
FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP,
- (long long)wall_clock_ns);
+ (long long)wallClockNs);
}
}
protoOutput->end(bucketInfoToken);
@@ -241,7 +244,7 @@
// TODO: Clear mDimensionKeyMap once the report is dumped.
}
-void GaugeMetricProducer::pullLocked() {
+void GaugeMetricProducer::pullLocked(const int64_t timestampNs) {
bool triggerPuller = false;
switch(mSamplingType) {
// When the metric wants to do random sampling and there is already one gauge atom for the
@@ -262,7 +265,7 @@
}
vector<std::shared_ptr<LogEvent>> allData;
- if (!mStatsPullerManager->Pull(mPullTagId, getElapsedRealtimeNs(), &allData)) {
+ if (!mStatsPullerManager->Pull(mPullTagId, timestampNs, &allData)) {
ALOGE("Gauge Stats puller failed for tag: %d", mPullTagId);
return;
}
@@ -273,26 +276,26 @@
}
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
- const int64_t eventTime) {
+ const int64_t eventTimeNs) {
VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
- flushIfNeededLocked(eventTime);
+ flushIfNeededLocked(eventTimeNs);
mCondition = conditionMet;
- if (mPullTagId != -1) {
- pullLocked();
+ if (mPullTagId != -1 && mCondition) {
+ pullLocked(eventTimeNs);
} // else: Push mode. No need to proactively pull the gauge data.
}
void GaugeMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const int64_t eventTime) {
+ const int64_t eventTimeNs) {
VLOG("GaugeMetric %lld onSlicedConditionMayChange overall condition %d", (long long)mMetricId,
overallCondition);
- flushIfNeededLocked(eventTime);
+ flushIfNeededLocked(eventTimeNs);
// If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
// pull for every dimension.
mCondition = overallCondition;
if (mPullTagId != -1) {
- pullLocked();
+ pullLocked(eventTimeNs);
} // else: Push mode. No need to proactively pull the gauge data.
}
@@ -360,7 +363,7 @@
if (hitGuardRailLocked(eventKey)) {
return;
}
- GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs);
+ GaugeAtom gaugeAtom(getGaugeFields(event), eventTimeNs, getWallClockNs());
(*mCurrentSlicedBucket)[eventKey].push_back(gaugeAtom);
// Anomaly detection on gauge metric only works when there is one numeric
// field specified.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 04b7df9..08765c2 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -33,11 +33,12 @@
namespace statsd {
struct GaugeAtom {
- GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t timeNs)
- : mFields(fields), mTimestamps(timeNs) {
+ GaugeAtom(std::shared_ptr<vector<FieldValue>> fields, int64_t elapsedTimeNs, int wallClockNs)
+ : mFields(fields), mElapsedTimestamps(elapsedTimeNs), mWallClockTimestampNs(wallClockNs) {
}
std::shared_ptr<vector<FieldValue>> mFields;
- int64_t mTimestamps;
+ int64_t mElapsedTimestamps;
+ int64_t mWallClockTimestampNs;
};
struct GaugeBucket {
@@ -57,7 +58,7 @@
public:
GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const int64_t startTimeNs);
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs);
virtual ~GaugeMetricProducer();
@@ -76,7 +77,7 @@
flushCurrentBucketLocked(eventTimeNs);
mCurrentBucketStartTimeNs = eventTimeNs;
if (mPullTagId != -1) {
- pullLocked();
+ pullLocked(eventTimeNs);
}
};
@@ -94,7 +95,8 @@
// for testing
GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const int64_t startTimeNs,
+ const int pullTagId,
+ const int64_t timeBaseNs, const int64_t startTimeNs,
std::shared_ptr<StatsPullerManager> statsPullerManager);
// Internal interface to handle condition change.
@@ -115,7 +117,7 @@
void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
- void pullLocked();
+ void pullLocked(const int64_t timestampNs);
int mTagId;
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index bcf0e62..5ff8082 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -27,7 +27,7 @@
void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
int64_t eventTimeNs = event.GetElapsedTimestampNs();
// this is old event, maybe statsd restarted?
- if (eventTimeNs < mStartTimeNs) {
+ if (eventTimeNs < mTimeBaseNs) {
return;
}
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index f931e57..532ecbf 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -40,12 +40,12 @@
// be a no-op.
class MetricProducer : public virtual PackageInfoListener {
public:
- MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t startTimeNs,
+ MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
const int conditionIndex, const sp<ConditionWizard>& wizard)
: mMetricId(metricId),
mConfigKey(key),
- mStartTimeNs(startTimeNs),
- mCurrentBucketStartTimeNs(startTimeNs),
+ mTimeBaseNs(timeBaseNs),
+ mCurrentBucketStartTimeNs(timeBaseNs),
mCurrentBucketNum(0),
mCondition(conditionIndex >= 0 ? false : true),
mConditionSliced(false),
@@ -165,6 +165,11 @@
dropDataLocked(dropTimeNs);
}
+ // For test only.
+ inline int64_t getCurrentBucketNum() const {
+ return mCurrentBucketNum;
+ }
+
protected:
virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0;
virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
@@ -204,7 +209,7 @@
// Convenience to compute the current bucket's end time, which is always aligned with the
// start time of the metric.
int64_t getCurrentBucketEndTimeNs() const {
- return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
+ return mTimeBaseNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
}
virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
@@ -215,7 +220,7 @@
// The time when this metric producer was first created. The end time for the current bucket
// can be computed from this based on mCurrentBucketNum.
- int64_t mStartTimeNs;
+ int64_t mTimeBaseNs;
// Start time may not be aligned with the start of statsd if there is an app upgrade in the
// middle of a bucket.
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index b7f1bd5..47a1a86 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -54,21 +54,21 @@
const int FIELD_ID_ANNOTATIONS_INT32 = 2;
MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
- const long timeBaseSec, const long currentTimeSec,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
const sp<UidMap> &uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor)
: mConfigKey(key), mUidMap(uidMap),
mTtlNs(config.has_ttl_in_seconds() ? config.ttl_in_seconds() * NS_PER_SEC : -1),
mTtlEndNs(-1),
- mLastReportTimeNs(timeBaseSec * NS_PER_SEC),
+ mLastReportTimeNs(timeBaseNs),
mLastReportWallClockNs(getWallClockNs()) {
// Init the ttl end timestamp.
- refreshTtl(timeBaseSec * NS_PER_SEC);
+ refreshTtl(timeBaseNs);
mConfigValid =
initStatsdConfig(key, config, *uidMap, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, currentTimeSec, mTagIds, mAllAtomMatchers,
+ timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers,
mAllConditionTrackers, mAllMetricProducers, mAllAnomalyTrackers,
mAllPeriodicAlarmTrackers, mConditionToMetricMap, mTrackerToMetricMap,
mTrackerToConditionMap, mNoReportMetricIds);
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 6aa260a..3d2c595 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -37,7 +37,7 @@
class MetricsManager : public PackageInfoListener {
public:
MetricsManager(const ConfigKey& configKey, const StatsdConfig& config,
- const long timeBaseSec, const long currentTimeSec,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
const sp<UidMap>& uidMap, const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor);
@@ -187,6 +187,11 @@
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
+ FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
+ FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
+ FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
+ FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
+ FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_OR_CombinationCondition);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 89efae3..844c728 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -63,9 +63,9 @@
ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const int64_t startTimeNs,
+ const int64_t timeBaseNs, const int64_t startTimestampNs,
shared_ptr<StatsPullerManager> statsPullerManager)
- : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
+ : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
mValueField(metric.value_field()),
mStatsPullerManager(statsPullerManager),
mPullTagId(pullTagId),
@@ -105,27 +105,28 @@
}
}
- if (mValueField.child_size()) {
+ if (mValueField.child_size() > 0) {
mField = mValueField.child(0).field();
}
mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
// Kicks off the puller immediately.
+ flushIfNeededLocked(startTimestampNs);
if (mPullTagId != -1) {
mStatsPullerManager->RegisterReceiver(
mPullTagId, this, mCurrentBucketStartTimeNs + mBucketSizeNs, mBucketSizeNs);
}
VLOG("value metric %lld created. bucket size %lld start_time: %lld",
- (long long)metric.id(), (long long)mBucketSizeNs, (long long)mStartTimeNs);
+ (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
// for testing
ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const int64_t startTimeNs)
- : ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId, startTimeNs,
+ const int64_t timeBaseNs, const int64_t startTimeNs)
+ : ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId, timeBaseNs, startTimeNs,
make_shared<StatsPullerManager>()) {
}
@@ -198,7 +199,6 @@
VLOG("metric %lld dump report now...", (long long)mMetricId);
mPastBuckets.clear();
- // TODO: Clear mDimensionKeyMap once the report is dumped.
}
void ValueMetricProducer::onConditionChangedLocked(const bool condition,
@@ -237,8 +237,8 @@
// For scheduled pulled data, the effective event time is snap to the nearest
// bucket boundary to make bucket finalize.
int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
- int64_t eventTime = mStartTimeNs +
- ((realEventTime - mStartTimeNs) / mBucketSizeNs) * mBucketSizeNs;
+ int64_t eventTime = mTimeBaseNs +
+ ((realEventTime - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
mCondition = false;
for (const auto& data : allData) {
@@ -310,7 +310,7 @@
Interval& interval = mCurrentSlicedBucket[eventKey];
int error = 0;
- const long value = event.GetLong(mField, &error);
+ const int64_t value = event.GetLong(mField, &error);
if (error < 0) {
return;
}
@@ -337,7 +337,7 @@
interval.hasValue = true;
interval.startUpdated = false;
} else {
- VLOG("No start for matching end %ld", value);
+ VLOG("No start for matching end %lld", (long long)value);
interval.tainted += 1;
}
}
@@ -359,7 +359,7 @@
void ValueMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
- if (currentBucketEndTimeNs > eventTimeNs) {
+ if (eventTimeNs < currentBucketEndTimeNs) {
VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
(long long)(currentBucketEndTimeNs));
return;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index b19adbe..9c5a56c 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -40,7 +40,7 @@
public:
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const int64_t startTimeNs);
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs);
virtual ~ValueMetricProducer();
@@ -115,7 +115,7 @@
// for testing
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const int64_t startTimeNs,
+ const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
std::shared_ptr<StatsPullerManager> statsPullerManager);
// tagId for pulled data. -1 if this is not pulled
@@ -127,14 +127,14 @@
typedef struct {
// Pulled data always come in pair of <start, end>. This holds the value
// for start. The diff (end - start) is added to sum.
- long start;
+ int64_t start;
// Whether the start data point is updated
bool startUpdated;
// If end data point comes before the start, record this pair as tainted
// and the value is not added to the running sum.
int tainted;
// Running sum of known pairs in this bucket
- long sum;
+ int64_t sum;
// If this dimension has any non-tainted value. If not, don't report the
// dimension.
bool hasValue;
@@ -142,7 +142,7 @@
std::unordered_map<MetricDimensionKey, Interval> mCurrentSlicedBucket;
- std::unordered_map<MetricDimensionKey, long> mCurrentFullBucket;
+ std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
// Save the past buckets and we can clear when the StatsLogReport is dumped.
// TODO: Add a lock to mPastBuckets.
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 566d34e..811a00e 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -262,7 +262,8 @@
return true;
}
-bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec,
+bool initMetrics(const ConfigKey& key, const StatsdConfig& config,
+ const int64_t timeBaseTimeNs, const int64_t currentTimeNs,
UidMap& uidMap, const unordered_map<int64_t, int>& logTrackerMap,
const unordered_map<int64_t, int>& conditionTrackerMap,
const vector<sp<LogMatchingTracker>>& allAtomMatchers,
@@ -277,8 +278,6 @@
allMetricProducers.reserve(allMetricsCount);
StatsPullerManager statsPullerManager;
- uint64_t startTimeNs = timeBaseSec * NS_PER_SEC;
-
// Build MetricProducers for each metric defined in config.
// build CountMetricProducer
for (int i = 0; i < config.count_metric_size(); i++) {
@@ -314,7 +313,7 @@
}
sp<MetricProducer> countProducer =
- new CountMetricProducer(key, metric, conditionIndex, wizard, startTimeNs);
+ new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
allMetricProducers.push_back(countProducer);
}
@@ -384,7 +383,7 @@
sp<MetricProducer> durationMetric = new DurationMetricProducer(
key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
- trackerIndices[2], nesting, wizard, internalDimensions, startTimeNs);
+ trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs);
allMetricProducers.push_back(durationMetric);
}
@@ -420,7 +419,7 @@
}
sp<MetricProducer> eventMetric =
- new EventMetricProducer(key, metric, conditionIndex, wizard, startTimeNs);
+ new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
allMetricProducers.push_back(eventMetric);
}
@@ -467,7 +466,8 @@
}
sp<MetricProducer> valueProducer = new ValueMetricProducer(key, metric, conditionIndex,
- wizard, pullTagId, startTimeNs);
+ wizard, pullTagId,
+ timeBaseTimeNs, currentTimeNs);
allMetricProducers.push_back(valueProducer);
}
@@ -526,7 +526,7 @@
}
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
- key, metric, conditionIndex, wizard, pullTagId, startTimeNs);
+ key, metric, conditionIndex, wizard, pullTagId, timeBaseTimeNs, currentTimeNs);
allMetricProducers.push_back(gaugeProducer);
}
for (int i = 0; i < config.no_report_metric_size(); ++i) {
@@ -601,11 +601,11 @@
bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
const sp<AlarmMonitor>& periodicAlarmMonitor,
- const long timeBaseSec, const long currentTimeSec,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
vector<sp<AlarmTracker>>& allAlarmTrackers) {
unordered_map<int64_t, int> alarmTrackerMap;
- uint64_t startMillis = (uint64_t)timeBaseSec * MS_PER_SEC;
- uint64_t currentTimeMillis = (uint64_t)currentTimeSec * MS_PER_SEC;
+ int64_t startMillis = timeBaseNs / 1000 / 1000;
+ int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
for (int i = 0; i < config.alarm_size(); i++) {
const Alarm& alarm = config.alarm(i);
if (alarm.offset_millis() <= 0) {
@@ -646,8 +646,9 @@
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
- const sp<AlarmMonitor>& periodicAlarmMonitor, const long timeBaseSec,
- const long currentTimeSec, set<int>& allTagIds,
+ const sp<AlarmMonitor>& periodicAlarmMonitor,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
+ set<int>& allTagIds,
vector<sp<LogMatchingTracker>>& allAtomMatchers,
vector<sp<ConditionTracker>>& allConditionTrackers,
vector<sp<MetricProducer>>& allMetricProducers,
@@ -673,7 +674,8 @@
return false;
}
- if (!initMetrics(key, config, timeBaseSec, uidMap, logTrackerMap, conditionTrackerMap,
+ if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap,
+ logTrackerMap, conditionTrackerMap,
allAtomMatchers, allConditionTrackers, allMetricProducers,
conditionToMetricMap, trackerToMetricMap, metricProducerMap,
noReportMetricIds)) {
@@ -686,7 +688,7 @@
return false;
}
if (!initAlarms(config, key, periodicAlarmMonitor,
- timeBaseSec, currentTimeSec, allPeriodicAlarmTrackers)) {
+ timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
ALOGE("initAlarms failed");
return false;
}
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index 0ebdcf9..d749bf4 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -81,7 +81,9 @@
// the list of MetricProducer index
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
bool initMetrics(
- const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec, UidMap& uidMap,
+ const ConfigKey& key, const StatsdConfig& config,
+ const int64_t timeBaseTimeNs, const int64_t currentTimeNs,
+ UidMap& uidMap,
const std::unordered_map<int64_t, int>& logTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
@@ -96,8 +98,9 @@
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
- const sp<AlarmMonitor>& periodicAlarmMonitor, const long timeBaseSec,
- const long currentTimeSec, std::set<int>& allTagIds,
+ const sp<AlarmMonitor>& periodicAlarmMonitor,
+ const int64_t timeBaseNs, const int64_t currentTimeNs,
+ std::set<int>& allTagIds,
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::vector<sp<MetricProducer>>& allMetricProducers,
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 36b24c8..4f7581d 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -97,9 +97,9 @@
}
message GaugeBucketInfo {
- optional int64 start_bucket_nanos = 1;
+ optional int64 start_bucket_elapsed_nanos = 1;
- optional int64 end_bucket_nanos = 2;
+ optional int64 end_bucket_elapsed_nanos = 2;
repeated Atom atom = 3;