blob: 14bcb639546e6235c326dd6198d60ac257bed6e6 [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
Mark Salyzyn03bb7592017-04-14 09:46:57 -070032static const uint64_t hourSec = 60 * 60;
33static const uint64_t monthSec = 31 * 24 * hourSec;
34
Tom Cherry64e90162020-05-07 14:44:43 -070035std::atomic<size_t> LogStatistics::SizesTotal;
Mark Salyzyn32962912016-09-12 10:29:17 -070036
Tom Cherry64e90162020-05-07 14:44:43 -070037LogStatistics::LogStatistics(bool enable_statistics) : enable(enable_statistics) {
Mark Salyzyn03bb7592017-04-14 09:46:57 -070038 log_time now(CLOCK_REALTIME);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070039 log_id_for_each(id) {
40 mSizes[id] = 0;
41 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070042 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070043 mSizesTotal[id] = 0;
44 mElementsTotal[id] = 0;
Mark Salyzyn03bb7592017-04-14 09:46:57 -070045 mOldest[id] = now;
46 mNewest[id] = now;
47 mNewestDropped[id] = now;
Mark Salyzyn34facab2014-02-06 14:48:50 -080048 }
49}
50
Mark Salyzyn720f6d12015-03-16 08:26:05 -070051namespace android {
52
Mark Salyzyn501c3732017-03-10 14:31:54 -080053size_t sizesTotal() {
54 return LogStatistics::sizesTotal();
55}
Mark Salyzyn32962912016-09-12 10:29:17 -070056
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070057// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -080058char* pidToName(pid_t pid) {
Yi Kongc8d09dd2018-07-13 17:39:22 -070059 char* retval = nullptr;
Mark Salyzyn501c3732017-03-10 14:31:54 -080060 if (pid == 0) { // special case from auditd/klogd for kernel
Mark Salyzynae4d9282014-10-15 08:49:39 -070061 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070062 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070063 char buffer[512];
64 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
65 int fd = open(buffer, O_RDONLY);
66 if (fd >= 0) {
67 ssize_t ret = read(fd, buffer, sizeof(buffer));
68 if (ret > 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080069 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn9a038632014-04-07 07:05:40 -070070 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080071 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070072 retval = strdup(buffer);
73 }
74 }
75 close(fd);
76 }
77 }
78 return retval;
79}
Mark Salyzyn720f6d12015-03-16 08:26:05 -070080}
81
Tom Cherry64e90162020-05-07 14:44:43 -070082void LogStatistics::AddTotal(LogBufferElement* element) {
83 auto lock = std::lock_guard{lock_};
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070084 if (element->getDropped()) return;
85
86 log_id_t log_id = element->getLogId();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -070087 uint16_t size = element->getMsgLen();
Mark Salyzyn02dd2f42017-04-14 09:46:57 -070088 mSizesTotal[log_id] += size;
89 SizesTotal += size;
90 ++mElementsTotal[log_id];
91}
92
Tom Cherry64e90162020-05-07 14:44:43 -070093void LogStatistics::Add(LogBufferElement* element) {
94 auto lock = std::lock_guard{lock_};
Mark Salyzyn758058f2015-08-21 16:44:30 -070095 log_id_t log_id = element->getLogId();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -070096 uint16_t size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080097 mSizes[log_id] += size;
98 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070099
Mark Salyzyn02dd2f42017-04-14 09:46:57 -0700100 // When caller adding a chatty entry, they will have already
101 // called add() and subtract() for each entry as they are
102 // evaluated and trimmed, thus recording size and number of
103 // elements, but we must recognize the manufactured dropped
104 // entry as not contributing to the lifetime totals.
Mark Salyzyna2c02222016-12-13 10:31:29 -0800105 if (element->getDropped()) {
106 ++mDroppedElements[log_id];
107 } else {
Mark Salyzyna2c02222016-12-13 10:31:29 -0800108 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -0700109 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -0800110 ++mElementsTotal[log_id];
111 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700112
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700113 log_time stamp(element->getRealTime());
114 if (mNewest[log_id] < stamp) {
115 // A major time update invalidates the statistics :-(
116 log_time diff = stamp - mNewest[log_id];
117 mNewest[log_id] = stamp;
118
119 if (diff.tv_sec > hourSec) {
120 // approximate Do-Your-Best fixup
121 diff += mOldest[log_id];
122 if ((diff > stamp) && ((diff - stamp).tv_sec < hourSec)) {
123 diff = stamp;
124 }
125 if (diff <= stamp) {
126 mOldest[log_id] = diff;
127 if (mNewestDropped[log_id] < diff) {
128 mNewestDropped[log_id] = diff;
129 }
130 }
131 }
132 }
133
Mark Salyzynae4d9282014-10-15 08:49:39 -0700134 if (log_id == LOG_ID_KERNEL) {
135 return;
136 }
137
Mark Salyzyn758058f2015-08-21 16:44:30 -0700138 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700139 if (element->getUid() == AID_SYSTEM) {
140 pidSystemTable[log_id].add(element->getPid(), element);
141 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700142
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700143 if (!enable) {
144 return;
145 }
146
Mark Salyzyn758058f2015-08-21 16:44:30 -0700147 pidTable.add(element->getPid(), element);
148 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700149
Mark Salyzyn758058f2015-08-21 16:44:30 -0700150 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700151 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800152 if (log_id == LOG_ID_SECURITY) {
153 securityTagTable.add(tag, element);
154 } else {
155 tagTable.add(tag, element);
156 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700157 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700158
159 if (!element->getDropped()) {
160 tagNameTable.add(TagNameKey(element), element);
161 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800162}
163
Tom Cherry64e90162020-05-07 14:44:43 -0700164void LogStatistics::Subtract(LogBufferElement* element) {
165 auto lock = std::lock_guard{lock_};
Mark Salyzyn758058f2015-08-21 16:44:30 -0700166 log_id_t log_id = element->getLogId();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700167 uint16_t size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800168 mSizes[log_id] -= size;
169 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700170 if (element->getDropped()) {
171 --mDroppedElements[log_id];
172 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700173
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700174 if (mOldest[log_id] < element->getRealTime()) {
175 mOldest[log_id] = element->getRealTime();
176 }
177
Mark Salyzynae4d9282014-10-15 08:49:39 -0700178 if (log_id == LOG_ID_KERNEL) {
179 return;
180 }
181
Mark Salyzyn758058f2015-08-21 16:44:30 -0700182 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700183 if (element->getUid() == AID_SYSTEM) {
184 pidSystemTable[log_id].subtract(element->getPid(), element);
185 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800186
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700187 if (!enable) {
188 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800189 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700190
Mark Salyzyn758058f2015-08-21 16:44:30 -0700191 pidTable.subtract(element->getPid(), element);
192 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700193
Mark Salyzyn758058f2015-08-21 16:44:30 -0700194 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700195 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800196 if (log_id == LOG_ID_SECURITY) {
197 securityTagTable.subtract(tag, element);
198 } else {
199 tagTable.subtract(tag, element);
200 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700201 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700202
203 if (!element->getDropped()) {
204 tagNameTable.subtract(TagNameKey(element), element);
205 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800206}
207
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700208// Atomically set an entry to drop
209// entry->setDropped(1) must follow this call, caller should do this explicitly.
Tom Cherry64e90162020-05-07 14:44:43 -0700210void LogStatistics::Drop(LogBufferElement* element) {
211 auto lock = std::lock_guard{lock_};
Mark Salyzyn758058f2015-08-21 16:44:30 -0700212 log_id_t log_id = element->getLogId();
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700213 uint16_t size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700214 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700215 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700216
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700217 if (mNewestDropped[log_id] < element->getRealTime()) {
218 mNewestDropped[log_id] = element->getRealTime();
219 }
220
Mark Salyzyn758058f2015-08-21 16:44:30 -0700221 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700222 if (element->getUid() == AID_SYSTEM) {
223 pidSystemTable[log_id].drop(element->getPid(), element);
224 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700225
226 if (!enable) {
227 return;
228 }
229
Mark Salyzyn758058f2015-08-21 16:44:30 -0700230 pidTable.drop(element->getPid(), element);
231 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700232
233 uint32_t tag = element->getTag();
234 if (tag) {
235 if (log_id == LOG_ID_SECURITY) {
236 securityTagTable.drop(tag, element);
237 } else {
238 tagTable.drop(tag, element);
239 }
240 }
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700241
242 tagNameTable.subtract(TagNameKey(element), element);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700243}
244
Tom Cherry64e90162020-05-07 14:44:43 -0700245const char* LogStatistics::UidToName(uid_t uid) const {
246 auto lock = std::lock_guard{lock_};
247 return UidToNameLocked(uid);
248}
249
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700250// caller must own and free character string
Tom Cherry64e90162020-05-07 14:44:43 -0700251const char* LogStatistics::UidToNameLocked(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700252 // Local hard coded favourites
253 if (uid == AID_LOGD) {
254 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800255 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700256
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700257 // Android system
258 if (uid < AID_APP) {
259 // in bionic, thread safe as long as we copy the results
Mark Salyzyn501c3732017-03-10 14:31:54 -0800260 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700261 if (pwd) {
262 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700263 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800264 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700265
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700266 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700267 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800268 const char* name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700269 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
270 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
271 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700272 if (name) {
273 return name;
274 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700275
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700276 // Android application
277 if (uid >= AID_APP) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800278 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700279 if (pwd) {
280 return strdup(pwd->pw_name);
281 }
282 }
283
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700284 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn501c3732017-03-10 14:31:54 -0800285 for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
286 ++it) {
287 const PidEntry& entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700288
289 if (entry.getUid() == uid) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800290 const char* nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700291
Mark Salyzyn758058f2015-08-21 16:44:30 -0700292 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700293 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700294 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800295 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800296 free(const_cast<char*>(name));
Yi Kongc8d09dd2018-07-13 17:39:22 -0700297 name = nullptr;
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700298 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700299 }
300 }
301 }
302 }
303
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700304 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700305 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800306}
307
Tom Cherryb6b78e92020-05-07 09:13:12 -0700308template <typename TKey, typename TEntry>
309void LogStatistics::WorstTwoWithThreshold(const LogHashtable<TKey, TEntry>& table, size_t threshold,
310 int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700311 size_t* second_worst_sizes) const {
Tom Cherryb6b78e92020-05-07 09:13:12 -0700312 std::array<const TEntry*, 2> max_entries;
313 table.MaxEntries(AID_ROOT, 0, &max_entries);
314 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
315 return;
316 }
317 *worst_sizes = max_entries[0]->getSizes();
318 // b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
319 // 100 characters.
320 if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->getDropped())) {
321 *worst = max_entries[0]->getKey();
322 *second_worst_sizes = max_entries[1]->getSizes();
323 if (*second_worst_sizes < threshold) {
324 *second_worst_sizes = threshold;
325 }
326 }
327}
328
329void LogStatistics::WorstTwoUids(log_id id, size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700330 size_t* second_worst_sizes) const {
331 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700332 WorstTwoWithThreshold(uidTable[id], threshold, worst, worst_sizes, second_worst_sizes);
333}
334
335void LogStatistics::WorstTwoTags(size_t threshold, int* worst, size_t* worst_sizes,
Tom Cherry64e90162020-05-07 14:44:43 -0700336 size_t* second_worst_sizes) const {
337 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700338 WorstTwoWithThreshold(tagTable, threshold, worst, worst_sizes, second_worst_sizes);
339}
340
341void LogStatistics::WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* worst,
Tom Cherry64e90162020-05-07 14:44:43 -0700342 size_t* second_worst_sizes) const {
343 auto lock = std::lock_guard{lock_};
Tom Cherryb6b78e92020-05-07 09:13:12 -0700344 std::array<const PidEntry*, 2> max_entries;
345 pidSystemTable[id].MaxEntries(AID_SYSTEM, 0, &max_entries);
346 if (max_entries[0] == nullptr || max_entries[1] == nullptr) {
347 return;
348 }
349
350 *worst = max_entries[0]->getKey();
351 *second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes();
352}
353
Tom Cherry64e90162020-05-07 14:44:43 -0700354// Prune at most 10% of the log entries or maxPrune, whichever is less.
355bool LogStatistics::ShouldPrune(log_id id, unsigned long max_size,
356 unsigned long* prune_rows) const {
357 static constexpr size_t kMinPrune = 4;
358 static constexpr size_t kMaxPrune = 256;
359
360 auto lock = std::lock_guard{lock_};
361 size_t sizes = mSizes[id];
362 if (sizes <= max_size) {
363 return false;
364 }
365 size_t size_over = sizes - ((max_size * 9) / 10);
366 size_t elements = mElements[id] - mDroppedElements[id];
367 size_t min_elements = elements / 100;
368 if (min_elements < kMinPrune) {
369 min_elements = kMinPrune;
370 }
371 *prune_rows = elements * size_over / sizes;
372 if (*prune_rows < min_elements) {
373 *prune_rows = min_elements;
374 }
375 if (*prune_rows > kMaxPrune) {
376 *prune_rows = kMaxPrune;
377 }
378
379 return true;
380}
381
Mark Salyzyn501c3732017-03-10 14:31:54 -0800382std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700383 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800384 return formatLine(android::base::StringPrintf(name.c_str(),
385 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700386 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800387 std::string(isprune ? "+/- Pruned" : "")) +
388 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700389 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800390}
391
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700392// Helper to truncate name, if too long, and add name dressings
Tom Cherry64e90162020-05-07 14:44:43 -0700393void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size,
394 size_t nameLen) const {
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700395 const char* allocNameTmp = nullptr;
Tom Cherry64e90162020-05-07 14:44:43 -0700396 if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700397 if (nameTmp) {
398 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
399 size_t len = EntryBaseConstants::total_len -
400 EntryBaseConstants::pruned_len - size.length() -
401 name.length() - lenSpace - 2;
402 size_t lenNameTmp = strlen(nameTmp);
403 while ((len < lenNameTmp) && (lenSpace > 1)) {
404 ++len;
405 --lenSpace;
406 }
407 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
408 if (len < lenNameTmp) {
409 name += "...";
410 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
411 }
412 name += nameTmp;
413 free(const_cast<char*>(allocNameTmp));
414 }
415}
416
Tom Cherry64e90162020-05-07 14:44:43 -0700417std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUIRES(stat.lock_) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800418 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700419 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700420 std::string size = android::base::StringPrintf("%zu", getSizes());
421
Tom Cherry64e90162020-05-07 14:44:43 -0700422 stat.FormatTmp(nullptr, uid, name, size, 6);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700423
Mark Salyzyn758058f2015-08-21 16:44:30 -0700424 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700425 if (worstUidEnabledForLogid(id)) {
426 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800427 for (LogStatistics::uidTable_t::const_iterator it =
428 stat.uidTable[id].begin();
429 it != stat.uidTable[id].end(); ++it) {
Mark Salyzync723df82015-08-24 11:08:00 -0700430 totalDropped += it->second.getDropped();
431 }
Tom Cherry64e90162020-05-07 14:44:43 -0700432 size_t sizes = stat.mSizes[id];
433 size_t totalSize = stat.mSizesTotal[id];
434 size_t totalElements = stat.mElementsTotal[id];
Mark Salyzyn501c3732017-03-10 14:31:54 -0800435 float totalVirtualSize =
436 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700437 size_t entrySize = getSizes();
438 float virtualEntrySize = entrySize;
439 int realPermille = virtualEntrySize * 1000.0 / sizes;
440 size_t dropped = getDropped();
441 if (dropped) {
442 pruned = android::base::StringPrintf("%zu", dropped);
443 virtualEntrySize += (float)dropped * totalSize / totalElements;
444 }
445 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800446 int permille =
447 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700448 if ((permille < -1) || (1 < permille)) {
449 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800450 const char* units = "%";
451 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700452
453 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800454 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700455 units = "X";
456 prefix = "";
457 }
458 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800459 change = android::base::StringPrintf(
460 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700461 ((permille < 0) ? (-permille % 10) : (permille % 10)),
462 units);
463 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800464 change = android::base::StringPrintf(
465 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700466 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800467 ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
468 pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700469 if ((spaces <= 0) && pruned.length()) {
470 spaces = 1;
471 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000472 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700473 change += android::base::StringPrintf("%*s", (int)spaces, "");
474 }
475 pruned = change + pruned;
476 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700477 }
478
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700479 std::string output = formatLine(name, size, pruned);
480
481 if (uid != AID_SYSTEM) {
482 return output;
483 }
484
485 static const size_t maximum_sorted_entries = 32;
Tom Cherryb6b78e92020-05-07 09:13:12 -0700486 std::array<const PidEntry*, maximum_sorted_entries> sorted;
487 stat.pidSystemTable[id].MaxEntries(uid, 0, &sorted);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700488
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700489 std::string byPid;
490 size_t index;
491 bool hasDropped = false;
492 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800493 const PidEntry* entry = sorted[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700494 if (!entry) {
495 break;
496 }
497 if (entry->getSizes() <= (getSizes() / 100)) {
498 break;
499 }
500 if (entry->getDropped()) {
501 hasDropped = true;
502 }
503 byPid += entry->format(stat, id);
504 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800505 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700506 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800507 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
508 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700509 output += byPid;
510 }
511
512 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700513}
514
Mark Salyzyn501c3732017-03-10 14:31:54 -0800515std::string PidEntry::formatHeader(const std::string& name,
516 log_id_t /* id */) const {
517 return formatLine(name, std::string("Size"), std::string("Pruned")) +
518 formatLine(std::string(" PID/UID COMMAND LINE"),
519 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700520}
521
Tom Cherry64e90162020-05-07 14:44:43 -0700522std::string PidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
523 REQUIRES(stat.lock_) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700524 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800525 pid_t pid = getPid();
526 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800527 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700528
Tom Cherry64e90162020-05-07 14:44:43 -0700529 stat.FormatTmp(getName(), uid, name, size, 12);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700530
Mark Salyzyn758058f2015-08-21 16:44:30 -0700531 std::string pruned = "";
532 size_t dropped = getDropped();
533 if (dropped) {
534 pruned = android::base::StringPrintf("%zu", dropped);
535 }
536
537 return formatLine(name, size, pruned);
538}
539
Mark Salyzyn501c3732017-03-10 14:31:54 -0800540std::string TidEntry::formatHeader(const std::string& name,
541 log_id_t /* id */) const {
542 return formatLine(name, std::string("Size"), std::string("Pruned")) +
543 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700544 std::string("NUM"));
545}
546
Tom Cherry64e90162020-05-07 14:44:43 -0700547std::string TidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
548 REQUIRES(stat.lock_) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700549 uid_t uid = getUid();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800550 std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800551 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700552
Tom Cherry64e90162020-05-07 14:44:43 -0700553 stat.FormatTmp(getName(), uid, name, size, 12);
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700554
Mark Salyzyn758058f2015-08-21 16:44:30 -0700555 std::string pruned = "";
556 size_t dropped = getDropped();
557 if (dropped) {
558 pruned = android::base::StringPrintf("%zu", dropped);
559 }
560
561 return formatLine(name, size, pruned);
562}
563
Mark Salyzyn501c3732017-03-10 14:31:54 -0800564std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700565 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800566 return formatLine(name, std::string("Size"),
567 std::string(isprune ? "Prune" : "")) +
568 formatLine(std::string(" TAG/UID TAGNAME"),
569 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700570}
571
Mark Salyzyn501c3732017-03-10 14:31:54 -0800572std::string TagEntry::format(const LogStatistics& /* stat */,
573 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700574 std::string name;
575 uid_t uid = getUid();
576 if (uid == (uid_t)-1) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800577 name = android::base::StringPrintf("%7u", getKey());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700578 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800579 name = android::base::StringPrintf("%7u/%u", getKey(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700580 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800581 const char* nameTmp = getName();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700582 if (nameTmp) {
583 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800584 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700585 }
586
Mark Salyzyn501c3732017-03-10 14:31:54 -0800587 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700588
589 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700590 size_t dropped = getDropped();
591 if (dropped) {
592 pruned = android::base::StringPrintf("%zu", dropped);
593 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700594
595 return formatLine(name, size, pruned);
596}
597
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700598std::string TagNameEntry::formatHeader(const std::string& name,
599 log_id_t /* id */) const {
600 return formatLine(name, std::string("Size"), std::string("")) +
601 formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
602 std::string("BYTES"), std::string(""));
603}
604
605std::string TagNameEntry::format(const LogStatistics& /* stat */,
606 log_id_t /* id */) const {
607 std::string name;
608 pid_t tid = getTid();
609 pid_t pid = getPid();
610 std::string pidstr;
611 if (pid != (pid_t)-1) {
612 pidstr = android::base::StringPrintf("%u", pid);
613 if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr;
614 }
615 int len = 9 - pidstr.length();
616 if (len < 0) len = 0;
617 if ((tid == (pid_t)-1) || (tid == pid)) {
618 name = android::base::StringPrintf("%*s", len, "");
619 } else {
620 name = android::base::StringPrintf("%*u", len, tid);
621 }
622 name += pidstr;
623 uid_t uid = getUid();
624 if (uid != (uid_t)-1) {
625 name += android::base::StringPrintf("/%u", uid);
626 }
627
628 std::string size = android::base::StringPrintf("%zu", getSizes());
629
630 const char* nameTmp = getName();
631 if (nameTmp) {
632 size_t lenSpace = std::max(16 - name.length(), (size_t)1);
633 size_t len = EntryBaseConstants::total_len -
634 EntryBaseConstants::pruned_len - size.length() -
635 name.length() - lenSpace - 2;
636 size_t lenNameTmp = strlen(nameTmp);
637 while ((len < lenNameTmp) && (lenSpace > 1)) {
638 ++len;
639 --lenSpace;
640 }
641 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
642 if (len < lenNameTmp) {
643 name += "...";
644 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
645 }
646 name += nameTmp;
647 }
648
649 std::string pruned = "";
650
651 return formatLine(name, size, pruned);
652}
653
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700654static std::string formatMsec(uint64_t val) {
655 static const unsigned subsecDigits = 3;
656 static const uint64_t sec = MS_PER_SEC;
657
658 static const uint64_t minute = 60 * sec;
659 static const uint64_t hour = 60 * minute;
660 static const uint64_t day = 24 * hour;
661
662 std::string output;
663 if (val < sec) return output;
664
665 if (val >= day) {
666 output = android::base::StringPrintf("%" PRIu64 "d ", val / day);
667 val = (val % day) + day;
668 }
669 if (val >= minute) {
670 if (val >= hour) {
671 output += android::base::StringPrintf("%" PRIu64 ":",
672 (val / hour) % (day / hour));
673 }
674 output += android::base::StringPrintf(
675 (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
676 (val / minute) % (hour / minute));
677 }
678 output +=
679 android::base::StringPrintf((val >= minute) ? "%02" PRIu64 : "%" PRIu64,
680 (val / sec) % (minute / sec));
681 val %= sec;
682 unsigned digits = subsecDigits;
683 while (digits && ((val % 10) == 0)) {
684 val /= 10;
685 --digits;
686 }
687 if (digits) {
688 output += android::base::StringPrintf(".%0*" PRIu64, digits, val);
689 }
690 return output;
691}
692
Tom Cherry64e90162020-05-07 14:44:43 -0700693template <typename TKey, typename TEntry>
694std::string LogStatistics::FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid,
695 pid_t pid, const std::string& name, log_id_t id) const
696 REQUIRES(lock_) {
697 static const size_t maximum_sorted_entries = 32;
698 std::string output;
699 std::array<const TEntry*, maximum_sorted_entries> sorted;
700 table.MaxEntries(uid, pid, &sorted);
701 bool header_printed = false;
702 for (size_t index = 0; index < maximum_sorted_entries; ++index) {
703 const TEntry* entry = sorted[index];
704 if (!entry) {
705 break;
706 }
707 if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
708 break;
709 }
710 if (!header_printed) {
711 output += "\n\n";
712 output += entry->formatHeader(name, id);
713 header_printed = true;
714 }
715 output += entry->format(*this, id);
716 }
717 return output;
718}
719
720std::string LogStatistics::Format(uid_t uid, pid_t pid, unsigned int logMask) const {
721 auto lock = std::lock_guard{lock_};
722
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700723 static const uint16_t spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800724
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700725 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800726
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700727 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700728 size_t oldLength;
Chih-Hung Hsieh08d470b2018-08-13 14:22:56 -0700729 int16_t spaces = 1;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700730
731 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700732 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700733 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700734 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700735 output += android::base::StringPrintf("%*s%s", spaces, "",
736 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700737 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800738 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700739 if (spaces < 0) spaces = 0;
740 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800741
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700742 static const char TotalStr[] = "\nTotal";
743 spaces = 10 - strlen(TotalStr);
744 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800745
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700746 size_t totalSize = 0;
747 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700748 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700749 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700750 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700751 if (spaces < 0) spaces = 0;
Tom Cherry64e90162020-05-07 14:44:43 -0700752 size_t szs = mSizesTotal[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700753 totalSize += szs;
Tom Cherry64e90162020-05-07 14:44:43 -0700754 size_t els = mElementsTotal[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700755 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800756 output +=
757 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700758 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800759 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700760 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800761 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
762 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800763
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700764 static const char NowStr[] = "\nNow";
765 spaces = 10 - strlen(NowStr);
766 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800767
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700768 totalSize = 0;
769 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700770 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700771 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800772
Tom Cherry64e90162020-05-07 14:44:43 -0700773 size_t els = mElements[id];
Mark Salyzyn34facab2014-02-06 14:48:50 -0800774 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700775 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700776 if (spaces < 0) spaces = 0;
Tom Cherry64e90162020-05-07 14:44:43 -0700777 size_t szs = mSizes[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700778 totalSize += szs;
779 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800780 output +=
781 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700782 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800783 }
784 spaces += spaces_total;
785 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700786 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800787 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
788 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700789
Mark Salyzyn03bb7592017-04-14 09:46:57 -0700790 static const char SpanStr[] = "\nLogspan";
791 spaces = 10 - strlen(SpanStr);
792 output += SpanStr;
793
794 // Total reports the greater of the individual maximum time span, or the
795 // validated minimum start and maximum end time span if it makes sense.
796 uint64_t minTime = UINT64_MAX;
797 uint64_t maxTime = 0;
798 uint64_t maxSpan = 0;
799 totalSize = 0;
800
801 log_id_for_each(id) {
802 if (!(logMask & (1 << id))) continue;
803
804 // validity checking
805 uint64_t oldest = mOldest[id].msec();
806 uint64_t newest = mNewest[id].msec();
807 if (newest <= oldest) {
808 spaces += spaces_total;
809 continue;
810 }
811
812 uint64_t span = newest - oldest;
813 if (span > (monthSec * MS_PER_SEC)) {
814 spaces += spaces_total;
815 continue;
816 }
817
818 // total span
819 if (minTime > oldest) minTime = oldest;
820 if (maxTime < newest) maxTime = newest;
821 if (span > maxSpan) maxSpan = span;
822 totalSize += span;
823
824 uint64_t dropped = mNewestDropped[id].msec();
825 if (dropped < oldest) dropped = oldest;
826 if (dropped > newest) dropped = newest;
827
828 oldLength = output.length();
829 output += android::base::StringPrintf("%*s%s", spaces, "",
830 formatMsec(span).c_str());
831 unsigned permille = ((newest - dropped) * 1000 + (span / 2)) / span;
832 if ((permille > 1) && (permille < 999)) {
833 output += android::base::StringPrintf("(%u", permille / 10);
834 permille %= 10;
835 if (permille) {
836 output += android::base::StringPrintf(".%u", permille);
837 }
838 output += android::base::StringPrintf("%%)");
839 }
840 spaces -= output.length() - oldLength;
841 spaces += spaces_total;
842 }
843 if ((maxTime > minTime) && ((maxTime -= minTime) < totalSize) &&
844 (maxTime > maxSpan)) {
845 maxSpan = maxTime;
846 }
847 if (spaces < 0) spaces = 0;
848 output += android::base::StringPrintf("%*s%s", spaces, "",
849 formatMsec(maxSpan).c_str());
850
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700851 static const char OverheadStr[] = "\nOverhead";
852 spaces = 10 - strlen(OverheadStr);
853 output += OverheadStr;
854
855 totalSize = 0;
856 log_id_for_each(id) {
857 if (!(logMask & (1 << id))) continue;
858
Tom Cherry64e90162020-05-07 14:44:43 -0700859 size_t els = mElements[id];
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700860 if (els) {
861 oldLength = output.length();
862 if (spaces < 0) spaces = 0;
863 // estimate the std::list overhead.
864 static const size_t overhead =
865 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800866 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700867 sizeof(std::list<LogBufferElement*>);
Tom Cherry64e90162020-05-07 14:44:43 -0700868 size_t szs = mSizes[id] + els * overhead;
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700869 totalSize += szs;
870 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
871 spaces -= output.length() - oldLength;
872 }
873 spaces += spaces_total;
874 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700875 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700876 if (spaces < 0) spaces = 0;
877 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800878
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700879 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700880
Mark Salyzyn758058f2015-08-21 16:44:30 -0700881 std::string name;
882
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700883 // Chattiest by application (UID)
884 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700885 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700886
Mark Salyzyn501c3732017-03-10 14:31:54 -0800887 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
888 : "Logging for your UID in %s log buffer:";
Tom Cherry64e90162020-05-07 14:44:43 -0700889 output += FormatTable(uidTable[id], uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700890 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700891
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700892 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800893 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
894 : "Logging for this PID:";
Tom Cherry64e90162020-05-07 14:44:43 -0700895 output += FormatTable(pidTable, uid, pid, name);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800896 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700897 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800898 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700899 output += FormatTable(tidTable, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700900 }
901
Mark Salyzyn344bff42015-04-13 14:24:45 -0700902 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800903 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700904 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800905 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700906 output += FormatTable(tagTable, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700907 }
908
Mark Salyzyn083b0372015-12-04 10:59:45 -0800909 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800910 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700911 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800912 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700913 output += FormatTable(securityTagTable, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800914 }
915
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700916 if (enable) {
917 name = "Chattiest TAGs";
918 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
919 name += ":";
Tom Cherry64e90162020-05-07 14:44:43 -0700920 output += FormatTable(tagNameTable, uid, pid, name);
Mark Salyzynf99a7d62017-04-19 14:39:21 -0700921 }
922
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700923 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800924}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700925
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700926namespace android {
927
928uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700929 char buffer[512];
930 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800931 FILE* fp = fopen(buffer, "r");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700932 if (fp) {
933 while (fgets(buffer, sizeof(buffer), fp)) {
Mark Salyzync4e48232017-05-04 13:54:46 -0700934 int uid = AID_LOGD;
935 char space = 0;
936 if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
937 isspace(space)) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700938 fclose(fp);
939 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700940 }
941 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700942 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700943 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800944 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700945}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700946}
947
Tom Cherry64e90162020-05-07 14:44:43 -0700948uid_t LogStatistics::PidToUid(pid_t pid) {
949 auto lock = std::lock_guard{lock_};
Mark Salyzyn511338d2015-05-19 09:12:30 -0700950 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700951}
952
953// caller must free character string
Tom Cherry64e90162020-05-07 14:44:43 -0700954const char* LogStatistics::PidToName(pid_t pid) const {
955 auto lock = std::lock_guard{lock_};
Mark Salyzyn758058f2015-08-21 16:44:30 -0700956 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800957 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
958 const char* name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700959 if (!name) {
Yi Kongc8d09dd2018-07-13 17:39:22 -0700960 return nullptr;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700961 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700962 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700963}