blob: 3cd8fde5b72e41b8a795a581de833aac4a4de0fb [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
Tom Cherry64e90162020-05-07 14:44:43 -070017#include "LogStatistics.h"
18
Mark Salyzync4e48232017-05-04 13:54:46 -070019#include <ctype.h>
Mark Salyzyn9a038632014-04-07 07:05:40 -070020#include <fcntl.h>
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070021#include <inttypes.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070022#include <pwd.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070023#include <stdio.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070024#include <string.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070025#include <sys/types.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070026#include <unistd.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080027
Mark Salyzyn9af33ee2016-10-05 12:34:37 -070028#include <list>
29
Mark Salyzyn03bb7592017-04-14 09:46:57 -070030#include <private/android_logger.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080031
Tom Cherry3dd3ec32020-06-02 15:39:21 -070032#include "LogBufferElement.h"
33
Mark Salyzyn03bb7592017-04-14 09:46:57 -070034static const uint64_t hourSec = 60 * 60;
35static const uint64_t monthSec = 31 * 24 * hourSec;
36
Tom Cherry64e90162020-05-07 14:44:43 -070037std::atomic<size_t> LogStatistics::SizesTotal;
Mark Salyzyn32962912016-09-12 10:29:17 -070038
Tom Cherryb0263af2020-06-03 15:38:32 -070039static std::string TagNameKey(const LogStatisticsElement& element) {
40 if (IsBinary(element.log_id)) {
41 uint32_t tag = element.tag;
42 if (tag) {
43 const char* cp = android::tagToName(tag);
44 if (cp) {
45 return std::string(cp);
46 }
47 }
48 return android::base::StringPrintf("[%" PRIu32 "]", tag);
49 }
50 const char* msg = element.msg;
51 if (!msg) {
52 return "chatty";
53 }
54 ++msg;
55 uint16_t len = element.msg_len;
56 len = (len <= 1) ? 0 : strnlen(msg, len - 1);
57 if (!len) {
58 return "<NULL>";
59 }
60 return std::string(msg, len);
61}
62
Tom Cherry64e90162020-05-07 14:44:43 -070063LogStatistics::LogStatistics(bool enable_statistics) : enable(enable_statistics) {
Mark Salyzyn03bb7592017-04-14 09:46:57 -070064 log_time now(CLOCK_REALTIME);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070065 log_id_for_each(id) {
66 mSizes[id] = 0;
67 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070068 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070069 mSizesTotal[id] = 0;
70 mElementsTotal[id] = 0;
Mark Salyzyn03bb7592017-04-14 09:46:57 -070071 mOldest[id] = now;
72 mNewest[id] = now;
73 mNewestDropped[id] = now;
Mark Salyzyn34facab2014-02-06 14:48:50 -080074 }
75}
76
Mark Salyzyn720f6d12015-03-16 08:26:05 -070077namespace android {
78
Mark Salyzyn501c3732017-03-10 14:31:54 -080079size_t sizesTotal() {
80 return LogStatistics::sizesTotal();
81}
Mark Salyzyn32962912016-09-12 10:29:17 -070082
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070083// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -080084char* pidToName(pid_t pid) {
Yi Kongc8d09dd2018-07-13 17:39:22 -070085 char* retval = nullptr;
Mark Salyzyn501c3732017-03-10 14:31:54 -080086 if (pid == 0) { // special case from auditd/klogd for kernel
Mark Salyzynae4d9282014-10-15 08:49:39 -070087 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070088 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070089 char buffer[512];
90 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
Tom Cherry9b4246d2020-06-17 11:40:55 -070091 int fd = open(buffer, O_RDONLY | O_CLOEXEC);
Mark Salyzyn9a038632014-04-07 07:05:40 -070092 if (fd >= 0) {
93 ssize_t ret = read(fd, buffer, sizeof(buffer));
94 if (ret > 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080095 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn9a038632014-04-07 07:05:40 -070096 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080097 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070098 retval = strdup(buffer);
99 }
100 }
101 close(fd);
102 }
103 }
104 return retval;
105}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700106}
107
Tom Cherrya26f7df2020-05-19 17:48:42 -0700108void LogStatistics::AddTotal(log_id_t log_id, uint16_t size) {
Tom Cherry64e90162020-05-07 14:44:43 -0700109 auto lock = std::lock_guard{lock_};
Mark Salyzyn02dd2f42017-04-14 09:46:57 -0700110
Mark Salyzyn02dd2f42017-04-14 09:46:57 -0700111 mSizesTotal[log_id] += size;
112 SizesTotal += size;
113 ++mElementsTotal[log_id];
114}
115
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700116void LogStatistics::Add(const LogStatisticsElement& element) {
Tom Cherry64e90162020-05-07 14:44:43 -0700117 auto lock = std::lock_guard{lock_};
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700118 log_id_t log_id = element.log_id;
119 uint16_t size = element.msg_len;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800120 mSizes[log_id] += size;
121 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700122
Mark Salyzyn02dd2f42017-04-14 09:46:57 -0700123 // When caller adding a chatty entry, they will have already
124 // called add() and subtract() for each entry as they are
125 // evaluated and trimmed, thus recording size and number of
126 // elements, but we must recognize the manufactured dropped
127 // entry as not contributing to the lifetime totals.
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700128 if (element.dropped_count) {
Mark Salyzyna2c02222016-12-13 10:31:29 -0800129 ++mDroppedElements[log_id];
130 } else {
Mark Salyzyna2c02222016-12-13 10:31:29 -0800131 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -0700132 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -0800133 ++mElementsTotal[log_id];
134 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700135
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700136 log_time stamp(element.realtime);
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700137 if (mNewest[log_id] < stamp) {
138 // A major time update invalidates the statistics :-(
139 log_time diff = stamp - mNewest[log_id];
140 mNewest[log_id] = stamp;
141
142 if (diff.tv_sec > hourSec) {
143 // approximate Do-Your-Best fixup
144 diff += mOldest[log_id];
145 if ((diff > stamp) && ((diff - stamp).tv_sec < hourSec)) {
146 diff = stamp;
147 }
148 if (diff <= stamp) {
149 mOldest[log_id] = diff;
150 if (mNewestDropped[log_id] < diff) {
151 mNewestDropped[log_id] = diff;
152 }
153 }
154 }
155 }
156
Mark Salyzynae4d9282014-10-15 08:49:39 -0700157 if (log_id == LOG_ID_KERNEL) {
158 return;
159 }
160
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700161 uidTable[log_id].Add(element.uid, element);
162 if (element.uid == AID_SYSTEM) {
163 pidSystemTable[log_id].Add(element.pid, element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700164 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700165
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700166 if (!enable) {
167 return;
168 }
169
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700170 pidTable.Add(element.pid, element);
171 tidTable.Add(element.tid, element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700172
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700173 uint32_t tag = element.tag;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700174 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800175 if (log_id == LOG_ID_SECURITY) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700176 securityTagTable.Add(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800177 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700178 tagTable.Add(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800179 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700180 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700181
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700182 if (!element.dropped_count) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700183 tagNameTable.Add(TagNameKey(element), element);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700184 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800185}
186
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700187void LogStatistics::Subtract(const LogStatisticsElement& element) {
Tom Cherry64e90162020-05-07 14:44:43 -0700188 auto lock = std::lock_guard{lock_};
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700189 log_id_t log_id = element.log_id;
190 uint16_t size = element.msg_len;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800191 mSizes[log_id] -= size;
192 --mElements[log_id];
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700193 if (element.dropped_count) {
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700194 --mDroppedElements[log_id];
195 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700196
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700197 if (mOldest[log_id] < element.realtime) {
198 mOldest[log_id] = element.realtime;
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700199 }
200
Mark Salyzynae4d9282014-10-15 08:49:39 -0700201 if (log_id == LOG_ID_KERNEL) {
202 return;
203 }
204
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700205 uidTable[log_id].Subtract(element.uid, element);
206 if (element.uid == AID_SYSTEM) {
207 pidSystemTable[log_id].Subtract(element.pid, element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700208 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800209
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700210 if (!enable) {
211 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800212 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700213
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700214 pidTable.Subtract(element.pid, element);
215 tidTable.Subtract(element.tid, element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700216
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700217 uint32_t tag = element.tag;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700218 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800219 if (log_id == LOG_ID_SECURITY) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700220 securityTagTable.Subtract(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800221 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700222 tagTable.Subtract(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800223 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700224 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700225
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700226 if (!element.dropped_count) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700227 tagNameTable.Subtract(TagNameKey(element), element);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700228 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800229}
230
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700231// Atomically set an entry to drop
232// entry->setDropped(1) must follow this call, caller should do this explicitly.
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700233void LogStatistics::Drop(const LogStatisticsElement& element) {
Tom Cherry64e90162020-05-07 14:44:43 -0700234 auto lock = std::lock_guard{lock_};
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700235 log_id_t log_id = element.log_id;
236 uint16_t size = element.msg_len;
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700237 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700238 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700239
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700240 if (mNewestDropped[log_id] < element.realtime) {
241 mNewestDropped[log_id] = element.realtime;
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700242 }
243
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700244 uidTable[log_id].Drop(element.uid, element);
245 if (element.uid == AID_SYSTEM) {
246 pidSystemTable[log_id].Drop(element.pid, element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700247 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700248
249 if (!enable) {
250 return;
251 }
252
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700253 pidTable.Drop(element.pid, element);
254 tidTable.Drop(element.tid, element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700255
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700256 uint32_t tag = element.tag;
Mark Salyzyn6a066942016-07-14 15:34:30 -0700257 if (tag) {
258 if (log_id == LOG_ID_SECURITY) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700259 securityTagTable.Drop(tag, element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700260 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700261 tagTable.Drop(tag, element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700262 }
263 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700264
Tom Cherry9787f9a2020-05-19 19:01:16 -0700265 tagNameTable.Subtract(TagNameKey(element), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700266}
267
Tom Cherry64e90162020-05-07 14:44:43 -0700268const char* LogStatistics::UidToName(uid_t uid) const {
269 auto lock = std::lock_guard{lock_};
270 return UidToNameLocked(uid);
271}
272
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700273// caller must own and free character string
Tom Cherry64e90162020-05-07 14:44:43 -0700274const char* LogStatistics::UidToNameLocked(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700275 // Local hard coded favourites
276 if (uid == AID_LOGD) {
277 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800278 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700279
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700280 // Android system
281 if (uid < AID_APP) {
282 // in bionic, thread safe as long as we copy the results
Mark Salyzyn501c3732017-03-10 14:31:54 -0800283 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700284 if (pwd) {
285 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700286 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800287 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700288
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700289 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700290 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800291 const char* name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700292 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
293 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
294 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700295 if (name) {
296 return name;
297 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700298
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700299 // Android application
300 if (uid >= AID_APP) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800301 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700302 if (pwd) {
303 return strdup(pwd->pw_name);
304 }
305 }
306
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700307 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn501c3732017-03-10 14:31:54 -0800308 for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
309 ++it) {
310 const PidEntry& entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700311
Tom Cherry9787f9a2020-05-19 19:01:16 -0700312 if (entry.uid() == uid) {
313 const char* nameTmp = entry.name();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700314
Mark Salyzyn758058f2015-08-21 16:44:30 -0700315 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700316 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700317 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800318 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800319 free(const_cast<char*>(name));
Yi Kongc8d09dd2018-07-13 17:39:22 -0700320 name = nullptr;
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700321 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700322 }
323 }
324 }
325 }
326
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700327 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700328 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800329}
330
Tom Cherryb6b78e92020-05-07 09:13:12 -0700331template <typename TKey, typename TEntry>
332void LogStatistics::WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& table, size_t threshold,
333 int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700334 size_t* second_worst_sizes) const {
Tom Cherry4596b782020-06-03 13:49:24 -0700335 std::array<const TKey*, 2> max_keys;
Tom Cherryb6b78e92020-05-07 09:13:12 -0700336 std::array<const TEntry*, 2> max_entries;
Tom Cherry4596b782020-06-03 13:49:24 -0700337 table.MaxEntries(AID_ROOT, 0, max_keys, max_entries);
Tom Cherryb6b78e92020-05-07 09:13:12 -0700338 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
339 return;
340 }
341 *worst_sizes = max_entries[0]->getSizes();
342 // b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
343 // 100 characters.
Tom Cherry9787f9a2020-05-19 19:01:16 -0700344 if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->dropped_count())) {
Tom Cherry4596b782020-06-03 13:49:24 -0700345 *worst = *max_keys[0];
Tom Cherryb6b78e92020-05-07 09:13:12 -0700346 *second_worst_sizes = max_entries[1]->getSizes();
347 if (*second_worst_sizes < threshold) {
348 *second_worst_sizes = threshold;
349 }
350 }
351}
352
353void LogStatistics::WorstTwoUids(log_id id, size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700354 size_t* second_worst_sizes) const {
355 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700356 WorstTwoWithThreshold(uidTable[id], threshold, worst, worst_sizes, second_worst_sizes);
357}
358
359void LogStatistics::WorstTwoTags(size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700360 size_t* second_worst_sizes) const {
361 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700362 WorstTwoWithThreshold(tagTable, threshold, worst, worst_sizes, second_worst_sizes);
363}
364
365void LogStatistics::WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* worst,
Tom Cherry64e90162020-05-07 14:44:43 -0700366 size_t* second_worst_sizes) const {
367 auto lock = std::lock_guard{lock_};
Tom Cherry4596b782020-06-03 13:49:24 -0700368 std::array<const pid_t*, 2> max_keys;
Tom Cherryb6b78e92020-05-07 09:13:12 -0700369 std::array<const PidEntry*, 2> max_entries;
Tom Cherry4596b782020-06-03 13:49:24 -0700370 pidSystemTable[id].MaxEntries(AID_SYSTEM, 0, max_keys, max_entries);
Tom Cherryb6b78e92020-05-07 09:13:12 -0700371 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
372 return;
373 }
374
Tom Cherry4596b782020-06-03 13:49:24 -0700375 *worst = *max_keys[0];
Tom Cherryb6b78e92020-05-07 09:13:12 -0700376 *second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes();
377}
378
Tom Cherry64e90162020-05-07 14:44:43 -0700379// Prune at most 10% of the log entries or maxPrune, whichever is less.
380bool LogStatistics::ShouldPrune(log_id id, unsigned long max_size,
381 unsigned long* prune_rows) const {
382 static constexpr size_t kMinPrune = 4;
383 static constexpr size_t kMaxPrune = 256;
384
385 auto lock = std::lock_guard{lock_};
386 size_t sizes = mSizes[id];
387 if (sizes <= max_size) {
388 return false;
389 }
390 size_t size_over = sizes - ((max_size * 9) / 10);
391 size_t elements = mElements[id] - mDroppedElements[id];
392 size_t min_elements = elements / 100;
393 if (min_elements < kMinPrune) {
394 min_elements = kMinPrune;
395 }
396 *prune_rows = elements * size_over / sizes;
397 if (*prune_rows < min_elements) {
398 *prune_rows = min_elements;
399 }
400 if (*prune_rows > kMaxPrune) {
401 *prune_rows = kMaxPrune;
402 }
403
404 return true;
405}
406
Mark Salyzyn501c3732017-03-10 14:31:54 -0800407std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700408 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800409 return formatLine(android::base::StringPrintf(name.c_str(),
410 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700411 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800412 std::string(isprune ? "+/- Pruned" : "")) +
413 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700414 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800415}
416
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700417// Helper to truncate name, if too long, and add name dressings
Tom Cherry64e90162020-05-07 14:44:43 -0700418void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size,
419 size_t nameLen) const {
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700420 const char* allocNameTmp = nullptr;
Tom Cherry64e90162020-05-07 14:44:43 -0700421 if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700422 if (nameTmp) {
423 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
Tom Cherry9787f9a2020-05-19 19:01:16 -0700424 size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
425 lenSpace - 2;
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700426 size_t lenNameTmp = strlen(nameTmp);
427 while ((len < lenNameTmp) && (lenSpace > 1)) {
428 ++len;
429 --lenSpace;
430 }
431 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
432 if (len < lenNameTmp) {
433 name += "...";
434 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
435 }
436 name += nameTmp;
437 free(const_cast<char*>(allocNameTmp));
438 }
439}
440
Tom Cherry4596b782020-06-03 13:49:24 -0700441std::string UidEntry::format(const LogStatistics& stat, log_id_t id, uid_t uid) const
442 REQUIRES(stat.lock_) {
443 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700444 std::string size = android::base::StringPrintf("%zu", getSizes());
445
Tom Cherry4596b782020-06-03 13:49:24 -0700446 stat.FormatTmp(nullptr, uid, name, size, 6);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700447
Mark Salyzyn758058f2015-08-21 16:44:30 -0700448 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700449 if (worstUidEnabledForLogid(id)) {
450 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800451 for (LogStatistics::uidTable_t::const_iterator it =
452 stat.uidTable[id].begin();
453 it != stat.uidTable[id].end(); ++it) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700454 totalDropped += it->second.dropped_count();
Mark Salyzync723df82015-08-24 11:08:00 -0700455 }
Tom Cherry64e90162020-05-07 14:44:43 -0700456 size_t sizes = stat.mSizes[id];
457 size_t totalSize = stat.mSizesTotal[id];
458 size_t totalElements = stat.mElementsTotal[id];
Mark Salyzyn501c3732017-03-10 14:31:54 -0800459 float totalVirtualSize =
460 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700461 size_t entrySize = getSizes();
462 float virtualEntrySize = entrySize;
463 int realPermille = virtualEntrySize * 1000.0 / sizes;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700464 size_t dropped = dropped_count();
Mark Salyzync723df82015-08-24 11:08:00 -0700465 if (dropped) {
466 pruned = android::base::StringPrintf("%zu", dropped);
467 virtualEntrySize += (float)dropped * totalSize / totalElements;
468 }
469 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800470 int permille =
471 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700472 if ((permille < -1) || (1 < permille)) {
473 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800474 const char* units = "%";
475 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700476
477 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800478 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700479 units = "X";
480 prefix = "";
481 }
482 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800483 change = android::base::StringPrintf(
484 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700485 ((permille < 0) ? (-permille % 10) : (permille % 10)),
486 units);
487 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800488 change = android::base::StringPrintf(
489 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700490 }
Tom Cherry9787f9a2020-05-19 19:01:16 -0700491 ssize_t spaces = EntryBase::PRUNED_LEN - 2 - pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700492 if ((spaces <= 0) && pruned.length()) {
493 spaces = 1;
494 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000495 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700496 change += android::base::StringPrintf("%*s", (int)spaces, "");
497 }
498 pruned = change + pruned;
499 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700500 }
501
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700502 std::string output = formatLine(name, size, pruned);
503
Tom Cherry4596b782020-06-03 13:49:24 -0700504 if (uid != AID_SYSTEM) {
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700505 return output;
506 }
507
508 static const size_t maximum_sorted_entries = 32;
Tom Cherry4596b782020-06-03 13:49:24 -0700509 std::array<const pid_t*, maximum_sorted_entries> sorted_pids;
510 std::array<const PidEntry*, maximum_sorted_entries> sorted_entries;
511 stat.pidSystemTable[id].MaxEntries(uid, 0, sorted_pids, sorted_entries);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700512
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700513 std::string byPid;
514 size_t index;
515 bool hasDropped = false;
516 for (index = 0; index < maximum_sorted_entries; ++index) {
Tom Cherry4596b782020-06-03 13:49:24 -0700517 const PidEntry* entry = sorted_entries[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700518 if (!entry) {
519 break;
520 }
521 if (entry->getSizes() <= (getSizes() / 100)) {
522 break;
523 }
Tom Cherry9787f9a2020-05-19 19:01:16 -0700524 if (entry->dropped_count()) {
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700525 hasDropped = true;
526 }
Tom Cherry4596b782020-06-03 13:49:24 -0700527 byPid += entry->format(stat, id, *sorted_pids[index]);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700528 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800529 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700530 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800531 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
532 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700533 output += byPid;
534 }
535
536 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700537}
538
Mark Salyzyn501c3732017-03-10 14:31:54 -0800539std::string PidEntry::formatHeader(const std::string& name,
540 log_id_t /* id */) const {
541 return formatLine(name, std::string("Size"), std::string("Pruned")) +
542 formatLine(std::string(" PID/UID COMMAND LINE"),
543 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700544}
545
Tom Cherry4596b782020-06-03 13:49:24 -0700546std::string PidEntry::format(const LogStatistics& stat, log_id_t, pid_t pid) const
Tom Cherry64e90162020-05-07 14:44:43 -0700547 REQUIRES(stat.lock_) {
Tom Cherry4596b782020-06-03 13:49:24 -0700548 std::string name = android::base::StringPrintf("%5u/%u", pid, uid_);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800549 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700550
Tom Cherry9787f9a2020-05-19 19:01:16 -0700551 stat.FormatTmp(name_, uid_, name, size, 12);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700552
Mark Salyzyn758058f2015-08-21 16:44:30 -0700553 std::string pruned = "";
Tom Cherry9787f9a2020-05-19 19:01:16 -0700554 size_t dropped = dropped_count();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700555 if (dropped) {
556 pruned = android::base::StringPrintf("%zu", dropped);
557 }
558
559 return formatLine(name, size, pruned);
560}
561
Mark Salyzyn501c3732017-03-10 14:31:54 -0800562std::string TidEntry::formatHeader(const std::string& name,
563 log_id_t /* id */) const {
564 return formatLine(name, std::string("Size"), std::string("Pruned")) +
565 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700566 std::string("NUM"));
567}
568
Tom Cherry4596b782020-06-03 13:49:24 -0700569std::string TidEntry::format(const LogStatistics& stat, log_id_t, pid_t tid) const
Tom Cherry64e90162020-05-07 14:44:43 -0700570 REQUIRES(stat.lock_) {
Tom Cherry4596b782020-06-03 13:49:24 -0700571 std::string name = android::base::StringPrintf("%5u/%u", tid, uid_);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800572 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700573
Tom Cherry9787f9a2020-05-19 19:01:16 -0700574 stat.FormatTmp(name_, uid_, name, size, 12);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700575
Mark Salyzyn758058f2015-08-21 16:44:30 -0700576 std::string pruned = "";
Tom Cherry9787f9a2020-05-19 19:01:16 -0700577 size_t dropped = dropped_count();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700578 if (dropped) {
579 pruned = android::base::StringPrintf("%zu", dropped);
580 }
581
582 return formatLine(name, size, pruned);
583}
584
Mark Salyzyn501c3732017-03-10 14:31:54 -0800585std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700586 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800587 return formatLine(name, std::string("Size"),
588 std::string(isprune ? "Prune" : "")) +
589 formatLine(std::string(" TAG/UID TAGNAME"),
590 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700591}
592
Tom Cherry4596b782020-06-03 13:49:24 -0700593std::string TagEntry::format(const LogStatistics&, log_id_t, uint32_t) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700594 std::string name;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700595 if (uid_ == (uid_t)-1) {
596 name = android::base::StringPrintf("%7u", key());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700597 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700598 name = android::base::StringPrintf("%7u/%u", key(), uid_);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700599 }
Tom Cherry9787f9a2020-05-19 19:01:16 -0700600 const char* nameTmp = this->name();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700601 if (nameTmp) {
602 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800603 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700604 }
605
Mark Salyzyn501c3732017-03-10 14:31:54 -0800606 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700607
608 std::string pruned = "";
Tom Cherry9787f9a2020-05-19 19:01:16 -0700609 size_t dropped = dropped_count();
Mark Salyzyn6a066942016-07-14 15:34:30 -0700610 if (dropped) {
611 pruned = android::base::StringPrintf("%zu", dropped);
612 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700613
614 return formatLine(name, size, pruned);
615}
616
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700617std::string TagNameEntry::formatHeader(const std::string& name,
618 log_id_t /* id */) const {
619 return formatLine(name, std::string("Size"), std::string("")) +
620 formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
621 std::string("BYTES"), std::string(""));
622}
623
Tom Cherryb0263af2020-06-03 15:38:32 -0700624std::string TagNameEntry::format(const LogStatistics&, log_id_t,
625 const std::string& key_name) const {
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700626 std::string name;
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700627 std::string pidstr;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700628 if (pid_ != (pid_t)-1) {
629 pidstr = android::base::StringPrintf("%u", pid_);
630 if (tid_ != (pid_t)-1 && tid_ != pid_) pidstr = "/" + pidstr;
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700631 }
632 int len = 9 - pidstr.length();
633 if (len < 0) len = 0;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700634 if (tid_ == (pid_t)-1 || tid_ == pid_) {
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700635 name = android::base::StringPrintf("%*s", len, "");
636 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700637 name = android::base::StringPrintf("%*u", len, tid_);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700638 }
639 name += pidstr;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700640 if (uid_ != (uid_t)-1) {
641 name += android::base::StringPrintf("/%u", uid_);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700642 }
643
644 std::string size = android::base::StringPrintf("%zu", getSizes());
645
Tom Cherry4596b782020-06-03 13:49:24 -0700646 const char* nameTmp = key_name.data();
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700647 if (nameTmp) {
648 size_t lenSpace = std::max(16 - name.length(), (size_t)1);
Tom Cherry9787f9a2020-05-19 19:01:16 -0700649 size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
650 lenSpace - 2;
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700651 size_t lenNameTmp = strlen(nameTmp);
652 while ((len < lenNameTmp) && (lenSpace > 1)) {
653 ++len;
654 --lenSpace;
655 }
656 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
657 if (len < lenNameTmp) {
658 name += "...";
659 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
660 }
661 name += nameTmp;
662 }
663
664 std::string pruned = "";
665
666 return formatLine(name, size, pruned);
667}
668
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700669static std::string formatMsec(uint64_t val) {
670 static const unsigned subsecDigits = 3;
671 static const uint64_t sec = MS_PER_SEC;
672
673 static const uint64_t minute = 60 * sec;
674 static const uint64_t hour = 60 * minute;
675 static const uint64_t day = 24 * hour;
676
677 std::string output;
678 if (val < sec) return output;
679
680 if (val >= day) {
681 output = android::base::StringPrintf("%" PRIu64 "d ", val / day);
682 val = (val % day) + day;
683 }
684 if (val >= minute) {
685 if (val >= hour) {
686 output += android::base::StringPrintf("%" PRIu64 ":",
687 (val / hour) % (day / hour));
688 }
689 output += android::base::StringPrintf(
690 (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
691 (val / minute) % (hour / minute));
692 }
693 output +=
694 android::base::StringPrintf((val >= minute) ? "%02" PRIu64 : "%" PRIu64,
695 (val / sec) % (minute / sec));
696 val %= sec;
697 unsigned digits = subsecDigits;
698 while (digits && ((val % 10) == 0)) {
699 val /= 10;
700 --digits;
701 }
702 if (digits) {
703 output += android::base::StringPrintf(".%0*" PRIu64, digits, val);
704 }
705 return output;
706}
707
Tom Cherry64e90162020-05-07 14:44:43 -0700708template <typename TKey, typename TEntry>
709std::string LogStatistics::FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid,
710 pid_t pid, const std::string& name, log_id_t id) const
711 REQUIRES(lock_) {
712 static const size_t maximum_sorted_entries = 32;
713 std::string output;
Tom Cherry4596b782020-06-03 13:49:24 -0700714 std::array<const TKey*, maximum_sorted_entries> sorted_keys;
715 std::array<const TEntry*, maximum_sorted_entries> sorted_entries;
716 table.MaxEntries(uid, pid, sorted_keys, sorted_entries);
Tom Cherry64e90162020-05-07 14:44:43 -0700717 bool header_printed = false;
718 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
Tom Cherry4596b782020-06-03 13:49:24 -0700719 const TEntry* entry = sorted_entries[index];
Tom Cherry64e90162020-05-07 14:44:43 -0700720 if (!entry) {
721 break;
722 }
Tom Cherry4596b782020-06-03 13:49:24 -0700723 if (entry->getSizes() <= (sorted_entries[0]->getSizes() / 100)) {
Tom Cherry64e90162020-05-07 14:44:43 -0700724 break;
725 }
726 if (!header_printed) {
727 output += "\n\n";
728 output += entry->formatHeader(name, id);
729 header_printed = true;
730 }
Tom Cherry4596b782020-06-03 13:49:24 -0700731 output += entry->format(*this, id, *sorted_keys[index]);
Tom Cherry64e90162020-05-07 14:44:43 -0700732 }
733 return output;
734}
735
736std::string LogStatistics::Format(uid_t uid, pid_t pid, unsigned int logMask) const {
737 auto lock = std::lock_guard{lock_};
738
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700739 static const uint16_t spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800740
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700741 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800742
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700743 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700744 size_t oldLength;
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700745 int16_t spaces = 1;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700746
747 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700748 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700749 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700750 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700751 output += android::base::StringPrintf("%*s%s", spaces, "",
752 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700753 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800754 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700755 if (spaces < 0) spaces = 0;
756 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800757
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700758 static const char TotalStr[] = "\nTotal";
759 spaces = 10 - strlen(TotalStr);
760 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800761
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700762 size_t totalSize = 0;
763 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700764 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700765 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700766 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700767 if (spaces < 0) spaces = 0;
Tom Cherry64e90162020-05-07 14:44:43 -0700768 size_t szs = mSizesTotal[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700769 totalSize += szs;
Tom Cherry64e90162020-05-07 14:44:43 -0700770 size_t els = mElementsTotal[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700771 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800772 output +=
773 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700774 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800775 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700776 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800777 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
778 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800779
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700780 static const char NowStr[] = "\nNow";
781 spaces = 10 - strlen(NowStr);
782 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800783
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700784 totalSize = 0;
785 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700786 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700787 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800788
Tom Cherry64e90162020-05-07 14:44:43 -0700789 size_t els = mElements[id];
Mark Salyzyn34facab2014-02-06 14:48:50 -0800790 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700791 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700792 if (spaces < 0) spaces = 0;
Tom Cherry64e90162020-05-07 14:44:43 -0700793 size_t szs = mSizes[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700794 totalSize += szs;
795 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800796 output +=
797 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700798 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800799 }
800 spaces += spaces_total;
801 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700802 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800803 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
804 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700805
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700806 static const char SpanStr[] = "\nLogspan";
807 spaces = 10 - strlen(SpanStr);
808 output += SpanStr;
809
810 // Total reports the greater of the individual maximum time span, or the
811 // validated minimum start and maximum end time span if it makes sense.
812 uint64_t minTime = UINT64_MAX;
813 uint64_t maxTime = 0;
814 uint64_t maxSpan = 0;
815 totalSize = 0;
816
817 log_id_for_each(id) {
818 if (!(logMask & (1 << id))) continue;
819
820 // validity checking
821 uint64_t oldest = mOldest[id].msec();
822 uint64_t newest = mNewest[id].msec();
823 if (newest <= oldest) {
824 spaces += spaces_total;
825 continue;
826 }
827
828 uint64_t span = newest - oldest;
829 if (span > (monthSec * MS_PER_SEC)) {
830 spaces += spaces_total;
831 continue;
832 }
833
834 // total span
835 if (minTime > oldest) minTime = oldest;
836 if (maxTime < newest) maxTime = newest;
837 if (span > maxSpan) maxSpan = span;
838 totalSize += span;
839
840 uint64_t dropped = mNewestDropped[id].msec();
841 if (dropped < oldest) dropped = oldest;
842 if (dropped > newest) dropped = newest;
843
844 oldLength = output.length();
845 output += android::base::StringPrintf("%*s%s", spaces, "",
846 formatMsec(span).c_str());
847 unsigned permille = ((newest - dropped) * 1000 + (span / 2)) / span;
848 if ((permille > 1) && (permille < 999)) {
849 output += android::base::StringPrintf("(%u", permille / 10);
850 permille %= 10;
851 if (permille) {
852 output += android::base::StringPrintf(".%u", permille);
853 }
854 output += android::base::StringPrintf("%%)");
855 }
856 spaces -= output.length() - oldLength;
857 spaces += spaces_total;
858 }
859 if ((maxTime > minTime) && ((maxTime -= minTime) < totalSize) &&
860 (maxTime > maxSpan)) {
861 maxSpan = maxTime;
862 }
863 if (spaces < 0) spaces = 0;
864 output += android::base::StringPrintf("%*s%s", spaces, "",
865 formatMsec(maxSpan).c_str());
866
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700867 static const char OverheadStr[] = "\nOverhead";
868 spaces = 10 - strlen(OverheadStr);
869 output += OverheadStr;
870
871 totalSize = 0;
872 log_id_for_each(id) {
873 if (!(logMask & (1 << id))) continue;
874
Tom Cherry64e90162020-05-07 14:44:43 -0700875 size_t els = mElements[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700876 if (els) {
877 oldLength = output.length();
878 if (spaces < 0) spaces = 0;
879 // estimate the std::list overhead.
880 static const size_t overhead =
881 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800882 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700883 sizeof(std::list<LogBufferElement*>);
Tom Cherry64e90162020-05-07 14:44:43 -0700884 size_t szs = mSizes[id] + els * overhead;
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700885 totalSize += szs;
886 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
887 spaces -= output.length() - oldLength;
888 }
889 spaces += spaces_total;
890 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700891 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700892 if (spaces < 0) spaces = 0;
893 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800894
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700895 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700896
Mark Salyzyn758058f2015-08-21 16:44:30 -0700897 std::string name;
898
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700899 // Chattiest by application (UID)
900 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700901 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700902
Mark Salyzyn501c3732017-03-10 14:31:54 -0800903 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
904 : "Logging for your UID in %s log buffer:";
Tom Cherry64e90162020-05-07 14:44:43 -0700905 output += FormatTable(uidTable[id], uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700906 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700907
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700908 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800909 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
910 : "Logging for this PID:";
Tom Cherry64e90162020-05-07 14:44:43 -0700911 output += FormatTable(pidTable, uid, pid, name);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800912 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700913 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800914 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700915 output += FormatTable(tidTable, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700916 }
917
Mark Salyzyn344bff42015-04-13 14:24:45 -0700918 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800919 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700920 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800921 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700922 output += FormatTable(tagTable, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700923 }
924
Mark Salyzyn083b0372015-12-04 10:59:45 -0800925 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800926 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700927 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800928 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700929 output += FormatTable(securityTagTable, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800930 }
931
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700932 if (enable) {
933 name = "Chattiest TAGs";
934 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
935 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700936 output += FormatTable(tagNameTable, uid, pid, name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700937 }
938
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700939 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800940}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700941
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700942namespace android {
943
944uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700945 char buffer[512];
946 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Tom Cherry9b4246d2020-06-17 11:40:55 -0700947 FILE* fp = fopen(buffer, "re");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700948 if (fp) {
949 while (fgets(buffer, sizeof(buffer), fp)) {
Mark Salyzync4e48232017-05-04 13:54:46 -0700950 int uid = AID_LOGD;
951 char space = 0;
952 if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
953 isspace(space)) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700954 fclose(fp);
955 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700956 }
957 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700958 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700959 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800960 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700961}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700962}
963
Tom Cherry64e90162020-05-07 14:44:43 -0700964uid_t LogStatistics::PidToUid(pid_t pid) {
965 auto lock = std::lock_guard{lock_};
Tom Cherry9787f9a2020-05-19 19:01:16 -0700966 return pidTable.Add(pid)->second.uid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700967}
968
969// caller must free character string
Tom Cherry64e90162020-05-07 14:44:43 -0700970const char* LogStatistics::PidToName(pid_t pid) const {
971 auto lock = std::lock_guard{lock_};
Mark Salyzyn758058f2015-08-21 16:44:30 -0700972 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800973 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
Tom Cherry9787f9a2020-05-19 19:01:16 -0700974 const char* name = writablePidTable.Add(pid)->second.name();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700975 if (!name) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700976 return nullptr;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700977 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700978 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700979}