blob: ebd53e0562496eb2bc22941de780aa9c5448e9c2 [file] [log] [blame]
Bookatza4bc9c42017-10-04 11:45:57 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "CountAnomaly"
18#define DEBUG true // STOPSHIP if true
19#define VLOG(...) \
20 if (DEBUG) ALOGD(__VA_ARGS__);
21
22#include "CountAnomalyTracker.h"
23
24#include <cutils/log.h>
25
26namespace android {
27namespace os {
28namespace statsd {
29
30CountAnomalyTracker::CountAnomalyTracker(size_t numBuckets, int thresholdGt)
31 : mNumPastBuckets(numBuckets > 0 ? numBuckets - 1 : 0),
32 mPastBuckets(mNumPastBuckets > 0 ? (new int[mNumPastBuckets]) : nullptr),
33 mThresholdGt(thresholdGt) {
34
35 VLOG("CountAnomalyTracker() called");
36 if (numBuckets < 1) {
37 ALOGE("Cannot create CountAnomalyTracker with %zu buckets", numBuckets);
38 }
39 reset(); // initialization
40}
41
42CountAnomalyTracker::~CountAnomalyTracker() {
43 VLOG("~CountAnomalyTracker() called");
44}
45
46void CountAnomalyTracker::addPastBucket(int pastBucketCount,
47 time_t numberOfBucketsAgo) {
48 VLOG("addPastBucket() called.");
49 if (numberOfBucketsAgo < 1) {
50 ALOGE("Cannot add a past bucket %ld units in past", numberOfBucketsAgo);
51 return;
52 }
53 // If past bucket was ancient, just empty out all past info.
54 // This always applies if mNumPastBuckets == 0 (i.e. store no past buckets).
55 if (numberOfBucketsAgo > (time_t) mNumPastBuckets) {
56 reset();
57 return;
58 }
59
60 // Empty out old mPastBuckets[i] values and update mSumPastCounters.
61 for (size_t i = mOldestBucketIndex;
62 i < mOldestBucketIndex + numberOfBucketsAgo; i++) {
63 mSumPastCounters -= mPastBuckets[index(i)];
64 mPastBuckets[index(i)] = 0;
65 }
66
67 // Replace the oldest bucket with the new bucket we are adding.
68 mPastBuckets[mOldestBucketIndex] = pastBucketCount;
69 mSumPastCounters += pastBucketCount;
70
71 // Advance the oldest bucket index by numberOfBucketsAgo units.
72 mOldestBucketIndex = index(mOldestBucketIndex + numberOfBucketsAgo);
73
74 // TODO: Once dimensions are added to mSumPastCounters:
75 // iterate through mSumPastCounters and remove any entries that are 0.
76}
77
78void CountAnomalyTracker::reset() {
79 VLOG("reset() called.");
80 for (size_t i = 0; i < mNumPastBuckets; i++) {
81 mPastBuckets[i] = 0;
82 }
83 mSumPastCounters = 0;
84 mOldestBucketIndex = 0;
85}
86
87void CountAnomalyTracker::checkAnomaly(int currentCount) {
88 // Note that this works even if mNumPastBuckets < 1 (since then
89 // mSumPastCounters = 0 so the comparison is based only on currentCount).
90
91 // TODO: Remove these extremely verbose debugging log.
92 VLOG("Checking whether %d + %d > %d",
93 mSumPastCounters, currentCount, mThresholdGt);
94
95 if (mSumPastCounters + currentCount > mThresholdGt) {
96 declareAnomaly();
97 }
98}
99
100void CountAnomalyTracker::declareAnomaly() {
101 // TODO: check that not in refractory period.
102 // TODO: Do something.
103 ALOGI("An anomaly has occurred!");
104}
105
106} // namespace statsd
107} // namespace os
108} // namespace android