blob: fcb5107c31fcbf119217616ede7d4004ccd552ef [file] [log] [blame]
Yao Chenab273e22017-09-06 12:53:50 -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
Joe Onorato9fc9edf2017-10-15 20:08:52 -070017#include "Log.h"
David Chen21582962017-11-01 17:32:46 -070018#include "statslog.h"
Yao Chenab273e22017-09-06 12:53:50 -070019
Joe Onorato9fc9edf2017-10-15 20:08:52 -070020#include "StatsLogProcessor.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070021#include "metrics/CountMetricProducer.h"
22#include "stats_util.h"
23
yro00698da2017-09-15 10:06:40 -070024#include <log/log_event_list.h>
Yao Chenef99c4f2017-09-22 16:26:54 -070025#include <utils/Errors.h>
Yao Chenab273e22017-09-06 12:53:50 -070026
27using namespace android;
yrob0378b02017-11-09 20:36:25 -080028using android::util::FIELD_COUNT_REPEATED;
yro17adac92017-11-08 23:16:29 -080029using android::util::FIELD_TYPE_BOOL;
30using android::util::FIELD_TYPE_FLOAT;
31using android::util::FIELD_TYPE_INT32;
32using android::util::FIELD_TYPE_INT64;
33using android::util::FIELD_TYPE_MESSAGE;
34using android::util::FIELD_TYPE_STRING;
35using android::util::ProtoOutputStream;
Yao Chen44cf27c2017-09-14 22:32:50 -070036using std::make_unique;
37using std::unique_ptr;
38using std::vector;
Bookatz906a35c2017-09-20 15:26:44 -070039
40namespace android {
41namespace os {
42namespace statsd {
Yao Chenab273e22017-09-06 12:53:50 -070043
yro17adac92017-11-08 23:16:29 -080044// for ConfigMetricsReport
45const int FIELD_ID_CONFIG_KEY = 1;
46const int FIELD_ID_METRICS = 2;
47const int FIELD_ID_UID_MAP = 3;
48// for ConfigKey
49const int FIELD_ID_UID = 1;
yrob0378b02017-11-09 20:36:25 -080050const int FIELD_ID_NAME = 2;
yro17adac92017-11-08 23:16:29 -080051
yro31eb67b2017-10-24 13:33:21 -070052StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
Yangster-mace2cd6d52017-11-09 20:38:30 -080053 const sp<AnomalyMonitor>& anomalyMonitor,
David Chen1d7b0cd2017-11-15 14:20:04 -080054 const std::function<void(const ConfigKey&)>& sendBroadcast)
Yangster-mace2cd6d52017-11-09 20:38:30 -080055 : mUidMap(uidMap), mAnomalyMonitor(anomalyMonitor), mSendBroadcast(sendBroadcast) {
Yao Chenab273e22017-09-06 12:53:50 -070056}
57
Yao Chenef99c4f2017-09-22 16:26:54 -070058StatsLogProcessor::~StatsLogProcessor() {
Yao Chenab273e22017-09-06 12:53:50 -070059}
60
Yangster-mace2cd6d52017-11-09 20:38:30 -080061void StatsLogProcessor::onAnomalyAlarmFired(
62 const uint64_t timestampNs,
63 unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet) {
64 for (const auto& anomaly : anomalySet) {
65 for (const auto& itr : mMetricsManagers) {
66 itr.second->onAnomalyAlarmFired(timestampNs, anomaly);
67 }
68 }
69}
70
Yao Chen44cf27c2017-09-14 22:32:50 -070071// TODO: what if statsd service restarts? How do we know what logs are already processed before?
Joe Onoratoc4dfae52017-10-17 23:38:21 -070072void StatsLogProcessor::OnLogEvent(const LogEvent& msg) {
Yao Chen44cf27c2017-09-14 22:32:50 -070073 // pass the event to metrics managers.
74 for (auto& pair : mMetricsManagers) {
75 pair.second->onLogEvent(msg);
yro69007c82017-10-26 20:42:57 -070076 flushIfNecessary(msg.GetTimestampNs(), pair.first, pair.second);
Yao Chenab273e22017-09-06 12:53:50 -070077 }
David Chen21582962017-11-01 17:32:46 -070078
79 // Hard-coded logic to update the isolated uid's in the uid-map.
Stefan Lafonae2df012017-11-14 09:17:21 -080080 // The field numbers need to be currently updated by hand with atoms.proto
David Chen21582962017-11-01 17:32:46 -070081 if (msg.GetTagId() == android::util::ISOLATED_UID_CHANGED) {
82 status_t err = NO_ERROR, err2 = NO_ERROR, err3 = NO_ERROR;
83 bool is_create = msg.GetBool(3, &err);
84 auto parent_uid = int(msg.GetLong(1, &err2));
85 auto isolated_uid = int(msg.GetLong(2, &err3));
86 if (err == NO_ERROR && err2 == NO_ERROR && err3 == NO_ERROR) {
87 if (is_create) {
88 mUidMap->assignIsolatedUid(isolated_uid, parent_uid);
89 } else {
90 mUidMap->removeIsolatedUid(isolated_uid, parent_uid);
91 }
92 }
93 }
Yao Chenab273e22017-09-06 12:53:50 -070094}
95
Joe Onorato9fc9edf2017-10-15 20:08:52 -070096void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) {
97 auto it = mMetricsManagers.find(key);
Yao Chen44cf27c2017-09-14 22:32:50 -070098 if (it != mMetricsManagers.end()) {
99 it->second->finish();
100 }
101
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700102 ALOGD("Updated configuration for key %s", key.ToString().c_str());
Yao Chen44cf27c2017-09-14 22:32:50 -0700103
Yao Chencaf339d2017-10-06 16:01:10 -0700104 unique_ptr<MetricsManager> newMetricsManager = std::make_unique<MetricsManager>(config);
105 if (newMetricsManager->isConfigValid()) {
David Chend6896892017-10-25 11:49:03 -0700106 mUidMap->OnConfigUpdated(key);
Yangster-mace2cd6d52017-11-09 20:38:30 -0800107 newMetricsManager->setAnomalyMonitor(mAnomalyMonitor);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700108 mMetricsManagers[key] = std::move(newMetricsManager);
109 // Why doesn't this work? mMetricsManagers.insert({key, std::move(newMetricsManager)});
Yao Chencaf339d2017-10-06 16:01:10 -0700110 ALOGD("StatsdConfig valid");
111 } else {
112 // If there is any error in the config, don't use it.
113 ALOGD("StatsdConfig NOT valid");
114 }
yro00698da2017-09-15 10:06:40 -0700115}
Bookatz906a35c2017-09-20 15:26:44 -0700116
David Chen1d7b0cd2017-11-15 14:20:04 -0800117size_t StatsLogProcessor::GetMetricsSize(const ConfigKey& key) {
Yao Chen729093d2017-10-16 10:33:26 -0700118 auto it = mMetricsManagers.find(key);
119 if (it == mMetricsManagers.end()) {
120 ALOGW("Config source %s does not exist", key.ToString().c_str());
David Chen1d7b0cd2017-11-15 14:20:04 -0800121 return 0;
Yao Chen729093d2017-10-16 10:33:26 -0700122 }
David Chen1d7b0cd2017-11-15 14:20:04 -0800123 return it->second->byteSize();
124}
125
126void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outData) {
127 auto it = mMetricsManagers.find(key);
128 if (it == mMetricsManagers.end()) {
129 ALOGW("Config source %s does not exist", key.ToString().c_str());
130 return;
131 }
132
133 // This allows another broadcast to be sent within the rate-limit period if we get close to
134 // filling the buffer again soon.
135 mBroadcastTimesMutex.lock();
136 mLastBroadcastTimes.erase(key);
137 mBroadcastTimesMutex.unlock();
Yao Chen729093d2017-10-16 10:33:26 -0700138
yro17adac92017-11-08 23:16:29 -0800139 ProtoOutputStream proto;
140
141 // Fill in ConfigKey.
142 long long configKeyToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
143 proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid());
144 proto.write(FIELD_TYPE_STRING | FIELD_ID_NAME, key.GetName());
145 proto.end(configKeyToken);
146
147 // Fill in StatsLogReport's.
148 for (auto& m : it->second->onDumpReport()) {
149 // Add each vector of StatsLogReport into a repeated field.
yrob0378b02017-11-09 20:36:25 -0800150 proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS,
151 reinterpret_cast<char*>(m.get()->data()), m.get()->size());
David Chend6896892017-10-25 11:49:03 -0700152 }
yro17adac92017-11-08 23:16:29 -0800153
154 // Fill in UidMap.
155 auto uidMap = mUidMap->getOutput(key);
156 const int uidMapSize = uidMap.ByteSize();
157 char uidMapBuffer[uidMapSize];
158 uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize);
159 proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize);
160
David Chen1d7b0cd2017-11-15 14:20:04 -0800161 if (outData != nullptr) {
162 outData->clear();
163 outData->resize(proto.size());
164 size_t pos = 0;
165 auto iter = proto.data();
166 while (iter.readBuffer() != NULL) {
167 size_t toRead = iter.currentToRead();
168 std::memcpy(&((*outData)[pos]), iter.readBuffer(), toRead);
169 pos += toRead;
170 iter.rp()->move(toRead);
171 }
yro17adac92017-11-08 23:16:29 -0800172 }
Yao Chen729093d2017-10-16 10:33:26 -0700173}
174
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700175void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
176 auto it = mMetricsManagers.find(key);
177 if (it != mMetricsManagers.end()) {
178 it->second->finish();
179 mMetricsManagers.erase(it);
David Chend6896892017-10-25 11:49:03 -0700180 mUidMap->OnConfigRemoved(key);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700181 }
David Chen1d7b0cd2017-11-15 14:20:04 -0800182
183 std::lock_guard<std::mutex> lock(mBroadcastTimesMutex);
184 mLastBroadcastTimes.erase(key);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700185}
186
yro69007c82017-10-26 20:42:57 -0700187void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs,
188 const ConfigKey& key,
189 const unique_ptr<MetricsManager>& metricsManager) {
David Chen1d7b0cd2017-11-15 14:20:04 -0800190 std::lock_guard<std::mutex> lock(mBroadcastTimesMutex);
yro31eb67b2017-10-24 13:33:21 -0700191
yro69007c82017-10-26 20:42:57 -0700192 size_t totalBytes = metricsManager->byteSize();
David Chen1d7b0cd2017-11-15 14:20:04 -0800193 if (totalBytes > .9 * kMaxSerializedBytes) { // Send broadcast so that receivers can pull data.
194 auto lastFlushNs = mLastBroadcastTimes.find(key);
195 if (lastFlushNs != mLastBroadcastTimes.end()) {
196 if (timestampNs - lastFlushNs->second < kMinBroadcastPeriod) {
197 return;
198 }
199 }
200 mLastBroadcastTimes[key] = timestampNs;
201 ALOGD("StatsD requesting broadcast for %s", key.ToString().c_str());
202 mSendBroadcast(key);
203 } else if (totalBytes > kMaxSerializedBytes) { // Too late. We need to start clearing data.
204 // We ignore the return value so we force each metric producer to clear its contents.
205 metricsManager->onDumpReport();
206 ALOGD("StatsD had to toss out metrics for %s", key.ToString().c_str());
yro31eb67b2017-10-24 13:33:21 -0700207 }
208}
209
Yao Chenef99c4f2017-09-22 16:26:54 -0700210} // namespace statsd
211} // namespace os
212} // namespace android