blob: 945fc0ab6ee90b4aff31a0ccc9df369314eafd06 [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 Salyzynf99a7d62017-04-19 14:39:21 -070021#include <inttypes.h>
22#include <stdint.h>
Mark Salyzyn720f6d12015-03-16 08:26:05 -070023#include <stdlib.h>
Mark Salyzynf99a7d62017-04-19 14:39:21 -070024#include <string.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080025#include <sys/types.h>
26
Mark Salyzyn501c3732017-03-10 14:31:54 -080027#include <algorithm> // std::max
Mark Salyzynf99a7d62017-04-19 14:39:21 -070028#include <experimental/string_view>
Mark Salyzynb545e1c2016-12-19 14:51:15 -080029#include <memory>
Mark Salyzyn501c3732017-03-10 14:31:54 -080030#include <string> // std::string
Mark Salyzyn511338d2015-05-19 09:12:30 -070031#include <unordered_map>
32
Elliott Hughes4f713192015-12-04 22:00:26 -080033#include <android-base/stringprintf.h>
Mark Salyzyn501c3732017-03-10 14:31:54 -080034#include <android/log.h>
Mark Salyzyn03bb7592017-04-14 09:46:57 -070035#include <log/log_time.h>
Mark Salyzyn758058f2015-08-21 16:44:30 -070036#include <private/android_filesystem_config.h>
Mark Salyzynf99a7d62017-04-19 14:39:21 -070037#include <utils/FastStrcmp.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070038
39#include "LogBufferElement.h"
Mark Salyzyn5ac5c6b2015-08-28 08:02:59 -070040#include "LogUtils.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080041
42#define log_id_for_each(i) \
Mark Salyzyn501c3732017-03-10 14:31:54 -080043 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 -080044
Mark Salyzyn758058f2015-08-21 16:44:30 -070045class LogStatistics;
46
Mark Salyzyn720f6d12015-03-16 08:26:05 -070047template <typename TKey, typename TEntry>
Mark Salyzyn511338d2015-05-19 09:12:30 -070048class LogHashtable {
Mark Salyzyn511338d2015-05-19 09:12:30 -070049 std::unordered_map<TKey, TEntry> map;
50
Mark Salyzyn6d981af2016-10-06 09:55:21 -070051 size_t bucket_size() const {
52 size_t count = 0;
53 for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
54 size_t bucket_size = map.bucket_size(idx);
55 if (bucket_size == 0) bucket_size = 1;
56 count += bucket_size;
57 }
58 float load_factor = map.max_load_factor();
59 if (load_factor < 1.0) return count;
60 return count * load_factor;
61 }
62
63 static const size_t unordered_map_per_entry_overhead = sizeof(void*);
64 static const size_t unordered_map_bucket_overhead = sizeof(void*);
65
Mark Salyzyn501c3732017-03-10 14:31:54 -080066 public:
67 size_t size() const {
68 return map.size();
69 }
Mark Salyzynb0672292016-10-06 10:09:24 -070070
Mark Salyzyn6d981af2016-10-06 09:55:21 -070071 // Estimate unordered_map memory usage.
72 size_t sizeOf() const {
73 return sizeof(*this) +
Mark Salyzynb0672292016-10-06 10:09:24 -070074 (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
Mark Salyzyn6d981af2016-10-06 09:55:21 -070075 (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
76 }
77
Mark Salyzyn511338d2015-05-19 09:12:30 -070078 typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
Mark Salyzyn501c3732017-03-10 14:31:54 -080079 typedef
80 typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
Mark Salyzyn511338d2015-05-19 09:12:30 -070081
Mark Salyzyn501c3732017-03-10 14:31:54 -080082 std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid,
Mark Salyzynee3b8382015-12-17 09:58:43 -080083 size_t len) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -070084 if (!len) {
Mark Salyzynf99a7d62017-04-19 14:39:21 -070085 std::unique_ptr<const TEntry* []> sorted(nullptr);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070086 return sorted;
87 }
88
Mark Salyzyn501c3732017-03-10 14:31:54 -080089 const TEntry** retval = new const TEntry*[len];
Mark Salyzyn758058f2015-08-21 16:44:30 -070090 memset(retval, 0, sizeof(*retval) * len);
Mark Salyzyn720f6d12015-03-16 08:26:05 -070091
Mark Salyzyn501c3732017-03-10 14:31:54 -080092 for (const_iterator it = map.begin(); it != map.end(); ++it) {
93 const TEntry& entry = it->second;
Mark Salyzynee3b8382015-12-17 09:58:43 -080094
95 if ((uid != AID_ROOT) && (uid != entry.getUid())) {
96 continue;
97 }
98 if (pid && entry.getPid() && (pid != entry.getPid())) {
99 continue;
100 }
101
Mark Salyzyn758058f2015-08-21 16:44:30 -0700102 size_t sizes = entry.getSizes();
103 ssize_t index = len - 1;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800104 while ((!retval[index] || (sizes > retval[index]->getSizes())) &&
105 (--index >= 0))
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700106 ;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700107 if (++index < (ssize_t)len) {
108 size_t num = len - index - 1;
109 if (num) {
110 memmove(&retval[index + 1], &retval[index],
111 num * sizeof(retval[0]));
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700112 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700113 retval[index] = &entry;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700114 }
115 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800116 std::unique_ptr<const TEntry* []> sorted(retval);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700117 return sorted;
118 }
119
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700120 inline iterator add(const TKey& key, const LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700121 iterator it = map.find(key);
122 if (it == map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700123 it = map.insert(std::make_pair(key, TEntry(element))).first;
Mark Salyzyn511338d2015-05-19 09:12:30 -0700124 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700125 it->second.add(element);
Mark Salyzyn511338d2015-05-19 09:12:30 -0700126 }
127 return it;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700128 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700129
Mark Salyzyn511338d2015-05-19 09:12:30 -0700130 inline iterator add(TKey key) {
131 iterator it = map.find(key);
132 if (it == map.end()) {
133 it = map.insert(std::make_pair(key, TEntry(key))).first;
134 } else {
135 it->second.add(key);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700136 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700137 return it;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700138 }
139
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700140 void subtract(TKey&& key, const LogBufferElement* element) {
141 iterator it = map.find(std::move(key));
142 if ((it != map.end()) && it->second.subtract(element)) {
143 map.erase(it);
144 }
145 }
146
147 void subtract(const TKey& key, const LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700148 iterator it = map.find(key);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700149 if ((it != map.end()) && it->second.subtract(element)) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700150 map.erase(it);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700151 }
152 }
153
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700154 inline void drop(TKey key, const LogBufferElement* element) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700155 iterator it = map.find(key);
156 if (it != map.end()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700157 it->second.drop(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700158 }
159 }
160
Mark Salyzyn501c3732017-03-10 14:31:54 -0800161 inline iterator begin() {
162 return map.begin();
163 }
164 inline const_iterator begin() const {
165 return map.begin();
166 }
167 inline iterator end() {
168 return map.end();
169 }
170 inline const_iterator end() const {
171 return map.end();
172 }
Mark Salyzyn511338d2015-05-19 09:12:30 -0700173
Mark Salyzyn501c3732017-03-10 14:31:54 -0800174 std::string format(const LogStatistics& stat, uid_t uid, pid_t pid,
175 const std::string& name = std::string(""),
176 log_id_t id = LOG_ID_MAX) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700177 static const size_t maximum_sorted_entries = 32;
178 std::string output;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800179 std::unique_ptr<const TEntry* []> sorted =
180 sort(uid, pid, maximum_sorted_entries);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700181 if (!sorted.get()) {
182 return output;
183 }
184 bool headerPrinted = false;
185 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800186 const TEntry* entry = sorted[index];
Mark Salyzyn758058f2015-08-21 16:44:30 -0700187 if (!entry) {
188 break;
189 }
190 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
191 break;
192 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700193 if (!headerPrinted) {
194 output += "\n\n";
195 output += entry->formatHeader(name, id);
196 headerPrinted = true;
197 }
198 output += entry->format(stat, id);
199 }
200 return output;
201 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700202};
203
Mark Salyzyn758058f2015-08-21 16:44:30 -0700204namespace EntryBaseConstants {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800205static constexpr size_t pruned_len = 14;
206static constexpr size_t total_len = 80;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700207}
208
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700209struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700210 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700211
Mark Salyzyn501c3732017-03-10 14:31:54 -0800212 EntryBase() : size(0) {
213 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700214 explicit EntryBase(const LogBufferElement* element)
215 : size(element->getMsgLen()) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800216 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700217
Mark Salyzyn501c3732017-03-10 14:31:54 -0800218 size_t getSizes() const {
219 return size;
220 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700221
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700222 inline void add(const LogBufferElement* element) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800223 size += element->getMsgLen();
224 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700225 inline bool subtract(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700226 size -= element->getMsgLen();
227 return !size;
228 }
229
Mark Salyzyn501c3732017-03-10 14:31:54 -0800230 static std::string formatLine(const std::string& name,
231 const std::string& size,
232 const std::string& pruned) {
233 ssize_t drop_len =
234 std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
235 ssize_t size_len =
236 std::max(size.length() + 1, EntryBaseConstants::total_len -
237 name.length() - drop_len - 1);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700238
Mark Salyzyn501c3732017-03-10 14:31:54 -0800239 std::string ret = android::base::StringPrintf(
240 "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
241 (int)drop_len, pruned.c_str());
Mark Salyzynb545e1c2016-12-19 14:51:15 -0800242 // remove any trailing spaces
243 size_t pos = ret.size();
244 size_t len = 0;
245 while (pos && isspace(ret[--pos])) ++len;
246 if (len) ret.erase(pos + 1, len);
247 return ret + "\n";
Mark Salyzyn758058f2015-08-21 16:44:30 -0700248 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700249};
250
251struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700252 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800253
Mark Salyzyn501c3732017-03-10 14:31:54 -0800254 EntryBaseDropped() : dropped(0) {
255 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700256 explicit EntryBaseDropped(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800257 : EntryBase(element), dropped(element->getDropped()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700258 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800259
Mark Salyzyn501c3732017-03-10 14:31:54 -0800260 size_t getDropped() const {
261 return dropped;
262 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700263
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700264 inline void add(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700265 dropped += element->getDropped();
266 EntryBase::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700267 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700268 inline bool subtract(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700269 dropped -= element->getDropped();
270 return EntryBase::subtract(element) && !dropped;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700271 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700272 inline void drop(const LogBufferElement* element) {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700273 dropped += 1;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700274 EntryBase::subtract(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700275 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800276};
277
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700278struct UidEntry : public EntryBaseDropped {
279 const uid_t uid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800280 pid_t pid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700281
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700282 explicit UidEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800283 : EntryBaseDropped(element),
284 uid(element->getUid()),
285 pid(element->getPid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700286 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700287
Mark Salyzyn501c3732017-03-10 14:31:54 -0800288 inline const uid_t& getKey() const {
289 return uid;
290 }
291 inline const uid_t& getUid() const {
292 return getKey();
293 }
294 inline const pid_t& getPid() const {
295 return pid;
296 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800297
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700298 inline void add(const LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800299 if (pid != element->getPid()) {
300 pid = -1;
301 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800302 EntryBaseDropped::add(element);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800303 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700304
Mark Salyzyn501c3732017-03-10 14:31:54 -0800305 std::string formatHeader(const std::string& name, log_id_t id) const;
306 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700307};
308
309namespace android {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700310uid_t pidToUid(pid_t pid);
311}
312
313struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700314 const pid_t pid;
315 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800316 char* name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700317
Mark Salyzyn501c3732017-03-10 14:31:54 -0800318 explicit PidEntry(pid_t pid)
319 : EntryBaseDropped(),
320 pid(pid),
321 uid(android::pidToUid(pid)),
322 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700323 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700324 explicit PidEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800325 : EntryBaseDropped(element),
326 pid(element->getPid()),
327 uid(element->getUid()),
328 name(android::pidToName(pid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700329 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800330 PidEntry(const PidEntry& element)
331 : EntryBaseDropped(element),
332 pid(element.pid),
333 uid(element.uid),
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700334 name(element.name ? strdup(element.name) : nullptr) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700335 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800336 ~PidEntry() {
337 free(name);
338 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700339
Mark Salyzyn501c3732017-03-10 14:31:54 -0800340 const pid_t& getKey() const {
341 return pid;
342 }
343 const pid_t& getPid() const {
344 return getKey();
345 }
346 const uid_t& getUid() const {
347 return uid;
348 }
349 const char* getName() const {
350 return name;
351 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700352
Mark Salyzyn758058f2015-08-21 16:44:30 -0700353 inline void add(pid_t newPid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800354 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700355 free(name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700356 name = nullptr;
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700357 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700358 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700359 name = android::pidToName(newPid);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700360 }
361 }
362
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700363 inline void add(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700364 uid_t incomingUid = element->getUid();
365 if (getUid() != incomingUid) {
366 uid = incomingUid;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700367 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700368 name = android::pidToName(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700369 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700370 add(element->getPid());
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700371 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700372 EntryBaseDropped::add(element);
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700373 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700374
Mark Salyzyn501c3732017-03-10 14:31:54 -0800375 std::string formatHeader(const std::string& name, log_id_t id) const;
376 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700377};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700378
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700379struct TidEntry : public EntryBaseDropped {
380 const pid_t tid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800381 pid_t pid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700382 uid_t uid;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800383 char* name;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700384
Mark Salyzyn501c3732017-03-10 14:31:54 -0800385 TidEntry(pid_t tid, pid_t pid)
386 : EntryBaseDropped(),
387 tid(tid),
388 pid(pid),
389 uid(android::pidToUid(tid)),
390 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700391 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700392 explicit TidEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800393 : EntryBaseDropped(element),
394 tid(element->getTid()),
395 pid(element->getPid()),
396 uid(element->getUid()),
397 name(android::tidToName(tid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700398 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800399 TidEntry(const TidEntry& element)
400 : EntryBaseDropped(element),
401 tid(element.tid),
402 pid(element.pid),
403 uid(element.uid),
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700404 name(element.name ? strdup(element.name) : nullptr) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700405 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800406 ~TidEntry() {
407 free(name);
408 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700409
Mark Salyzyn501c3732017-03-10 14:31:54 -0800410 const pid_t& getKey() const {
411 return tid;
412 }
413 const pid_t& getTid() const {
414 return getKey();
415 }
416 const pid_t& getPid() const {
417 return pid;
418 }
419 const uid_t& getUid() const {
420 return uid;
421 }
422 const char* getName() const {
423 return name;
424 }
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700425
Mark Salyzyn758058f2015-08-21 16:44:30 -0700426 inline void add(pid_t incomingTid) {
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800427 if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700428 free(name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700429 name = nullptr;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700430 }
431 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700432 name = android::tidToName(incomingTid);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700433 }
434 }
435
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700436 inline void add(const LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700437 uid_t incomingUid = element->getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800438 pid_t incomingPid = element->getPid();
439 if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700440 uid = incomingUid;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800441 pid = incomingPid;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700442 free(name);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700443 name = android::tidToName(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700444 } else {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700445 add(element->getTid());
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700446 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700447 EntryBaseDropped::add(element);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700448 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700449
Mark Salyzyn501c3732017-03-10 14:31:54 -0800450 std::string formatHeader(const std::string& name, log_id_t id) const;
451 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700452};
453
Mark Salyzyn6a066942016-07-14 15:34:30 -0700454struct TagEntry : public EntryBaseDropped {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700455 const uint32_t tag;
Mark Salyzynee3b8382015-12-17 09:58:43 -0800456 pid_t pid;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700457 uid_t uid;
458
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700459 explicit TagEntry(const LogBufferElement* element)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800460 : EntryBaseDropped(element),
461 tag(element->getTag()),
462 pid(element->getPid()),
463 uid(element->getUid()) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700464 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700465
Mark Salyzyn501c3732017-03-10 14:31:54 -0800466 const uint32_t& getKey() const {
467 return tag;
468 }
469 const pid_t& getPid() const {
470 return pid;
471 }
472 const uid_t& getUid() const {
473 return uid;
474 }
475 const char* getName() const {
476 return android::tagToName(tag);
477 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700478
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700479 inline void add(const LogBufferElement* element) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800480 if (uid != element->getUid()) {
Mark Salyzyn344bff42015-04-13 14:24:45 -0700481 uid = -1;
482 }
Mark Salyzynee3b8382015-12-17 09:58:43 -0800483 if (pid != element->getPid()) {
484 pid = -1;
485 }
Mark Salyzyna2c02222016-12-13 10:31:29 -0800486 EntryBaseDropped::add(element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700487 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700488
Mark Salyzyn501c3732017-03-10 14:31:54 -0800489 std::string formatHeader(const std::string& name, log_id_t id) const;
490 std::string format(const LogStatistics& stat, log_id_t id) const;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700491};
492
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700493struct TagNameKey {
494 std::string* alloc;
495 std::experimental::string_view name; // Saves space if const char*
496
497 explicit TagNameKey(const LogBufferElement* element)
498 : alloc(nullptr), name("", strlen("")) {
499 if (element->isBinary()) {
500 uint32_t tag = element->getTag();
501 if (tag) {
502 const char* cp = android::tagToName(tag);
503 if (cp) {
504 name = std::experimental::string_view(cp, strlen(cp));
505 return;
506 }
507 }
508 alloc = new std::string(
509 android::base::StringPrintf("[%" PRIu32 "]", tag));
510 if (!alloc) return;
511 name = std::experimental::string_view(alloc->c_str(), alloc->size());
512 return;
513 }
514 const char* msg = element->getMsg();
515 if (!msg) {
516 name = std::experimental::string_view("chatty", strlen("chatty"));
517 return;
518 }
519 ++msg;
520 unsigned short len = element->getMsgLen();
521 len = (len <= 1) ? 0 : strnlen(msg, len - 1);
522 if (!len) {
523 name = std::experimental::string_view("<NULL>", strlen("<NULL>"));
524 return;
525 }
526 alloc = new std::string(msg, len);
527 if (!alloc) return;
528 name = std::experimental::string_view(alloc->c_str(), alloc->size());
529 }
530
531 explicit TagNameKey(TagNameKey&& rval)
532 : alloc(rval.alloc), name(rval.name.data(), rval.name.length()) {
533 rval.alloc = nullptr;
534 }
535
536 explicit TagNameKey(const TagNameKey& rval)
537 : alloc(rval.alloc ? new std::string(*rval.alloc) : nullptr),
538 name(alloc ? alloc->data() : rval.name.data(), rval.name.length()) {
539 }
540
541 ~TagNameKey() {
542 if (alloc) delete alloc;
543 }
544
545 operator const std::experimental::string_view() const {
546 return name;
547 }
548
549 const char* data() const {
550 return name.data();
551 }
552 size_t length() const {
553 return name.length();
554 }
555
556 bool operator==(const TagNameKey& rval) const {
557 if (length() != rval.length()) return false;
558 if (length() == 0) return true;
559 return fastcmp<strncmp>(data(), rval.data(), length()) == 0;
560 }
561 bool operator!=(const TagNameKey& rval) const {
562 return !(*this == rval);
563 }
564
565 size_t getAllocLength() const {
566 return alloc ? alloc->length() + 1 + sizeof(std::string) : 0;
567 }
568};
569
570// Hash for TagNameKey
571template <>
572struct std::hash<TagNameKey>
573 : public std::unary_function<const TagNameKey&, size_t> {
574 size_t operator()(const TagNameKey& __t) const noexcept {
575 if (!__t.length()) return 0;
576 return std::hash<std::experimental::string_view>()(
577 std::experimental::string_view(__t));
578 }
579};
580
581struct TagNameEntry : public EntryBase {
582 pid_t tid;
583 pid_t pid;
584 uid_t uid;
585 TagNameKey name;
586
587 explicit TagNameEntry(const LogBufferElement* element)
588 : EntryBase(element),
589 tid(element->getTid()),
590 pid(element->getPid()),
591 uid(element->getUid()),
592 name(element) {
593 }
594
595 const TagNameKey& getKey() const {
596 return name;
597 }
598 const pid_t& getTid() const {
599 return tid;
600 }
601 const pid_t& getPid() const {
602 return pid;
603 }
604 const uid_t& getUid() const {
605 return uid;
606 }
607 const char* getName() const {
608 return name.data();
609 }
610 size_t getNameAllocLength() const {
611 return name.getAllocLength();
612 }
613
614 inline void add(const LogBufferElement* element) {
615 if (uid != element->getUid()) {
616 uid = -1;
617 }
618 if (pid != element->getPid()) {
619 pid = -1;
620 }
621 if (tid != element->getTid()) {
622 tid = -1;
623 }
624 EntryBase::add(element);
625 }
626
627 std::string formatHeader(const std::string& name, log_id_t id) const;
628 std::string format(const LogStatistics& stat, log_id_t id) const;
629};
630
Mark Salyzyn6a066942016-07-14 15:34:30 -0700631template <typename TEntry>
632class LogFindWorst {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800633 std::unique_ptr<const TEntry* []> sorted;
Mark Salyzyn6a066942016-07-14 15:34:30 -0700634
Mark Salyzyn501c3732017-03-10 14:31:54 -0800635 public:
636 explicit LogFindWorst(std::unique_ptr<const TEntry* []>&& sorted)
637 : sorted(std::move(sorted)) {
638 }
Mark Salyzyn6a066942016-07-14 15:34:30 -0700639
Mark Salyzyn501c3732017-03-10 14:31:54 -0800640 void findWorst(int& worst, size_t& worst_sizes, size_t& second_worst_sizes,
641 size_t threshold) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700642 if (sorted.get() && sorted[0] && sorted[1]) {
643 worst_sizes = sorted[0]->getSizes();
644 if ((worst_sizes > threshold)
645 // Allow time horizon to extend roughly tenfold, assume
646 // average entry length is 100 characters.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800647 && (worst_sizes > (10 * sorted[0]->getDropped()))) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700648 worst = sorted[0]->getKey();
649 second_worst_sizes = sorted[1]->getSizes();
650 if (second_worst_sizes < threshold) {
651 second_worst_sizes = threshold;
652 }
653 }
654 }
655 }
656
Mark Salyzyn501c3732017-03-10 14:31:54 -0800657 void findWorst(int& worst, size_t worst_sizes, size_t& second_worst_sizes) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700658 if (sorted.get() && sorted[0] && sorted[1]) {
659 worst = sorted[0]->getKey();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800660 second_worst_sizes =
661 worst_sizes - sorted[0]->getSizes() + sorted[1]->getSizes();
Mark Salyzyn6a066942016-07-14 15:34:30 -0700662 }
663 }
664};
665
Mark Salyzyn34facab2014-02-06 14:48:50 -0800666// Log Statistics
667class LogStatistics {
Mark Salyzync723df82015-08-24 11:08:00 -0700668 friend UidEntry;
669
Mark Salyzyn34facab2014-02-06 14:48:50 -0800670 size_t mSizes[LOG_ID_MAX];
671 size_t mElements[LOG_ID_MAX];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700672 size_t mDroppedElements[LOG_ID_MAX];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700673 size_t mSizesTotal[LOG_ID_MAX];
674 size_t mElementsTotal[LOG_ID_MAX];
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700675 log_time mOldest[LOG_ID_MAX];
676 log_time mNewest[LOG_ID_MAX];
677 log_time mNewestDropped[LOG_ID_MAX];
Mark Salyzyn32962912016-09-12 10:29:17 -0700678 static size_t SizesTotal;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700679 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800680
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700681 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700682 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700683 uidTable_t uidTable[LOG_ID_MAX];
Mark Salyzyne457b742014-02-19 17:18:31 -0800684
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700685 // pid of system to size list
686 typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
687 pidSystemTable_t pidSystemTable[LOG_ID_MAX];
688
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700689 // pid to uid list
690 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
691 pidTable_t pidTable;
692
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700693 // tid to uid list
694 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
695 tidTable_t tidTable;
696
Mark Salyzyn344bff42015-04-13 14:24:45 -0700697 // tag list
698 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
699 tagTable_t tagTable;
700
Mark Salyzyn083b0372015-12-04 10:59:45 -0800701 // security tag list
702 tagTable_t securityTagTable;
703
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700704 // global tag list
705 typedef LogHashtable<TagNameKey, TagNameEntry> tagNameTable_t;
706 tagNameTable_t tagNameTable;
707
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700708 size_t sizeOf() const {
709 size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700710 tagTable.sizeOf() + securityTagTable.sizeOf() +
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700711 tagNameTable.sizeOf() +
Mark Salyzynb0672292016-10-06 10:09:24 -0700712 (pidTable.size() * sizeof(pidTable_t::iterator)) +
713 (tagTable.size() * sizeof(tagTable_t::iterator));
Mark Salyzyn501c3732017-03-10 14:31:54 -0800714 for (auto it : pidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700715 const char* name = it.second.getName();
716 if (name) size += strlen(name) + 1;
717 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800718 for (auto it : tidTable) {
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700719 const char* name = it.second.getName();
720 if (name) size += strlen(name) + 1;
721 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700722 for (auto it : tagNameTable) size += it.second.getNameAllocLength();
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700723 log_id_for_each(id) {
724 size += uidTable[id].sizeOf();
Mark Salyzynb0672292016-10-06 10:09:24 -0700725 size += uidTable[id].size() * sizeof(uidTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700726 size += pidSystemTable[id].sizeOf();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800727 size +=
728 pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700729 }
730 return size;
731 }
732
Mark Salyzyn501c3732017-03-10 14:31:54 -0800733 public:
Mark Salyzyn34facab2014-02-06 14:48:50 -0800734 LogStatistics();
735
Mark Salyzyn501c3732017-03-10 14:31:54 -0800736 void enableStatistics() {
737 enable = true;
738 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800739
Mark Salyzyn02dd2f42017-04-14 09:46:57 -0700740 void addTotal(LogBufferElement* entry);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800741 void add(LogBufferElement* entry);
742 void subtract(LogBufferElement* entry);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700743 // entry->setDropped(1) must follow this call
Mark Salyzyn501c3732017-03-10 14:31:54 -0800744 void drop(LogBufferElement* entry);
Mark Salyzynaaad42f2015-09-30 07:40:09 -0700745 // Correct for coalescing two entries referencing dropped content
Mark Salyzyn501c3732017-03-10 14:31:54 -0800746 void erase(LogBufferElement* element) {
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700747 log_id_t log_id = element->getLogId();
748 --mElements[log_id];
749 --mDroppedElements[log_id];
750 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800751
Mark Salyzyn6a066942016-07-14 15:34:30 -0700752 LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
753 return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700754 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800755 LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len,
756 log_id id) {
Mark Salyzyn6a066942016-07-14 15:34:30 -0700757 return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
758 }
759 LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
760 return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700761 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800762
763 // fast track current value by id only
Mark Salyzyn501c3732017-03-10 14:31:54 -0800764 size_t sizes(log_id_t id) const {
765 return mSizes[id];
766 }
767 size_t elements(log_id_t id) const {
768 return mElements[id];
769 }
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700770 size_t realElements(log_id_t id) const {
771 return mElements[id] - mDroppedElements[id];
772 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800773 size_t sizesTotal(log_id_t id) const {
774 return mSizesTotal[id];
775 }
776 size_t elementsTotal(log_id_t id) const {
777 return mElementsTotal[id];
778 }
779 static size_t sizesTotal() {
780 return SizesTotal;
781 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800782
Mark Salyzynee3b8382015-12-17 09:58:43 -0800783 std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
Mark Salyzyn9a038632014-04-07 07:05:40 -0700784
Mark Salyzyned777e92015-06-24 16:22:54 -0700785 // helper (must be locked directly or implicitly by mLogElementsLock)
Mark Salyzyn501c3732017-03-10 14:31:54 -0800786 const char* pidToName(pid_t pid) const;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700787 uid_t pidToUid(pid_t pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800788 const char* uidToName(uid_t uid) const;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800789};
790
Mark Salyzyn501c3732017-03-10 14:31:54 -0800791#endif // _LOGD_LOG_STATISTICS_H__