blob: 7acef6d6cf389545739299444eb66f0df3929404 [file] [log] [blame]
Mark Salyzyn34facab2014-02-06 14:48:50 -08001/*
2 * Copyright (C) 2014 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#ifndef _LOGD_LOG_STATISTICS_H__
18#define _LOGD_LOG_STATISTICS_H__
19
Mark Salyzynb545e1c2016-12-19 14:51:15 -080020#include <ctype.h>
Mark Salyzyn720f6d12015-03-16 08:26:05 -070021#include <stdlib.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080022#include <sys/types.h>
23
Mark Salyzyn758058f2015-08-21 16:44:30 -070024#include <algorithm> // std::max
Mark Salyzynb545e1c2016-12-19 14:51:15 -080025#include <memory>
Mark Salyzyn758058f2015-08-21 16:44:30 -070026#include <string> // std::string
Mark Salyzyn511338d2015-05-19 09:12:30 -070027#include <unordered_map>
28
Mark Salyzyn0dd44312016-09-28 15:54:45 -070029#include <android/log.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080030#include <android-base/stringprintf.h>
Mark Salyzyn758058f2015-08-21 16:44:30 -070031#include <private/android_filesystem_config.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070032
33#include "LogBufferElement.h"
Mark Salyzyn5ac5c6b2015-08-28 08:02:59 -070034#include "LogUtils.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080035
36#define log_id_for_each(i) \
Chih-Hung Hsiehf0f94fe2016-05-18 15:47:19 -070037 for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t) ((i) + 1))
Mark Salyzyn34facab2014-02-06 14:48:50 -080038
Mark Salyzyn758058f2015-08-21 16:44:30 -070039class LogStatistics;
40
Mark Salyzyn720f6d12015-03-16 08:26:05 -070041template <typename TKey, typename TEntry>
Mark Salyzyn511338d2015-05-19 09:12:30 -070042class LogHashtable {
43
44 std::unordered_map<TKey, TEntry> map;
45
Mark Salyzyn6d981af2016-10-06 09:55:21 -070046 size_t bucket_size() const {
47 size_t count = 0;
48 for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
49 size_t bucket_size = map.bucket_size(idx);
50 if (bucket_size == 0) bucket_size = 1;
51 count += bucket_size;
52 }
53 float load_factor = map.max_load_factor();
54 if (load_factor < 1.0) return count;
55 return count * load_factor;
56 }
57
58 static const size_t unordered_map_per_entry_overhead = sizeof(void*);
59 static const size_t unordered_map_bucket_overhead = sizeof(void*);
60
Mark Salyzyn720f6d12015-03-16 08:26:05 -070061public:
Mark Salyzyn511338d2015-05-19 09:12:30 -070062
Mark Salyzynb0672292016-10-06 10:09:24 -070063 size_t size() const { return map.size(); }
64
Mark Salyzyn6d981af2016-10-06 09:55:21 -070065 // Estimate unordered_map memory usage.
66 size_t sizeOf() const {
67 return sizeof(*this) +
Mark Salyzynb0672292016-10-06 10:09:24 -070068 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn6d981af2016-10-06 09:55:21 -070069 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
70 }
71
Mark Salyzyn511338d2015-05-19 09:12:30 -070072 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn758058f2015-08-21 16:44:30 -070073 typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn511338d2015-05-19 09:12:30 -070074
Mark Salyzynee3b8382015-12-17 09:58:43 -080075 std::unique_ptr<const TEntry *[]> sort(uid_t uid, pid_t pid,
76 size_t len) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -070077 if (!len) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -070078 std::unique_ptr<const TEntry *[]> sorted(NULL);
79 return sorted;
80 }
81
Mark Salyzyn758058f2015-08-21 16:44:30 -070082 const TEntry **retval = new const TEntry* [len];
83 memset(retval, 0, sizeof(*retval) * len);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070084
Mark Salyzyn758058f2015-08-21 16:44:30 -070085 for(const_iterator it = map.begin(); it != map.end(); ++it) {
Mark Salyzyn511338d2015-05-19 09:12:30 -070086 const TEntry &entry = it->second;
Mark Salyzynee3b8382015-12-17 09:58:43 -080087
88 if ((uid != AID_ROOT) && (uid != entry.getUid())) {
89 continue;
90 }
91 if (pid && entry.getPid() && (pid != entry.getPid())) {
92 continue;
93 }
94
Mark Salyzyn758058f2015-08-21 16:44:30 -070095 size_t sizes = entry.getSizes();
96 ssize_t index = len - 1;
97 while ((!retval[index] || (sizes > retval[index]->getSizes()))
98 && (--index >= 0))
Mark Salyzyn720f6d12015-03-16 08:26:05 -070099 ;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700100 if (++index < (ssize_t)len) {
101 size_t num = len - index - 1;
102 if (num) {
103 memmove(&retval[index + 1], &retval[index],
104 num * sizeof(retval[0]));
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700105 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700106 retval[index] = &entry;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700107 }
108 }
109 std::unique_ptr<const TEntry *[]> sorted(retval);
110 return sorted;
111 }
112
Mark Salyzyn758058f2015-08-21 16:44:30 -0700113 inline iterator add(TKey key, LogBufferElement *element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700114 iterator it = map.find(key);
115 if (it == map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700116 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn511338d2015-05-19 09:12:30 -0700117 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700118 it->second.add(element);
Mark Salyzyn511338d2015-05-19 09:12:30 -0700119 }
120 return it;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700121 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700122
Mark Salyzyn511338d2015-05-19 09:12:30 -0700123 inline iterator add(TKey key) {
124 iterator it = map.find(key);
125 if (it == map.end()) {
126 it = map.insert(std::make_pair(key, TEntry(key))).first;
127 } else {
128 it->second.add(key);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700129 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700130 return it;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700131 }
132
Mark Salyzyn758058f2015-08-21 16:44:30 -0700133 void subtract(TKey key, LogBufferElement *element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700134 iterator it = map.find(key);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700135 if ((it != map.end()) && it->second.subtract(element)) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700136 map.erase(it);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700137 }
138 }
139
Mark Salyzyn758058f2015-08-21 16:44:30 -0700140 inline void drop(TKey key, LogBufferElement *element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700141 iterator it = map.find(key);
142 if (it != map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700143 it->second.drop(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700144 }
145 }
146
Mark Salyzyn511338d2015-05-19 09:12:30 -0700147 inline iterator begin() { return map.begin(); }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700148 inline const_iterator begin() const { return map.begin(); }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700149 inline iterator end() { return map.end(); }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700150 inline const_iterator end() const { return map.end(); }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700151
Mark Salyzyn758058f2015-08-21 16:44:30 -0700152 std::string format(
153 const LogStatistics &stat,
154 uid_t uid,
Mark Salyzynee3b8382015-12-17 09:58:43 -0800155 pid_t pid,
Mark Salyzyn758058f2015-08-21 16:44:30 -0700156 const std::string &name = std::string(""),
157 log_id_t id = LOG_ID_MAX) const {
158 static const size_t maximum_sorted_entries = 32;
159 std::string output;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800160 std::unique_ptr<const TEntry *[]> sorted = sort(uid, pid,
161 maximum_sorted_entries);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700162 if (!sorted.get()) {
163 return output;
164 }
165 bool headerPrinted = false;
166 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
167 const TEntry *entry = sorted[index];
168 if (!entry) {
169 break;
170 }
171 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
172 break;
173 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700174 if (!headerPrinted) {
175 output += "\n\n";
176 output += entry->formatHeader(name, id);
177 headerPrinted = true;
178 }
179 output += entry->format(stat, id);
180 }
181 return output;
182 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700183
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700184};
185
Mark Salyzyn758058f2015-08-21 16:44:30 -0700186namespace EntryBaseConstants {
187 static constexpr size_t pruned_len = 14;
188 static constexpr size_t total_len = 80;
189}
190
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700191struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700192 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700193
194 EntryBase():size(0) { }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700195 explicit EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700196
197 size_t getSizes() const { return size; }
198
Mark Salyzyn758058f2015-08-21 16:44:30 -0700199 inline void add(LogBufferElement *element) { size += element->getMsgLen(); }
200 inline bool subtract(LogBufferElement *element) {
201 size -= element->getMsgLen();
202 return !size;
203 }
204
205 static std::string formatLine(
206 const std::string &name,
207 const std::string &size,
208 const std::string &pruned) {
209 ssize_t drop_len = std::max(pruned.length() + 1,
210 EntryBaseConstants::pruned_len);
211 ssize_t size_len = std::max(size.length() + 1,
212 EntryBaseConstants::total_len
213 - name.length() - drop_len - 1);
214
Mark Salyzynb545e1c2016-12-19 14:51:15 -0800215 std::string ret = android::base::StringPrintf("%s%*s%*s",
216 name.c_str(),
217 (int)size_len, size.c_str(),
218 (int)drop_len, pruned.c_str());
219 // remove any trailing spaces
220 size_t pos = ret.size();
221 size_t len = 0;
222 while (pos && isspace(ret[--pos])) ++len;
223 if (len) ret.erase(pos + 1, len);
224 return ret + "\n";
Mark Salyzyn758058f2015-08-21 16:44:30 -0700225 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700226};
227
228struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700229 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800230
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700231 EntryBaseDropped():dropped(0) { }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700232 explicit EntryBaseDropped(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700233 EntryBase(element),
Mark Salyzyn6a066942016-07-14 15:34:30 -0700234 dropped(element->getDropped()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700235 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800236
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700237 size_t getDropped() const { return dropped; }
238
Mark Salyzyn758058f2015-08-21 16:44:30 -0700239 inline void add(LogBufferElement *element) {
240 dropped += element->getDropped();
241 EntryBase::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700242 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700243 inline bool subtract(LogBufferElement *element) {
244 dropped -= element->getDropped();
245 return EntryBase::subtract(element) && !dropped;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700246 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700247 inline void drop(LogBufferElement *element) {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700248 dropped += 1;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700249 EntryBase::subtract(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700250 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800251};
252
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700253struct UidEntry : public EntryBaseDropped {
254 const uid_t uid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800255 pid_t pid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700256
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700257 explicit UidEntry(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700258 EntryBaseDropped(element),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800259 uid(element->getUid()),
260 pid(element->getPid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700261 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700262
263 inline const uid_t&getKey() const { return uid; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800264 inline const uid_t&getUid() const { return getKey(); }
265 inline const pid_t&getPid() const { return pid; }
266
267 inline void add(LogBufferElement *element) {
268 if (pid != element->getPid()) {
269 pid = -1;
270 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800271 EntryBaseDropped::add(element);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800272 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700273
274 std::string formatHeader(const std::string &name, log_id_t id) const;
275 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700276};
277
278namespace android {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700279uid_t pidToUid(pid_t pid);
280}
281
282struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700283 const pid_t pid;
284 uid_t uid;
285 char *name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700286
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700287 explicit PidEntry(pid_t pid):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700288 EntryBaseDropped(),
289 pid(pid),
290 uid(android::pidToUid(pid)),
291 name(android::pidToName(pid)) {
292 }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700293 explicit PidEntry(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700294 EntryBaseDropped(element),
295 pid(element->getPid()),
296 uid(element->getUid()),
297 name(android::pidToName(pid)) {
298 }
299 PidEntry(const PidEntry &element):
300 EntryBaseDropped(element),
301 pid(element.pid),
302 uid(element.uid),
303 name(element.name ? strdup(element.name) : NULL) {
304 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700305 ~PidEntry() { free(name); }
306
307 const pid_t&getKey() const { return pid; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800308 const pid_t&getPid() const { return getKey(); }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700309 const uid_t&getUid() const { return uid; }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700310 const char*getName() const { return name; }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700311
Mark Salyzyn758058f2015-08-21 16:44:30 -0700312 inline void add(pid_t newPid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800313 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700314 free(name);
315 name = NULL;
316 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700317 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700318 name = android::pidToName(newPid);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700319 }
320 }
321
Mark Salyzyn758058f2015-08-21 16:44:30 -0700322 inline void add(LogBufferElement *element) {
323 uid_t incomingUid = element->getUid();
324 if (getUid() != incomingUid) {
325 uid = incomingUid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700326 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700327 name = android::pidToName(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700328 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700329 add(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700330 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700331 EntryBaseDropped::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700332 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700333
334 std::string formatHeader(const std::string &name, log_id_t id) const;
335 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700336};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700337
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700338struct TidEntry : public EntryBaseDropped {
339 const pid_t tid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800340 pid_t pid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700341 uid_t uid;
342 char *name;
343
Mark Salyzynee3b8382015-12-17 09:58:43 -0800344 TidEntry(pid_t tid, pid_t pid):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700345 EntryBaseDropped(),
346 tid(tid),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800347 pid(pid),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700348 uid(android::pidToUid(tid)),
349 name(android::tidToName(tid)) {
350 }
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700351 explicit TidEntry(LogBufferElement *element):
Mark Salyzyn758058f2015-08-21 16:44:30 -0700352 EntryBaseDropped(element),
353 tid(element->getTid()),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800354 pid(element->getPid()),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700355 uid(element->getUid()),
356 name(android::tidToName(tid)) {
357 }
358 TidEntry(const TidEntry &element):
359 EntryBaseDropped(element),
360 tid(element.tid),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800361 pid(element.pid),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700362 uid(element.uid),
363 name(element.name ? strdup(element.name) : NULL) {
364 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700365 ~TidEntry() { free(name); }
366
367 const pid_t&getKey() const { return tid; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800368 const pid_t&getTid() const { return getKey(); }
369 const pid_t&getPid() const { return pid; }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700370 const uid_t&getUid() const { return uid; }
371 const char*getName() const { return name; }
372
Mark Salyzyn758058f2015-08-21 16:44:30 -0700373 inline void add(pid_t incomingTid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800374 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700375 free(name);
376 name = NULL;
377 }
378 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700379 name = android::tidToName(incomingTid);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700380 }
381 }
382
Mark Salyzyn758058f2015-08-21 16:44:30 -0700383 inline void add(LogBufferElement *element) {
384 uid_t incomingUid = element->getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800385 pid_t incomingPid = element->getPid();
386 if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700387 uid = incomingUid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800388 pid = incomingPid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700389 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700390 name = android::tidToName(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700391 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700392 add(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700393 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700394 EntryBaseDropped::add(element);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700395 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700396
397 std::string formatHeader(const std::string &name, log_id_t id) const;
398 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700399};
400
Mark Salyzyn6a066942016-07-14 15:34:30 -0700401struct TagEntry : public EntryBaseDropped {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700402 const uint32_t tag;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800403 pid_t pid;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700404 uid_t uid;
405
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700406 explicit TagEntry(LogBufferElement *element):
Mark Salyzyn6a066942016-07-14 15:34:30 -0700407 EntryBaseDropped(element),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700408 tag(element->getTag()),
Mark Salyzynee3b8382015-12-17 09:58:43 -0800409 pid(element->getPid()),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700410 uid(element->getUid()) {
411 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700412
413 const uint32_t&getKey() const { return tag; }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800414 const pid_t&getPid() const { return pid; }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700415 const uid_t&getUid() const { return uid; }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700416 const char*getName(size_t &len) const { return android::tagToName(&len, tag); }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700417
Mark Salyzyn758058f2015-08-21 16:44:30 -0700418 inline void add(LogBufferElement *element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800419 if (uid != element->getUid()) {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700420 uid = -1;
421 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800422 if (pid != element->getPid()) {
423 pid = -1;
424 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800425 EntryBaseDropped::add(element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700426 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700427
428 std::string formatHeader(const std::string &name, log_id_t id) const;
429 std::string format(const LogStatistics &stat, log_id_t id) const;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700430};
431
Mark Salyzyn6a066942016-07-14 15:34:30 -0700432template <typename TEntry>
433class LogFindWorst {
434 std::unique_ptr<const TEntry *[]> sorted;
435
436public:
437
Chih-Hung Hsieh9e70ba62016-08-02 11:31:44 -0700438 explicit LogFindWorst(std::unique_ptr<const TEntry *[]> &&sorted) : sorted(std::move(sorted)) { }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700439
440 void findWorst(int &worst,
441 size_t &worst_sizes, size_t &second_worst_sizes,
442 size_t threshold) {
443 if (sorted.get() && sorted[0] && sorted[1]) {
444 worst_sizes = sorted[0]->getSizes();
445 if ((worst_sizes > threshold)
446 // Allow time horizon to extend roughly tenfold, assume
447 // average entry length is 100 characters.
448 && (worst_sizes > (10 * sorted[0]->getDropped()))) {
449 worst = sorted[0]->getKey();
450 second_worst_sizes = sorted[1]->getSizes();
451 if (second_worst_sizes < threshold) {
452 second_worst_sizes = threshold;
453 }
454 }
455 }
456 }
457
458 void findWorst(int &worst,
459 size_t worst_sizes, size_t &second_worst_sizes) {
460 if (sorted.get() && sorted[0] && sorted[1]) {
461 worst = sorted[0]->getKey();
462 second_worst_sizes = worst_sizes
463 - sorted[0]->getSizes()
464 + sorted[1]->getSizes();
465 }
466 }
467};
468
Mark Salyzyn34facab2014-02-06 14:48:50 -0800469// Log Statistics
470class LogStatistics {
Mark Salyzync723df82015-08-24 11:08:00 -0700471 friend UidEntry;
472
Mark Salyzyn34facab2014-02-06 14:48:50 -0800473 size_t mSizes[LOG_ID_MAX];
474 size_t mElements[LOG_ID_MAX];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700475 size_t mDroppedElements[LOG_ID_MAX];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700476 size_t mSizesTotal[LOG_ID_MAX];
477 size_t mElementsTotal[LOG_ID_MAX];
Mark Salyzyn32962912016-09-12 10:29:17 -0700478 static size_t SizesTotal;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700479 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800480
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700481 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700482 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700483 uidTable_t uidTable[LOG_ID_MAX];
Mark Salyzyne457b742014-02-19 17:18:31 -0800484
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700485 // pid of system to size list
486 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
487 pidSystemTable_t pidSystemTable[LOG_ID_MAX];
488
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700489 // pid to uid list
490 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
491 pidTable_t pidTable;
492
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700493 // tid to uid list
494 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
495 tidTable_t tidTable;
496
Mark Salyzyn344bff42015-04-13 14:24:45 -0700497 // tag list
498 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
499 tagTable_t tagTable;
500
Mark Salyzyn083b0372015-12-04 10:59:45 -0800501 // security tag list
502 tagTable_t securityTagTable;
503
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700504 size_t sizeOf() const {
505 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700506 tagTable.sizeOf() + securityTagTable.sizeOf() +
507 (pidTable.size() * sizeof(pidTable_t::iterator)) +
508 (tagTable.size() * sizeof(tagTable_t::iterator));
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700509 for(auto it : pidTable) {
510 const char* name = it.second.getName();
511 if (name) size += strlen(name) + 1;
512 }
513 for(auto it : tidTable) {
514 const char* name = it.second.getName();
515 if (name) size += strlen(name) + 1;
516 }
517 log_id_for_each(id) {
518 size += uidTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700519 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700520 size += pidSystemTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700521 size += pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700522 }
523 return size;
524 }
525
Mark Salyzyn34facab2014-02-06 14:48:50 -0800526public:
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700527
Mark Salyzyn34facab2014-02-06 14:48:50 -0800528 LogStatistics();
529
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700530 void enableStatistics() { enable = true; }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800531
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700532 void add(LogBufferElement *entry);
533 void subtract(LogBufferElement *entry);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700534 // entry->setDropped(1) must follow this call
535 void drop(LogBufferElement *entry);
Mark Salyzynaaad42f2015-09-30 07:40:09 -0700536 // Correct for coalescing two entries referencing dropped content
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700537 void erase(LogBufferElement *element) {
538 log_id_t log_id = element->getLogId();
539 --mElements[log_id];
540 --mDroppedElements[log_id];
541 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800542
Mark Salyzyn6a066942016-07-14 15:34:30 -0700543 LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
544 return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700545 }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700546 LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len, log_id id) {
547 return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
548 }
549 LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
550 return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700551 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800552
553 // fast track current value by id only
554 size_t sizes(log_id_t id) const { return mSizes[id]; }
555 size_t elements(log_id_t id) const { return mElements[id]; }
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700556 size_t realElements(log_id_t id) const {
557 return mElements[id] - mDroppedElements[id];
558 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700559 size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
560 size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
Mark Salyzyn32962912016-09-12 10:29:17 -0700561 static size_t sizesTotal() { return SizesTotal; }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800562
Mark Salyzynee3b8382015-12-17 09:58:43 -0800563 std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
Mark Salyzyn9a038632014-04-07 07:05:40 -0700564
Mark Salyzyned777e92015-06-24 16:22:54 -0700565 // helper (must be locked directly or implicitly by mLogElementsLock)
Mark Salyzyn758058f2015-08-21 16:44:30 -0700566 const char *pidToName(pid_t pid) const;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700567 uid_t pidToUid(pid_t pid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700568 const char *uidToName(uid_t uid) const;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800569};
570
571#endif // _LOGD_LOG_STATISTICS_H__