blob: 83e262001da09bdd7cce793b36510e686e48044c [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"
Yao Chenab273e22017-09-06 12:53:50 -070018
Joe Onorato9fc9edf2017-10-15 20:08:52 -070019#include "StatsLogProcessor.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070020#include "metrics/CountMetricProducer.h"
21#include "stats_util.h"
22
yro00698da2017-09-15 10:06:40 -070023#include <log/log_event_list.h>
Yao Chenef99c4f2017-09-22 16:26:54 -070024#include <utils/Errors.h>
Yao Chenab273e22017-09-06 12:53:50 -070025
26using namespace android;
yro17adac92017-11-08 23:16:29 -080027using android::util::FIELD_TYPE_BOOL;
28using android::util::FIELD_TYPE_FLOAT;
29using android::util::FIELD_TYPE_INT32;
30using android::util::FIELD_TYPE_INT64;
31using android::util::FIELD_TYPE_MESSAGE;
32using android::util::FIELD_TYPE_STRING;
33using android::util::ProtoOutputStream;
Yao Chen44cf27c2017-09-14 22:32:50 -070034using std::make_unique;
35using std::unique_ptr;
36using std::vector;
Bookatz906a35c2017-09-20 15:26:44 -070037
38namespace android {
39namespace os {
40namespace statsd {
Yao Chenab273e22017-09-06 12:53:50 -070041
yro17adac92017-11-08 23:16:29 -080042// for ConfigMetricsReport
43const int FIELD_ID_CONFIG_KEY = 1;
44const int FIELD_ID_METRICS = 2;
45const int FIELD_ID_UID_MAP = 3;
46// for ConfigKey
47const int FIELD_ID_UID = 1;
48const int FIELD_ID_NAME = 1;
49
yro31eb67b2017-10-24 13:33:21 -070050StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
51 const std::function<void(const vector<uint8_t>&)>& pushLog)
yrofd05a4e2017-10-26 14:08:26 -070052 : mUidMap(uidMap), mPushLog(pushLog) {
Yao Chenab273e22017-09-06 12:53:50 -070053}
54
Yao Chenef99c4f2017-09-22 16:26:54 -070055StatsLogProcessor::~StatsLogProcessor() {
Yao Chenab273e22017-09-06 12:53:50 -070056}
57
Yao Chen44cf27c2017-09-14 22:32:50 -070058// TODO: what if statsd service restarts? How do we know what logs are already processed before?
Joe Onoratoc4dfae52017-10-17 23:38:21 -070059void StatsLogProcessor::OnLogEvent(const LogEvent& msg) {
Yao Chen44cf27c2017-09-14 22:32:50 -070060 // pass the event to metrics managers.
61 for (auto& pair : mMetricsManagers) {
62 pair.second->onLogEvent(msg);
yro69007c82017-10-26 20:42:57 -070063 flushIfNecessary(msg.GetTimestampNs(), pair.first, pair.second);
Yao Chenab273e22017-09-06 12:53:50 -070064 }
65}
66
Joe Onorato9fc9edf2017-10-15 20:08:52 -070067void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) {
68 auto it = mMetricsManagers.find(key);
Yao Chen44cf27c2017-09-14 22:32:50 -070069 if (it != mMetricsManagers.end()) {
70 it->second->finish();
71 }
72
Joe Onorato9fc9edf2017-10-15 20:08:52 -070073 ALOGD("Updated configuration for key %s", key.ToString().c_str());
Yao Chen44cf27c2017-09-14 22:32:50 -070074
Yao Chencaf339d2017-10-06 16:01:10 -070075 unique_ptr<MetricsManager> newMetricsManager = std::make_unique<MetricsManager>(config);
76 if (newMetricsManager->isConfigValid()) {
David Chend6896892017-10-25 11:49:03 -070077 mUidMap->OnConfigUpdated(key);
Joe Onorato9fc9edf2017-10-15 20:08:52 -070078 mMetricsManagers[key] = std::move(newMetricsManager);
79 // Why doesn't this work? mMetricsManagers.insert({key, std::move(newMetricsManager)});
Yao Chencaf339d2017-10-06 16:01:10 -070080 ALOGD("StatsdConfig valid");
81 } else {
82 // If there is any error in the config, don't use it.
83 ALOGD("StatsdConfig NOT valid");
84 }
yro00698da2017-09-15 10:06:40 -070085}
Bookatz906a35c2017-09-20 15:26:44 -070086
yro17adac92017-11-08 23:16:29 -080087vector<uint8_t> StatsLogProcessor::onDumpReport(const ConfigKey& key) {
Yao Chen729093d2017-10-16 10:33:26 -070088 auto it = mMetricsManagers.find(key);
89 if (it == mMetricsManagers.end()) {
90 ALOGW("Config source %s does not exist", key.ToString().c_str());
yro17adac92017-11-08 23:16:29 -080091 return vector<uint8_t>();
Yao Chen729093d2017-10-16 10:33:26 -070092 }
93
yro17adac92017-11-08 23:16:29 -080094 ProtoOutputStream proto;
95
96 // Fill in ConfigKey.
97 long long configKeyToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
98 proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid());
99 proto.write(FIELD_TYPE_STRING | FIELD_ID_NAME, key.GetName());
100 proto.end(configKeyToken);
101
102 // Fill in StatsLogReport's.
103 for (auto& m : it->second->onDumpReport()) {
104 // Add each vector of StatsLogReport into a repeated field.
105 proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_METRICS, reinterpret_cast<char*>(m.get()->data()),
106 m.get()->size());
David Chend6896892017-10-25 11:49:03 -0700107 }
yro17adac92017-11-08 23:16:29 -0800108
109 // Fill in UidMap.
110 auto uidMap = mUidMap->getOutput(key);
111 const int uidMapSize = uidMap.ByteSize();
112 char uidMapBuffer[uidMapSize];
113 uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize);
114 proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize);
115
116 vector<uint8_t> buffer(proto.size());
117 size_t pos = 0;
118 auto iter = proto.data();
119 while (iter.readBuffer() != NULL) {
120 size_t toRead = iter.currentToRead();
121 std::memcpy(&buffer[pos], iter.readBuffer(), toRead);
122 pos += toRead;
123 iter.rp()->move(toRead);
124 }
125
126 return buffer;
Yao Chen729093d2017-10-16 10:33:26 -0700127}
128
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700129void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
130 auto it = mMetricsManagers.find(key);
131 if (it != mMetricsManagers.end()) {
132 it->second->finish();
133 mMetricsManagers.erase(it);
David Chend6896892017-10-25 11:49:03 -0700134 mUidMap->OnConfigRemoved(key);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700135 }
yro69007c82017-10-26 20:42:57 -0700136 auto flushTime = mLastFlushTimes.find(key);
137 if (flushTime != mLastFlushTimes.end()) {
138 mLastFlushTimes.erase(flushTime);
139 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700140}
141
yro69007c82017-10-26 20:42:57 -0700142void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs,
143 const ConfigKey& key,
144 const unique_ptr<MetricsManager>& metricsManager) {
145 auto lastFlushNs = mLastFlushTimes.find(key);
146 if (lastFlushNs != mLastFlushTimes.end()) {
147 if (timestampNs - lastFlushNs->second < kMinFlushPeriod) {
148 return;
149 }
150 }
yro31eb67b2017-10-24 13:33:21 -0700151
yro69007c82017-10-26 20:42:57 -0700152 size_t totalBytes = metricsManager->byteSize();
153 if (totalBytes > kMaxSerializedBytes) {
154 flush();
155 mLastFlushTimes[key] = std::move(timestampNs);
yro31eb67b2017-10-24 13:33:21 -0700156 }
157}
158
159void StatsLogProcessor::flush() {
yro69007c82017-10-26 20:42:57 -0700160 // TODO: Take ConfigKey as an argument and flush metrics related to the
161 // ConfigKey. Also, create a wrapper that holds a repeated field of
162 // StatsLogReport's.
163 /*
yro31eb67b2017-10-24 13:33:21 -0700164 StatsLogReport logReport;
yro31eb67b2017-10-24 13:33:21 -0700165 const int numBytes = logReport.ByteSize();
166 vector<uint8_t> logReportBuffer(numBytes);
167 logReport.SerializeToArray(&logReportBuffer[0], numBytes);
168 mPushLog(logReportBuffer);
yro69007c82017-10-26 20:42:57 -0700169 */
yro31eb67b2017-10-24 13:33:21 -0700170}
171
Yao Chenef99c4f2017-09-22 16:26:54 -0700172} // namespace statsd
173} // namespace os
174} // namespace android