blob: 04fd59d95c4809f05ec5ecfd207655df7617f181 [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 Cherry64e90162020-05-07 14:44:43 -070039LogStatistics::LogStatistics(bool enable_statistics) : enable(enable_statistics) {
Mark Salyzyn03bb7592017-04-14 09:46:57 -070040 log_time now(CLOCK_REALTIME);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070041 log_id_for_each(id) {
42 mSizes[id] = 0;
43 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070044 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070045 mSizesTotal[id] = 0;
46 mElementsTotal[id] = 0;
Mark Salyzyn03bb7592017-04-14 09:46:57 -070047 mOldest[id] = now;
48 mNewest[id] = now;
49 mNewestDropped[id] = now;
Mark Salyzyn34facab2014-02-06 14:48:50 -080050 }
51}
52
Mark Salyzyn720f6d12015-03-16 08:26:05 -070053namespace android {
54
Mark Salyzyn501c3732017-03-10 14:31:54 -080055size_t sizesTotal() {
56 return LogStatistics::sizesTotal();
57}
Mark Salyzyn32962912016-09-12 10:29:17 -070058
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070059// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -080060char* pidToName(pid_t pid) {
Yi Kongc8d09dd2018-07-13 17:39:22 -070061 char* retval = nullptr;
Mark Salyzyn501c3732017-03-10 14:31:54 -080062 if (pid == 0) { // special case from auditd/klogd for kernel
Mark Salyzynae4d9282014-10-15 08:49:39 -070063 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070064 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070065 char buffer[512];
66 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
67 int fd = open(buffer, O_RDONLY);
68 if (fd >= 0) {
69 ssize_t ret = read(fd, buffer, sizeof(buffer));
70 if (ret > 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080071 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn9a038632014-04-07 07:05:40 -070072 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080073 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070074 retval = strdup(buffer);
75 }
76 }
77 close(fd);
78 }
79 }
80 return retval;
81}
Mark Salyzyn720f6d12015-03-16 08:26:05 -070082}
83
Tom Cherrya26f7df2020-05-19 17:48:42 -070084void LogStatistics::AddTotal(log_id_t log_id, uint16_t size) {
Tom Cherry64e90162020-05-07 14:44:43 -070085 auto lock = std::lock_guard{lock_};
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070086
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070087 mSizesTotal[log_id] += size;
88 SizesTotal += size;
89 ++mElementsTotal[log_id];
90}
91
Tom Cherry3dd3ec32020-06-02 15:39:21 -070092void LogStatistics::Add(const LogStatisticsElement& element) {
Tom Cherry64e90162020-05-07 14:44:43 -070093 auto lock = std::lock_guard{lock_};
Tom Cherry3dd3ec32020-06-02 15:39:21 -070094 log_id_t log_id = element.log_id;
95 uint16_t size = element.msg_len;
Mark Salyzyn34facab2014-02-06 14:48:50 -080096 mSizes[log_id] += size;
97 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070098
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070099 // When caller adding a chatty entry, they will have already
100 // called add() and subtract() for each entry as they are
101 // evaluated and trimmed, thus recording size and number of
102 // elements, but we must recognize the manufactured dropped
103 // entry as not contributing to the lifetime totals.
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700104 if (element.dropped_count) {
Mark Salyzyna2c02222016-12-13 10:31:29 -0800105 ++mDroppedElements[log_id];
106 } else {
Mark Salyzyna2c02222016-12-13 10:31:29 -0800107 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -0700108 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -0800109 ++mElementsTotal[log_id];
110 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700111
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700112 log_time stamp(element.realtime);
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700113 if (mNewest[log_id] < stamp) {
114 // A major time update invalidates the statistics :-(
115 log_time diff = stamp - mNewest[log_id];
116 mNewest[log_id] = stamp;
117
118 if (diff.tv_sec > hourSec) {
119 // approximate Do-Your-Best fixup
120 diff += mOldest[log_id];
121 if ((diff > stamp) && ((diff - stamp).tv_sec < hourSec)) {
122 diff = stamp;
123 }
124 if (diff <= stamp) {
125 mOldest[log_id] = diff;
126 if (mNewestDropped[log_id] < diff) {
127 mNewestDropped[log_id] = diff;
128 }
129 }
130 }
131 }
132
Mark Salyzynae4d9282014-10-15 08:49:39 -0700133 if (log_id == LOG_ID_KERNEL) {
134 return;
135 }
136
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700137 uidTable[log_id].Add(element.uid, element);
138 if (element.uid == AID_SYSTEM) {
139 pidSystemTable[log_id].Add(element.pid, element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700140 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700141
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700142 if (!enable) {
143 return;
144 }
145
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700146 pidTable.Add(element.pid, element);
147 tidTable.Add(element.tid, element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700148
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700149 uint32_t tag = element.tag;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700150 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800151 if (log_id == LOG_ID_SECURITY) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700152 securityTagTable.Add(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800153 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700154 tagTable.Add(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800155 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700156 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700157
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700158 if (!element.dropped_count) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700159 tagNameTable.Add(TagNameKey(element), element);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700160 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800161}
162
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700163void LogStatistics::Subtract(const LogStatisticsElement& element) {
Tom Cherry64e90162020-05-07 14:44:43 -0700164 auto lock = std::lock_guard{lock_};
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700165 log_id_t log_id = element.log_id;
166 uint16_t size = element.msg_len;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800167 mSizes[log_id] -= size;
168 --mElements[log_id];
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700169 if (element.dropped_count) {
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700170 --mDroppedElements[log_id];
171 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700172
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700173 if (mOldest[log_id] < element.realtime) {
174 mOldest[log_id] = element.realtime;
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700175 }
176
Mark Salyzynae4d9282014-10-15 08:49:39 -0700177 if (log_id == LOG_ID_KERNEL) {
178 return;
179 }
180
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700181 uidTable[log_id].Subtract(element.uid, element);
182 if (element.uid == AID_SYSTEM) {
183 pidSystemTable[log_id].Subtract(element.pid, element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700184 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800185
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700186 if (!enable) {
187 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800188 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700189
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700190 pidTable.Subtract(element.pid, element);
191 tidTable.Subtract(element.tid, element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700192
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700193 uint32_t tag = element.tag;
Mark Salyzyn344bff42015-04-13 14:24:45 -0700194 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800195 if (log_id == LOG_ID_SECURITY) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700196 securityTagTable.Subtract(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800197 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700198 tagTable.Subtract(tag, element);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800199 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700200 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700201
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700202 if (!element.dropped_count) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700203 tagNameTable.Subtract(TagNameKey(element), element);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700204 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800205}
206
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700207// Atomically set an entry to drop
208// entry->setDropped(1) must follow this call, caller should do this explicitly.
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700209void LogStatistics::Drop(const LogStatisticsElement& element) {
Tom Cherry64e90162020-05-07 14:44:43 -0700210 auto lock = std::lock_guard{lock_};
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700211 log_id_t log_id = element.log_id;
212 uint16_t size = element.msg_len;
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700213 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700214 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700215
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700216 if (mNewestDropped[log_id] < element.realtime) {
217 mNewestDropped[log_id] = element.realtime;
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700218 }
219
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700220 uidTable[log_id].Drop(element.uid, element);
221 if (element.uid == AID_SYSTEM) {
222 pidSystemTable[log_id].Drop(element.pid, element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700223 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700224
225 if (!enable) {
226 return;
227 }
228
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700229 pidTable.Drop(element.pid, element);
230 tidTable.Drop(element.tid, element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700231
Tom Cherry3dd3ec32020-06-02 15:39:21 -0700232 uint32_t tag = element.tag;
Mark Salyzyn6a066942016-07-14 15:34:30 -0700233 if (tag) {
234 if (log_id == LOG_ID_SECURITY) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700235 securityTagTable.Drop(tag, element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700236 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700237 tagTable.Drop(tag, element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700238 }
239 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700240
Tom Cherry9787f9a2020-05-19 19:01:16 -0700241 tagNameTable.Subtract(TagNameKey(element), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700242}
243
Tom Cherry64e90162020-05-07 14:44:43 -0700244const char* LogStatistics::UidToName(uid_t uid) const {
245 auto lock = std::lock_guard{lock_};
246 return UidToNameLocked(uid);
247}
248
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700249// caller must own and free character string
Tom Cherry64e90162020-05-07 14:44:43 -0700250const char* LogStatistics::UidToNameLocked(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700251 // Local hard coded favourites
252 if (uid == AID_LOGD) {
253 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800254 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700255
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700256 // Android system
257 if (uid < AID_APP) {
258 // in bionic, thread safe as long as we copy the results
Mark Salyzyn501c3732017-03-10 14:31:54 -0800259 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700260 if (pwd) {
261 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700262 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800263 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700264
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700265 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700266 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800267 const char* name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700268 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
269 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
270 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700271 if (name) {
272 return name;
273 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700274
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700275 // Android application
276 if (uid >= AID_APP) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800277 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700278 if (pwd) {
279 return strdup(pwd->pw_name);
280 }
281 }
282
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700283 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn501c3732017-03-10 14:31:54 -0800284 for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
285 ++it) {
286 const PidEntry& entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700287
Tom Cherry9787f9a2020-05-19 19:01:16 -0700288 if (entry.uid() == uid) {
289 const char* nameTmp = entry.name();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700290
Mark Salyzyn758058f2015-08-21 16:44:30 -0700291 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700292 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700293 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800294 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800295 free(const_cast<char*>(name));
Yi Kongc8d09dd2018-07-13 17:39:22 -0700296 name = nullptr;
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700297 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700298 }
299 }
300 }
301 }
302
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700303 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700304 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800305}
306
Tom Cherryb6b78e92020-05-07 09:13:12 -0700307template <typename TKey, typename TEntry>
308void LogStatistics::WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& table, size_t threshold,
309 int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700310 size_t* second_worst_sizes) const {
Tom Cherryb6b78e92020-05-07 09:13:12 -0700311 std::array<const TEntry*, 2> max_entries;
312 table.MaxEntries(AID_ROOT, 0, &max_entries);
313 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
314 return;
315 }
316 *worst_sizes = max_entries[0]->getSizes();
317 // b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
318 // 100 characters.
Tom Cherry9787f9a2020-05-19 19:01:16 -0700319 if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->dropped_count())) {
320 *worst = max_entries[0]->key();
Tom Cherryb6b78e92020-05-07 09:13:12 -0700321 *second_worst_sizes = max_entries[1]->getSizes();
322 if (*second_worst_sizes < threshold) {
323 *second_worst_sizes = threshold;
324 }
325 }
326}
327
328void LogStatistics::WorstTwoUids(log_id id, size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700329 size_t* second_worst_sizes) const {
330 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700331 WorstTwoWithThreshold(uidTable[id], threshold, worst, worst_sizes, second_worst_sizes);
332}
333
334void LogStatistics::WorstTwoTags(size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700335 size_t* second_worst_sizes) const {
336 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700337 WorstTwoWithThreshold(tagTable, threshold, worst, worst_sizes, second_worst_sizes);
338}
339
340void LogStatistics::WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* worst,
Tom Cherry64e90162020-05-07 14:44:43 -0700341 size_t* second_worst_sizes) const {
342 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700343 std::array<const PidEntry*, 2> max_entries;
344 pidSystemTable[id].MaxEntries(AID_SYSTEM, 0, &max_entries);
345 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
346 return;
347 }
348
Tom Cherry9787f9a2020-05-19 19:01:16 -0700349 *worst = max_entries[0]->key();
Tom Cherryb6b78e92020-05-07 09:13:12 -0700350 *second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes();
351}
352
Tom Cherry64e90162020-05-07 14:44:43 -0700353// Prune at most 10% of the log entries or maxPrune, whichever is less.
354bool LogStatistics::ShouldPrune(log_id id, unsigned long max_size,
355 unsigned long* prune_rows) const {
356 static constexpr size_t kMinPrune = 4;
357 static constexpr size_t kMaxPrune = 256;
358
359 auto lock = std::lock_guard{lock_};
360 size_t sizes = mSizes[id];
361 if (sizes <= max_size) {
362 return false;
363 }
364 size_t size_over = sizes - ((max_size * 9) / 10);
365 size_t elements = mElements[id] - mDroppedElements[id];
366 size_t min_elements = elements / 100;
367 if (min_elements < kMinPrune) {
368 min_elements = kMinPrune;
369 }
370 *prune_rows = elements * size_over / sizes;
371 if (*prune_rows < min_elements) {
372 *prune_rows = min_elements;
373 }
374 if (*prune_rows > kMaxPrune) {
375 *prune_rows = kMaxPrune;
376 }
377
378 return true;
379}
380
Mark Salyzyn501c3732017-03-10 14:31:54 -0800381std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700382 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800383 return formatLine(android::base::StringPrintf(name.c_str(),
384 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700385 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800386 std::string(isprune ? "+/- Pruned" : "")) +
387 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700388 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800389}
390
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700391// Helper to truncate name, if too long, and add name dressings
Tom Cherry64e90162020-05-07 14:44:43 -0700392void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size,
393 size_t nameLen) const {
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700394 const char* allocNameTmp = nullptr;
Tom Cherry64e90162020-05-07 14:44:43 -0700395 if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700396 if (nameTmp) {
397 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
Tom Cherry9787f9a2020-05-19 19:01:16 -0700398 size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
399 lenSpace - 2;
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700400 size_t lenNameTmp = strlen(nameTmp);
401 while ((len < lenNameTmp) && (lenSpace > 1)) {
402 ++len;
403 --lenSpace;
404 }
405 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
406 if (len < lenNameTmp) {
407 name += "...";
408 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
409 }
410 name += nameTmp;
411 free(const_cast<char*>(allocNameTmp));
412 }
413}
414
Tom Cherry64e90162020-05-07 14:44:43 -0700415std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUIRES(stat.lock_) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700416 std::string name = android::base::StringPrintf("%u", uid_);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700417 std::string size = android::base::StringPrintf("%zu", getSizes());
418
Tom Cherry9787f9a2020-05-19 19:01:16 -0700419 stat.FormatTmp(nullptr, uid_, name, size, 6);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700420
Mark Salyzyn758058f2015-08-21 16:44:30 -0700421 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700422 if (worstUidEnabledForLogid(id)) {
423 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800424 for (LogStatistics::uidTable_t::const_iterator it =
425 stat.uidTable[id].begin();
426 it != stat.uidTable[id].end(); ++it) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700427 totalDropped += it->second.dropped_count();
Mark Salyzync723df82015-08-24 11:08:00 -0700428 }
Tom Cherry64e90162020-05-07 14:44:43 -0700429 size_t sizes = stat.mSizes[id];
430 size_t totalSize = stat.mSizesTotal[id];
431 size_t totalElements = stat.mElementsTotal[id];
Mark Salyzyn501c3732017-03-10 14:31:54 -0800432 float totalVirtualSize =
433 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700434 size_t entrySize = getSizes();
435 float virtualEntrySize = entrySize;
436 int realPermille = virtualEntrySize * 1000.0 / sizes;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700437 size_t dropped = dropped_count();
Mark Salyzync723df82015-08-24 11:08:00 -0700438 if (dropped) {
439 pruned = android::base::StringPrintf("%zu", dropped);
440 virtualEntrySize += (float)dropped * totalSize / totalElements;
441 }
442 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800443 int permille =
444 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700445 if ((permille < -1) || (1 < permille)) {
446 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800447 const char* units = "%";
448 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700449
450 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800451 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700452 units = "X";
453 prefix = "";
454 }
455 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800456 change = android::base::StringPrintf(
457 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700458 ((permille < 0) ? (-permille % 10) : (permille % 10)),
459 units);
460 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800461 change = android::base::StringPrintf(
462 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700463 }
Tom Cherry9787f9a2020-05-19 19:01:16 -0700464 ssize_t spaces = EntryBase::PRUNED_LEN - 2 - pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700465 if ((spaces <= 0) && pruned.length()) {
466 spaces = 1;
467 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000468 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700469 change += android::base::StringPrintf("%*s", (int)spaces, "");
470 }
471 pruned = change + pruned;
472 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700473 }
474
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700475 std::string output = formatLine(name, size, pruned);
476
Tom Cherry9787f9a2020-05-19 19:01:16 -0700477 if (uid_ != AID_SYSTEM) {
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700478 return output;
479 }
480
481 static const size_t maximum_sorted_entries = 32;
Tom Cherryb6b78e92020-05-07 09:13:12 -0700482 std::array<const PidEntry*, maximum_sorted_entries> sorted;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700483 stat.pidSystemTable[id].MaxEntries(uid_, 0, &sorted);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700484
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700485 std::string byPid;
486 size_t index;
487 bool hasDropped = false;
488 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800489 const PidEntry* entry = sorted[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700490 if (!entry) {
491 break;
492 }
493 if (entry->getSizes() <= (getSizes() / 100)) {
494 break;
495 }
Tom Cherry9787f9a2020-05-19 19:01:16 -0700496 if (entry->dropped_count()) {
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700497 hasDropped = true;
498 }
499 byPid += entry->format(stat, id);
500 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800501 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700502 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800503 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
504 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700505 output += byPid;
506 }
507
508 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700509}
510
Mark Salyzyn501c3732017-03-10 14:31:54 -0800511std::string PidEntry::formatHeader(const std::string& name,
512 log_id_t /* id */) const {
513 return formatLine(name, std::string("Size"), std::string("Pruned")) +
514 formatLine(std::string(" PID/UID COMMAND LINE"),
515 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700516}
517
Tom Cherry64e90162020-05-07 14:44:43 -0700518std::string PidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
519 REQUIRES(stat.lock_) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700520 std::string name = android::base::StringPrintf("%5u/%u", pid_, uid_);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800521 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700522
Tom Cherry9787f9a2020-05-19 19:01:16 -0700523 stat.FormatTmp(name_, uid_, name, size, 12);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700524
Mark Salyzyn758058f2015-08-21 16:44:30 -0700525 std::string pruned = "";
Tom Cherry9787f9a2020-05-19 19:01:16 -0700526 size_t dropped = dropped_count();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700527 if (dropped) {
528 pruned = android::base::StringPrintf("%zu", dropped);
529 }
530
531 return formatLine(name, size, pruned);
532}
533
Mark Salyzyn501c3732017-03-10 14:31:54 -0800534std::string TidEntry::formatHeader(const std::string& name,
535 log_id_t /* id */) const {
536 return formatLine(name, std::string("Size"), std::string("Pruned")) +
537 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700538 std::string("NUM"));
539}
540
Tom Cherry64e90162020-05-07 14:44:43 -0700541std::string TidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
542 REQUIRES(stat.lock_) {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700543 std::string name = android::base::StringPrintf("%5u/%u", tid(), uid_);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800544 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700545
Tom Cherry9787f9a2020-05-19 19:01:16 -0700546 stat.FormatTmp(name_, uid_, name, size, 12);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700547
Mark Salyzyn758058f2015-08-21 16:44:30 -0700548 std::string pruned = "";
Tom Cherry9787f9a2020-05-19 19:01:16 -0700549 size_t dropped = dropped_count();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700550 if (dropped) {
551 pruned = android::base::StringPrintf("%zu", dropped);
552 }
553
554 return formatLine(name, size, pruned);
555}
556
Mark Salyzyn501c3732017-03-10 14:31:54 -0800557std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700558 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800559 return formatLine(name, std::string("Size"),
560 std::string(isprune ? "Prune" : "")) +
561 formatLine(std::string(" TAG/UID TAGNAME"),
562 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700563}
564
Mark Salyzyn501c3732017-03-10 14:31:54 -0800565std::string TagEntry::format(const LogStatistics& /* stat */,
566 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700567 std::string name;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700568 if (uid_ == (uid_t)-1) {
569 name = android::base::StringPrintf("%7u", key());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700570 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700571 name = android::base::StringPrintf("%7u/%u", key(), uid_);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700572 }
Tom Cherry9787f9a2020-05-19 19:01:16 -0700573 const char* nameTmp = this->name();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700574 if (nameTmp) {
575 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800576 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700577 }
578
Mark Salyzyn501c3732017-03-10 14:31:54 -0800579 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700580
581 std::string pruned = "";
Tom Cherry9787f9a2020-05-19 19:01:16 -0700582 size_t dropped = dropped_count();
Mark Salyzyn6a066942016-07-14 15:34:30 -0700583 if (dropped) {
584 pruned = android::base::StringPrintf("%zu", dropped);
585 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700586
587 return formatLine(name, size, pruned);
588}
589
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700590std::string TagNameEntry::formatHeader(const std::string& name,
591 log_id_t /* id */) const {
592 return formatLine(name, std::string("Size"), std::string("")) +
593 formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
594 std::string("BYTES"), std::string(""));
595}
596
597std::string TagNameEntry::format(const LogStatistics& /* stat */,
598 log_id_t /* id */) const {
599 std::string name;
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700600 std::string pidstr;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700601 if (pid_ != (pid_t)-1) {
602 pidstr = android::base::StringPrintf("%u", pid_);
603 if (tid_ != (pid_t)-1 && tid_ != pid_) pidstr = "/" + pidstr;
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700604 }
605 int len = 9 - pidstr.length();
606 if (len < 0) len = 0;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700607 if (tid_ == (pid_t)-1 || tid_ == pid_) {
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700608 name = android::base::StringPrintf("%*s", len, "");
609 } else {
Tom Cherry9787f9a2020-05-19 19:01:16 -0700610 name = android::base::StringPrintf("%*u", len, tid_);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700611 }
612 name += pidstr;
Tom Cherry9787f9a2020-05-19 19:01:16 -0700613 if (uid_ != (uid_t)-1) {
614 name += android::base::StringPrintf("/%u", uid_);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700615 }
616
617 std::string size = android::base::StringPrintf("%zu", getSizes());
618
Tom Cherry9787f9a2020-05-19 19:01:16 -0700619 const char* nameTmp = this->name();
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700620 if (nameTmp) {
621 size_t lenSpace = std::max(16 - name.length(), (size_t)1);
Tom Cherry9787f9a2020-05-19 19:01:16 -0700622 size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
623 lenSpace - 2;
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700624 size_t lenNameTmp = strlen(nameTmp);
625 while ((len < lenNameTmp) && (lenSpace > 1)) {
626 ++len;
627 --lenSpace;
628 }
629 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
630 if (len < lenNameTmp) {
631 name += "...";
632 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
633 }
634 name += nameTmp;
635 }
636
637 std::string pruned = "";
638
639 return formatLine(name, size, pruned);
640}
641
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700642static std::string formatMsec(uint64_t val) {
643 static const unsigned subsecDigits = 3;
644 static const uint64_t sec = MS_PER_SEC;
645
646 static const uint64_t minute = 60 * sec;
647 static const uint64_t hour = 60 * minute;
648 static const uint64_t day = 24 * hour;
649
650 std::string output;
651 if (val < sec) return output;
652
653 if (val >= day) {
654 output = android::base::StringPrintf("%" PRIu64 "d ", val / day);
655 val = (val % day) + day;
656 }
657 if (val >= minute) {
658 if (val >= hour) {
659 output += android::base::StringPrintf("%" PRIu64 ":",
660 (val / hour) % (day / hour));
661 }
662 output += android::base::StringPrintf(
663 (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
664 (val / minute) % (hour / minute));
665 }
666 output +=
667 android::base::StringPrintf((val >= minute) ? "%02" PRIu64 : "%" PRIu64,
668 (val / sec) % (minute / sec));
669 val %= sec;
670 unsigned digits = subsecDigits;
671 while (digits && ((val % 10) == 0)) {
672 val /= 10;
673 --digits;
674 }
675 if (digits) {
676 output += android::base::StringPrintf(".%0*" PRIu64, digits, val);
677 }
678 return output;
679}
680
Tom Cherry64e90162020-05-07 14:44:43 -0700681template <typename TKey, typename TEntry>
682std::string LogStatistics::FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid,
683 pid_t pid, const std::string& name, log_id_t id) const
684 REQUIRES(lock_) {
685 static const size_t maximum_sorted_entries = 32;
686 std::string output;
687 std::array<const TEntry*, maximum_sorted_entries> sorted;
688 table.MaxEntries(uid, pid, &sorted);
689 bool header_printed = false;
690 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
691 const TEntry* entry = sorted[index];
692 if (!entry) {
693 break;
694 }
695 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
696 break;
697 }
698 if (!header_printed) {
699 output += "\n\n";
700 output += entry->formatHeader(name, id);
701 header_printed = true;
702 }
703 output += entry->format(*this, id);
704 }
705 return output;
706}
707
708std::string LogStatistics::Format(uid_t uid, pid_t pid, unsigned int logMask) const {
709 auto lock = std::lock_guard{lock_};
710
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700711 static const uint16_t spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800712
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700713 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800714
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700715 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700716 size_t oldLength;
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700717 int16_t spaces = 1;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700718
719 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700720 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700721 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700722 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700723 output += android::base::StringPrintf("%*s%s", spaces, "",
724 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700725 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800726 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700727 if (spaces < 0) spaces = 0;
728 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800729
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700730 static const char TotalStr[] = "\nTotal";
731 spaces = 10 - strlen(TotalStr);
732 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800733
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700734 size_t totalSize = 0;
735 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700736 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700737 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700738 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700739 if (spaces < 0) spaces = 0;
Tom Cherry64e90162020-05-07 14:44:43 -0700740 size_t szs = mSizesTotal[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700741 totalSize += szs;
Tom Cherry64e90162020-05-07 14:44:43 -0700742 size_t els = mElementsTotal[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700743 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800744 output +=
745 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700746 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800747 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700748 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800749 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
750 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800751
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700752 static const char NowStr[] = "\nNow";
753 spaces = 10 - strlen(NowStr);
754 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800755
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700756 totalSize = 0;
757 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700758 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700759 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800760
Tom Cherry64e90162020-05-07 14:44:43 -0700761 size_t els = mElements[id];
Mark Salyzyn34facab2014-02-06 14:48:50 -0800762 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700763 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700764 if (spaces < 0) spaces = 0;
Tom Cherry64e90162020-05-07 14:44:43 -0700765 size_t szs = mSizes[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700766 totalSize += szs;
767 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800768 output +=
769 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700770 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800771 }
772 spaces += spaces_total;
773 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700774 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800775 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
776 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700777
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700778 static const char SpanStr[] = "\nLogspan";
779 spaces = 10 - strlen(SpanStr);
780 output += SpanStr;
781
782 // Total reports the greater of the individual maximum time span, or the
783 // validated minimum start and maximum end time span if it makes sense.
784 uint64_t minTime = UINT64_MAX;
785 uint64_t maxTime = 0;
786 uint64_t maxSpan = 0;
787 totalSize = 0;
788
789 log_id_for_each(id) {
790 if (!(logMask & (1 << id))) continue;
791
792 // validity checking
793 uint64_t oldest = mOldest[id].msec();
794 uint64_t newest = mNewest[id].msec();
795 if (newest <= oldest) {
796 spaces += spaces_total;
797 continue;
798 }
799
800 uint64_t span = newest - oldest;
801 if (span > (monthSec * MS_PER_SEC)) {
802 spaces += spaces_total;
803 continue;
804 }
805
806 // total span
807 if (minTime > oldest) minTime = oldest;
808 if (maxTime < newest) maxTime = newest;
809 if (span > maxSpan) maxSpan = span;
810 totalSize += span;
811
812 uint64_t dropped = mNewestDropped[id].msec();
813 if (dropped < oldest) dropped = oldest;
814 if (dropped > newest) dropped = newest;
815
816 oldLength = output.length();
817 output += android::base::StringPrintf("%*s%s", spaces, "",
818 formatMsec(span).c_str());
819 unsigned permille = ((newest - dropped) * 1000 + (span / 2)) / span;
820 if ((permille > 1) && (permille < 999)) {
821 output += android::base::StringPrintf("(%u", permille / 10);
822 permille %= 10;
823 if (permille) {
824 output += android::base::StringPrintf(".%u", permille);
825 }
826 output += android::base::StringPrintf("%%)");
827 }
828 spaces -= output.length() - oldLength;
829 spaces += spaces_total;
830 }
831 if ((maxTime > minTime) && ((maxTime -= minTime) < totalSize) &&
832 (maxTime > maxSpan)) {
833 maxSpan = maxTime;
834 }
835 if (spaces < 0) spaces = 0;
836 output += android::base::StringPrintf("%*s%s", spaces, "",
837 formatMsec(maxSpan).c_str());
838
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700839 static const char OverheadStr[] = "\nOverhead";
840 spaces = 10 - strlen(OverheadStr);
841 output += OverheadStr;
842
843 totalSize = 0;
844 log_id_for_each(id) {
845 if (!(logMask & (1 << id))) continue;
846
Tom Cherry64e90162020-05-07 14:44:43 -0700847 size_t els = mElements[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700848 if (els) {
849 oldLength = output.length();
850 if (spaces < 0) spaces = 0;
851 // estimate the std::list overhead.
852 static const size_t overhead =
853 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800854 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700855 sizeof(std::list<LogBufferElement*>);
Tom Cherry64e90162020-05-07 14:44:43 -0700856 size_t szs = mSizes[id] + els * overhead;
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700857 totalSize += szs;
858 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
859 spaces -= output.length() - oldLength;
860 }
861 spaces += spaces_total;
862 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700863 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700864 if (spaces < 0) spaces = 0;
865 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800866
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700867 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700868
Mark Salyzyn758058f2015-08-21 16:44:30 -0700869 std::string name;
870
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700871 // Chattiest by application (UID)
872 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700873 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700874
Mark Salyzyn501c3732017-03-10 14:31:54 -0800875 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
876 : "Logging for your UID in %s log buffer:";
Tom Cherry64e90162020-05-07 14:44:43 -0700877 output += FormatTable(uidTable[id], uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700878 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700879
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700880 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800881 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
882 : "Logging for this PID:";
Tom Cherry64e90162020-05-07 14:44:43 -0700883 output += FormatTable(pidTable, uid, pid, name);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800884 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700885 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800886 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700887 output += FormatTable(tidTable, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700888 }
889
Mark Salyzyn344bff42015-04-13 14:24:45 -0700890 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800891 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700892 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800893 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700894 output += FormatTable(tagTable, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700895 }
896
Mark Salyzyn083b0372015-12-04 10:59:45 -0800897 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800898 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700899 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800900 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700901 output += FormatTable(securityTagTable, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800902 }
903
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700904 if (enable) {
905 name = "Chattiest TAGs";
906 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
907 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700908 output += FormatTable(tagNameTable, uid, pid, name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700909 }
910
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700911 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800912}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700913
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700914namespace android {
915
916uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700917 char buffer[512];
918 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800919 FILE* fp = fopen(buffer, "r");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700920 if (fp) {
921 while (fgets(buffer, sizeof(buffer), fp)) {
Mark Salyzync4e48232017-05-04 13:54:46 -0700922 int uid = AID_LOGD;
923 char space = 0;
924 if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
925 isspace(space)) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700926 fclose(fp);
927 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700928 }
929 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700930 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700931 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800932 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700933}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700934}
935
Tom Cherry64e90162020-05-07 14:44:43 -0700936uid_t LogStatistics::PidToUid(pid_t pid) {
937 auto lock = std::lock_guard{lock_};
Tom Cherry9787f9a2020-05-19 19:01:16 -0700938 return pidTable.Add(pid)->second.uid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700939}
940
941// caller must free character string
Tom Cherry64e90162020-05-07 14:44:43 -0700942const char* LogStatistics::PidToName(pid_t pid) const {
943 auto lock = std::lock_guard{lock_};
Mark Salyzyn758058f2015-08-21 16:44:30 -0700944 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800945 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
Tom Cherry9787f9a2020-05-19 19:01:16 -0700946 const char* name = writablePidTable.Add(pid)->second.name();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700947 if (!name) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700948 return nullptr;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700949 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700950 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700951}