blob: e6f01d64d45dde5cca5bb7b3d3e90393e6099d32 [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 Salyzyn501c3732017-03-10 14:31:54 -080024#include <algorithm> // std::max
Mark Salyzynb545e1c2016-12-19 14:51:15 -080025#include <memory>
Mark Salyzyn501c3732017-03-10 14:31:54 -080026#include <string> // std::string
Mark Salyzyn511338d2015-05-19 09:12:30 -070027#include <unordered_map>
28
Elliott Hughes4f713192015-12-04 22:00:26 -080029#include <android-base/stringprintf.h>
Mark Salyzyn501c3732017-03-10 14:31:54 -080030#include <android/log.h>
Mark Salyzyn03bb7592017-04-14 09:46:57 -070031#include <log/log_time.h>
Mark Salyzyn758058f2015-08-21 16:44:30 -070032#include <private/android_filesystem_config.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070033
34#include "LogBufferElement.h"
Mark Salyzyn5ac5c6b2015-08-28 08:02:59 -070035#include "LogUtils.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080036
37#define log_id_for_each(i) \
Mark Salyzyn501c3732017-03-10 14:31:54 -080038 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 -080039
Mark Salyzyn758058f2015-08-21 16:44:30 -070040class LogStatistics;
41
Mark Salyzyn720f6d12015-03-16 08:26:05 -070042template <typename TKey, typename TEntry>
Mark Salyzyn511338d2015-05-19 09:12:30 -070043class LogHashtable {
Mark Salyzyn511338d2015-05-19 09:12:30 -070044 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 Salyzyn501c3732017-03-10 14:31:54 -080061 public:
62 size_t size() const {
63 return map.size();
64 }
Mark Salyzynb0672292016-10-06 10:09:24 -070065
Mark Salyzyn6d981af2016-10-06 09:55:21 -070066 // Estimate unordered_map memory usage.
67 size_t sizeOf() const {
68 return sizeof(*this) +
Mark Salyzynb0672292016-10-06 10:09:24 -070069 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn6d981af2016-10-06 09:55:21 -070070 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
71 }
72
Mark Salyzyn511338d2015-05-19 09:12:30 -070073 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn501c3732017-03-10 14:31:54 -080074 typedef
75 typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn511338d2015-05-19 09:12:30 -070076
Mark Salyzyn501c3732017-03-10 14:31:54 -080077 std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid,
Mark Salyzynee3b8382015-12-17 09:58:43 -080078 size_t len) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -070079 if (!len) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080080 std::unique_ptr<const TEntry* []> sorted(NULL);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070081 return sorted;
82 }
83
Mark Salyzyn501c3732017-03-10 14:31:54 -080084 const TEntry** retval = new const TEntry*[len];
Mark Salyzyn758058f2015-08-21 16:44:30 -070085 memset(retval, 0, sizeof(*retval) * len);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070086
Mark Salyzyn501c3732017-03-10 14:31:54 -080087 for (const_iterator it = map.begin(); it != map.end(); ++it) {
88 const TEntry& entry = it->second;
Mark Salyzynee3b8382015-12-17 09:58:43 -080089
90 if ((uid != AID_ROOT) && (uid != entry.getUid())) {
91 continue;
92 }
93 if (pid && entry.getPid() && (pid != entry.getPid())) {
94 continue;
95 }
96
Mark Salyzyn758058f2015-08-21 16:44:30 -070097 size_t sizes = entry.getSizes();
98 ssize_t index = len - 1;
Mark Salyzyn501c3732017-03-10 14:31:54 -080099 while ((!retval[index] || (sizes > retval[index]->getSizes())) &&
100 (--index >= 0))
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700101 ;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700102 if (++index < (ssize_t)len) {
103 size_t num = len - index - 1;
104 if (num) {
105 memmove(&retval[index + 1], &retval[index],
106 num * sizeof(retval[0]));
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700107 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700108 retval[index] = &entry;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700109 }
110 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800111 std::unique_ptr<const TEntry* []> sorted(retval);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700112 return sorted;
113 }
114
Mark Salyzyn501c3732017-03-10 14:31:54 -0800115 inline iterator add(TKey key, LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700116 iterator it = map.find(key);
117 if (it == map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700118 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn511338d2015-05-19 09:12:30 -0700119 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700120 it->second.add(element);
Mark Salyzyn511338d2015-05-19 09:12:30 -0700121 }
122 return it;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700123 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700124
Mark Salyzyn511338d2015-05-19 09:12:30 -0700125 inline iterator add(TKey key) {
126 iterator it = map.find(key);
127 if (it == map.end()) {
128 it = map.insert(std::make_pair(key, TEntry(key))).first;
129 } else {
130 it->second.add(key);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700131 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700132 return it;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700133 }
134
Mark Salyzyn501c3732017-03-10 14:31:54 -0800135 void subtract(TKey key, LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700136 iterator it = map.find(key);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700137 if ((it != map.end()) && it->second.subtract(element)) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700138 map.erase(it);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700139 }
140 }
141
Mark Salyzyn501c3732017-03-10 14:31:54 -0800142 inline void drop(TKey key, LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700143 iterator it = map.find(key);
144 if (it != map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700145 it->second.drop(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700146 }
147 }
148
Mark Salyzyn501c3732017-03-10 14:31:54 -0800149 inline iterator begin() {
150 return map.begin();
151 }
152 inline const_iterator begin() const {
153 return map.begin();
154 }
155 inline iterator end() {
156 return map.end();
157 }
158 inline const_iterator end() const {
159 return map.end();
160 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700161
Mark Salyzyn501c3732017-03-10 14:31:54 -0800162 std::string format(const LogStatistics& stat, uid_t uid, pid_t pid,
163 const std::string& name = std::string(""),
164 log_id_t id = LOG_ID_MAX) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700165 static const size_t maximum_sorted_entries = 32;
166 std::string output;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800167 std::unique_ptr<const TEntry* []> sorted =
168 sort(uid, pid, maximum_sorted_entries);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700169 if (!sorted.get()) {
170 return output;
171 }
172 bool headerPrinted = false;
173 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800174 const TEntry* entry = sorted[index];
Mark Salyzyn758058f2015-08-21 16:44:30 -0700175 if (!entry) {
176 break;
177 }
178 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
179 break;
180 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700181 if (!headerPrinted) {
182 output += "\n\n";
183 output += entry->formatHeader(name, id);
184 headerPrinted = true;
185 }
186 output += entry->format(stat, id);
187 }
188 return output;
189 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700190};
191
Mark Salyzyn758058f2015-08-21 16:44:30 -0700192namespace EntryBaseConstants {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800193static constexpr size_t pruned_len = 14;
194static constexpr size_t total_len = 80;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700195}
196
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700197struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700198 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700199
Mark Salyzyn501c3732017-03-10 14:31:54 -0800200 EntryBase() : size(0) {
201 }
202 explicit EntryBase(LogBufferElement* element) : size(element->getMsgLen()) {
203 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700204
Mark Salyzyn501c3732017-03-10 14:31:54 -0800205 size_t getSizes() const {
206 return size;
207 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700208
Mark Salyzyn501c3732017-03-10 14:31:54 -0800209 inline void add(LogBufferElement* element) {
210 size += element->getMsgLen();
211 }
212 inline bool subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700213 size -= element->getMsgLen();
214 return !size;
215 }
216
Mark Salyzyn501c3732017-03-10 14:31:54 -0800217 static std::string formatLine(const std::string& name,
218 const std::string& size,
219 const std::string& pruned) {
220 ssize_t drop_len =
221 std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
222 ssize_t size_len =
223 std::max(size.length() + 1, EntryBaseConstants::total_len -
224 name.length() - drop_len - 1);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700225
Mark Salyzyn501c3732017-03-10 14:31:54 -0800226 std::string ret = android::base::StringPrintf(
227 "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
228 (int)drop_len, pruned.c_str());
Mark Salyzynb545e1c2016-12-19 14:51:15 -0800229 // remove any trailing spaces
230 size_t pos = ret.size();
231 size_t len = 0;
232 while (pos && isspace(ret[--pos])) ++len;
233 if (len) ret.erase(pos + 1, len);
234 return ret + "\n";
Mark Salyzyn758058f2015-08-21 16:44:30 -0700235 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700236};
237
238struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700239 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800240
Mark Salyzyn501c3732017-03-10 14:31:54 -0800241 EntryBaseDropped() : dropped(0) {
242 }
243 explicit EntryBaseDropped(LogBufferElement* element)
244 : EntryBase(element), dropped(element->getDropped()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700245 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800246
Mark Salyzyn501c3732017-03-10 14:31:54 -0800247 size_t getDropped() const {
248 return dropped;
249 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700250
Mark Salyzyn501c3732017-03-10 14:31:54 -0800251 inline void add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700252 dropped += element->getDropped();
253 EntryBase::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700254 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800255 inline bool subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700256 dropped -= element->getDropped();
257 return EntryBase::subtract(element) && !dropped;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700258 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800259 inline void drop(LogBufferElement* element) {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700260 dropped += 1;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700261 EntryBase::subtract(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700262 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800263};
264
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700265struct UidEntry : public EntryBaseDropped {
266 const uid_t uid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800267 pid_t pid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700268
Mark Salyzyn501c3732017-03-10 14:31:54 -0800269 explicit UidEntry(LogBufferElement* element)
270 : EntryBaseDropped(element),
271 uid(element->getUid()),
272 pid(element->getPid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700273 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700274
Mark Salyzyn501c3732017-03-10 14:31:54 -0800275 inline const uid_t& getKey() const {
276 return uid;
277 }
278 inline const uid_t& getUid() const {
279 return getKey();
280 }
281 inline const pid_t& getPid() const {
282 return pid;
283 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800284
Mark Salyzyn501c3732017-03-10 14:31:54 -0800285 inline void add(LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800286 if (pid != element->getPid()) {
287 pid = -1;
288 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800289 EntryBaseDropped::add(element);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800290 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700291
Mark Salyzyn501c3732017-03-10 14:31:54 -0800292 std::string formatHeader(const std::string& name, log_id_t id) const;
293 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700294};
295
296namespace android {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700297uid_t pidToUid(pid_t pid);
298}
299
300struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700301 const pid_t pid;
302 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800303 char* name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700304
Mark Salyzyn501c3732017-03-10 14:31:54 -0800305 explicit PidEntry(pid_t pid)
306 : EntryBaseDropped(),
307 pid(pid),
308 uid(android::pidToUid(pid)),
309 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700310 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800311 explicit PidEntry(LogBufferElement* element)
312 : EntryBaseDropped(element),
313 pid(element->getPid()),
314 uid(element->getUid()),
315 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700316 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800317 PidEntry(const PidEntry& element)
318 : EntryBaseDropped(element),
319 pid(element.pid),
320 uid(element.uid),
321 name(element.name ? strdup(element.name) : NULL) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700322 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800323 ~PidEntry() {
324 free(name);
325 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700326
Mark Salyzyn501c3732017-03-10 14:31:54 -0800327 const pid_t& getKey() const {
328 return pid;
329 }
330 const pid_t& getPid() const {
331 return getKey();
332 }
333 const uid_t& getUid() const {
334 return uid;
335 }
336 const char* getName() const {
337 return name;
338 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700339
Mark Salyzyn758058f2015-08-21 16:44:30 -0700340 inline void add(pid_t newPid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800341 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700342 free(name);
343 name = NULL;
344 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700345 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700346 name = android::pidToName(newPid);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700347 }
348 }
349
Mark Salyzyn501c3732017-03-10 14:31:54 -0800350 inline void add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700351 uid_t incomingUid = element->getUid();
352 if (getUid() != incomingUid) {
353 uid = incomingUid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700354 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700355 name = android::pidToName(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700356 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700357 add(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700358 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700359 EntryBaseDropped::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700360 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700361
Mark Salyzyn501c3732017-03-10 14:31:54 -0800362 std::string formatHeader(const std::string& name, log_id_t id) const;
363 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700364};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700365
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700366struct TidEntry : public EntryBaseDropped {
367 const pid_t tid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800368 pid_t pid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700369 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800370 char* name;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700371
Mark Salyzyn501c3732017-03-10 14:31:54 -0800372 TidEntry(pid_t tid, pid_t pid)
373 : EntryBaseDropped(),
374 tid(tid),
375 pid(pid),
376 uid(android::pidToUid(tid)),
377 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700378 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800379 explicit TidEntry(LogBufferElement* element)
380 : EntryBaseDropped(element),
381 tid(element->getTid()),
382 pid(element->getPid()),
383 uid(element->getUid()),
384 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700385 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800386 TidEntry(const TidEntry& element)
387 : EntryBaseDropped(element),
388 tid(element.tid),
389 pid(element.pid),
390 uid(element.uid),
391 name(element.name ? strdup(element.name) : NULL) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700392 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800393 ~TidEntry() {
394 free(name);
395 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700396
Mark Salyzyn501c3732017-03-10 14:31:54 -0800397 const pid_t& getKey() const {
398 return tid;
399 }
400 const pid_t& getTid() const {
401 return getKey();
402 }
403 const pid_t& getPid() const {
404 return pid;
405 }
406 const uid_t& getUid() const {
407 return uid;
408 }
409 const char* getName() const {
410 return name;
411 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700412
Mark Salyzyn758058f2015-08-21 16:44:30 -0700413 inline void add(pid_t incomingTid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800414 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700415 free(name);
416 name = NULL;
417 }
418 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700419 name = android::tidToName(incomingTid);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700420 }
421 }
422
Mark Salyzyn501c3732017-03-10 14:31:54 -0800423 inline void add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700424 uid_t incomingUid = element->getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800425 pid_t incomingPid = element->getPid();
426 if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700427 uid = incomingUid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800428 pid = incomingPid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700429 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700430 name = android::tidToName(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700431 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700432 add(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700433 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700434 EntryBaseDropped::add(element);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700435 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700436
Mark Salyzyn501c3732017-03-10 14:31:54 -0800437 std::string formatHeader(const std::string& name, log_id_t id) const;
438 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700439};
440
Mark Salyzyn6a066942016-07-14 15:34:30 -0700441struct TagEntry : public EntryBaseDropped {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700442 const uint32_t tag;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800443 pid_t pid;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700444 uid_t uid;
445
Mark Salyzyn501c3732017-03-10 14:31:54 -0800446 explicit TagEntry(LogBufferElement* element)
447 : EntryBaseDropped(element),
448 tag(element->getTag()),
449 pid(element->getPid()),
450 uid(element->getUid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700451 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700452
Mark Salyzyn501c3732017-03-10 14:31:54 -0800453 const uint32_t& getKey() const {
454 return tag;
455 }
456 const pid_t& getPid() const {
457 return pid;
458 }
459 const uid_t& getUid() const {
460 return uid;
461 }
462 const char* getName() const {
463 return android::tagToName(tag);
464 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700465
Mark Salyzyn501c3732017-03-10 14:31:54 -0800466 inline void add(LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800467 if (uid != element->getUid()) {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700468 uid = -1;
469 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800470 if (pid != element->getPid()) {
471 pid = -1;
472 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800473 EntryBaseDropped::add(element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700474 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700475
Mark Salyzyn501c3732017-03-10 14:31:54 -0800476 std::string formatHeader(const std::string& name, log_id_t id) const;
477 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700478};
479
Mark Salyzyn6a066942016-07-14 15:34:30 -0700480template <typename TEntry>
481class LogFindWorst {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800482 std::unique_ptr<const TEntry* []> sorted;
Mark Salyzyn6a066942016-07-14 15:34:30 -0700483
Mark Salyzyn501c3732017-03-10 14:31:54 -0800484 public:
485 explicit LogFindWorst(std::unique_ptr<const TEntry* []>&& sorted)
486 : sorted(std::move(sorted)) {
487 }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700488
Mark Salyzyn501c3732017-03-10 14:31:54 -0800489 void findWorst(int& worst, size_t& worst_sizes, size_t& second_worst_sizes,
490 size_t threshold) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700491 if (sorted.get() && sorted[0] && sorted[1]) {
492 worst_sizes = sorted[0]->getSizes();
493 if ((worst_sizes > threshold)
494 // Allow time horizon to extend roughly tenfold, assume
495 // average entry length is 100 characters.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800496 && (worst_sizes > (10 * sorted[0]->getDropped()))) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700497 worst = sorted[0]->getKey();
498 second_worst_sizes = sorted[1]->getSizes();
499 if (second_worst_sizes < threshold) {
500 second_worst_sizes = threshold;
501 }
502 }
503 }
504 }
505
Mark Salyzyn501c3732017-03-10 14:31:54 -0800506 void findWorst(int& worst, size_t worst_sizes, size_t& second_worst_sizes) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700507 if (sorted.get() && sorted[0] && sorted[1]) {
508 worst = sorted[0]->getKey();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800509 second_worst_sizes =
510 worst_sizes - sorted[0]->getSizes() + sorted[1]->getSizes();
Mark Salyzyn6a066942016-07-14 15:34:30 -0700511 }
512 }
513};
514
Mark Salyzyn34facab2014-02-06 14:48:50 -0800515// Log Statistics
516class LogStatistics {
Mark Salyzync723df82015-08-24 11:08:00 -0700517 friend UidEntry;
518
Mark Salyzyn34facab2014-02-06 14:48:50 -0800519 size_t mSizes[LOG_ID_MAX];
520 size_t mElements[LOG_ID_MAX];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700521 size_t mDroppedElements[LOG_ID_MAX];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700522 size_t mSizesTotal[LOG_ID_MAX];
523 size_t mElementsTotal[LOG_ID_MAX];
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700524 log_time mOldest[LOG_ID_MAX];
525 log_time mNewest[LOG_ID_MAX];
526 log_time mNewestDropped[LOG_ID_MAX];
Mark Salyzyn32962912016-09-12 10:29:17 -0700527 static size_t SizesTotal;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700528 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800529
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700530 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700531 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700532 uidTable_t uidTable[LOG_ID_MAX];
Mark Salyzyne457b742014-02-19 17:18:31 -0800533
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700534 // pid of system to size list
535 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
536 pidSystemTable_t pidSystemTable[LOG_ID_MAX];
537
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700538 // pid to uid list
539 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
540 pidTable_t pidTable;
541
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700542 // tid to uid list
543 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
544 tidTable_t tidTable;
545
Mark Salyzyn344bff42015-04-13 14:24:45 -0700546 // tag list
547 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
548 tagTable_t tagTable;
549
Mark Salyzyn083b0372015-12-04 10:59:45 -0800550 // security tag list
551 tagTable_t securityTagTable;
552
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700553 size_t sizeOf() const {
554 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700555 tagTable.sizeOf() + securityTagTable.sizeOf() +
556 (pidTable.size() * sizeof(pidTable_t::iterator)) +
557 (tagTable.size() * sizeof(tagTable_t::iterator));
Mark Salyzyn501c3732017-03-10 14:31:54 -0800558 for (auto it : pidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700559 const char* name = it.second.getName();
560 if (name) size += strlen(name) + 1;
561 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800562 for (auto it : tidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700563 const char* name = it.second.getName();
564 if (name) size += strlen(name) + 1;
565 }
566 log_id_for_each(id) {
567 size += uidTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700568 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700569 size += pidSystemTable[id].sizeOf();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800570 size +=
571 pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700572 }
573 return size;
574 }
575
Mark Salyzyn501c3732017-03-10 14:31:54 -0800576 public:
Mark Salyzyn34facab2014-02-06 14:48:50 -0800577 LogStatistics();
578
Mark Salyzyn501c3732017-03-10 14:31:54 -0800579 void enableStatistics() {
580 enable = true;
581 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800582
Mark Salyzyn02dd2f42017-04-14 09:46:57 -0700583 void addTotal(LogBufferElement* entry);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800584 void add(LogBufferElement* entry);
585 void subtract(LogBufferElement* entry);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700586 // entry->setDropped(1) must follow this call
Mark Salyzyn501c3732017-03-10 14:31:54 -0800587 void drop(LogBufferElement* entry);
Mark Salyzynaaad42f2015-09-30 07:40:09 -0700588 // Correct for coalescing two entries referencing dropped content
Mark Salyzyn501c3732017-03-10 14:31:54 -0800589 void erase(LogBufferElement* element) {
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700590 log_id_t log_id = element->getLogId();
591 --mElements[log_id];
592 --mDroppedElements[log_id];
593 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800594
Mark Salyzyn6a066942016-07-14 15:34:30 -0700595 LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
596 return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700597 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800598 LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len,
599 log_id id) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700600 return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
601 }
602 LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
603 return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700604 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800605
606 // fast track current value by id only
Mark Salyzyn501c3732017-03-10 14:31:54 -0800607 size_t sizes(log_id_t id) const {
608 return mSizes[id];
609 }
610 size_t elements(log_id_t id) const {
611 return mElements[id];
612 }
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700613 size_t realElements(log_id_t id) const {
614 return mElements[id] - mDroppedElements[id];
615 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800616 size_t sizesTotal(log_id_t id) const {
617 return mSizesTotal[id];
618 }
619 size_t elementsTotal(log_id_t id) const {
620 return mElementsTotal[id];
621 }
622 static size_t sizesTotal() {
623 return SizesTotal;
624 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800625
Mark Salyzynee3b8382015-12-17 09:58:43 -0800626 std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
Mark Salyzyn9a038632014-04-07 07:05:40 -0700627
Mark Salyzyned777e92015-06-24 16:22:54 -0700628 // helper (must be locked directly or implicitly by mLogElementsLock)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800629 const char* pidToName(pid_t pid) const;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700630 uid_t pidToUid(pid_t pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800631 const char* uidToName(uid_t uid) const;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800632};
633
Mark Salyzyn501c3732017-03-10 14:31:54 -0800634#endif // _LOGD_LOG_STATISTICS_H__