blob: d3167ad3a4b870c75f31f4dfc5018763655cd3de [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
Mark Salyzyn9a038632014-04-07 07:05:40 -070017#include <fcntl.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070018#include <pwd.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070019#include <stdio.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070020#include <string.h>
Mark Salyzynb8a95bd2016-04-07 11:06:31 -070021#include <sys/types.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070022#include <unistd.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080023
Mark Salyzyn9af33ee2016-10-05 12:34:37 -070024#include <list>
25
Mark Salyzynaeaaf812016-09-30 13:30:33 -070026#include <android/log.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080027
28#include "LogStatistics.h"
29
Mark Salyzyn32962912016-09-12 10:29:17 -070030size_t LogStatistics::SizesTotal;
31
Mark Salyzyn77187782015-05-12 15:21:31 -070032LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070033 log_id_for_each(id) {
34 mSizes[id] = 0;
35 mElements[id] = 0;
Mark Salyzyn58b8be82015-09-30 07:40:09 -070036 mDroppedElements[id] = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070037 mSizesTotal[id] = 0;
38 mElementsTotal[id] = 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -080039 }
40}
41
Mark Salyzyn720f6d12015-03-16 08:26:05 -070042namespace android {
43
Mark Salyzyn501c3732017-03-10 14:31:54 -080044size_t sizesTotal() {
45 return LogStatistics::sizesTotal();
46}
Mark Salyzyn32962912016-09-12 10:29:17 -070047
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070048// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -080049char* pidToName(pid_t pid) {
50 char* retval = NULL;
51 if (pid == 0) { // special case from auditd/klogd for kernel
Mark Salyzynae4d9282014-10-15 08:49:39 -070052 retval = strdup("logd");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070053 } else {
Mark Salyzyn9a038632014-04-07 07:05:40 -070054 char buffer[512];
55 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
56 int fd = open(buffer, O_RDONLY);
57 if (fd >= 0) {
58 ssize_t ret = read(fd, buffer, sizeof(buffer));
59 if (ret > 0) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080060 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn9a038632014-04-07 07:05:40 -070061 // frameworks intermediate state
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -080062 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn9a038632014-04-07 07:05:40 -070063 retval = strdup(buffer);
64 }
65 }
66 close(fd);
67 }
68 }
69 return retval;
70}
Mark Salyzyn720f6d12015-03-16 08:26:05 -070071}
72
Mark Salyzyn501c3732017-03-10 14:31:54 -080073void LogStatistics::add(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -070074 log_id_t log_id = element->getLogId();
75 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -080076 mSizes[log_id] += size;
77 ++mElements[log_id];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070078
Mark Salyzyna2c02222016-12-13 10:31:29 -080079 if (element->getDropped()) {
80 ++mDroppedElements[log_id];
81 } else {
82 // When caller adding a chatty entry, they will have already
83 // called add() and subtract() for each entry as they are
84 // evaluated and trimmed, thus recording size and number of
85 // elements, but we must recognize the manufactured dropped
86 // entry as not contributing to the lifetime totals.
87 mSizesTotal[log_id] += size;
Mark Salyzyn32962912016-09-12 10:29:17 -070088 SizesTotal += size;
Mark Salyzyna2c02222016-12-13 10:31:29 -080089 ++mElementsTotal[log_id];
90 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -070091
Mark Salyzynae4d9282014-10-15 08:49:39 -070092 if (log_id == LOG_ID_KERNEL) {
93 return;
94 }
95
Mark Salyzyn758058f2015-08-21 16:44:30 -070096 uidTable[log_id].add(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -070097 if (element->getUid() == AID_SYSTEM) {
98 pidSystemTable[log_id].add(element->getPid(), element);
99 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700100
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700101 if (!enable) {
102 return;
103 }
104
Mark Salyzyn758058f2015-08-21 16:44:30 -0700105 pidTable.add(element->getPid(), element);
106 tidTable.add(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700107
Mark Salyzyn758058f2015-08-21 16:44:30 -0700108 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700109 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800110 if (log_id == LOG_ID_SECURITY) {
111 securityTagTable.add(tag, element);
112 } else {
113 tagTable.add(tag, element);
114 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700115 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800116}
117
Mark Salyzyn501c3732017-03-10 14:31:54 -0800118void LogStatistics::subtract(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700119 log_id_t log_id = element->getLogId();
120 unsigned short size = element->getMsgLen();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800121 mSizes[log_id] -= size;
122 --mElements[log_id];
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700123 if (element->getDropped()) {
124 --mDroppedElements[log_id];
125 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700126
Mark Salyzynae4d9282014-10-15 08:49:39 -0700127 if (log_id == LOG_ID_KERNEL) {
128 return;
129 }
130
Mark Salyzyn758058f2015-08-21 16:44:30 -0700131 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700132 if (element->getUid() == AID_SYSTEM) {
133 pidSystemTable[log_id].subtract(element->getPid(), element);
134 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800135
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700136 if (!enable) {
137 return;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800138 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700139
Mark Salyzyn758058f2015-08-21 16:44:30 -0700140 pidTable.subtract(element->getPid(), element);
141 tidTable.subtract(element->getTid(), element);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700142
Mark Salyzyn758058f2015-08-21 16:44:30 -0700143 uint32_t tag = element->getTag();
Mark Salyzyn344bff42015-04-13 14:24:45 -0700144 if (tag) {
Mark Salyzyn083b0372015-12-04 10:59:45 -0800145 if (log_id == LOG_ID_SECURITY) {
146 securityTagTable.subtract(tag, element);
147 } else {
148 tagTable.subtract(tag, element);
149 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700150 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800151}
152
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700153// Atomically set an entry to drop
154// entry->setDropped(1) must follow this call, caller should do this explicitly.
Mark Salyzyn501c3732017-03-10 14:31:54 -0800155void LogStatistics::drop(LogBufferElement* element) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700156 log_id_t log_id = element->getLogId();
157 unsigned short size = element->getMsgLen();
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700158 mSizes[log_id] -= size;
Mark Salyzyn58b8be82015-09-30 07:40:09 -0700159 ++mDroppedElements[log_id];
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700160
Mark Salyzyn758058f2015-08-21 16:44:30 -0700161 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700162 if (element->getUid() == AID_SYSTEM) {
163 pidSystemTable[log_id].drop(element->getPid(), element);
164 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700165
166 if (!enable) {
167 return;
168 }
169
Mark Salyzyn758058f2015-08-21 16:44:30 -0700170 pidTable.drop(element->getPid(), element);
171 tidTable.drop(element->getTid(), element);
Mark Salyzyn6a066942016-07-14 15:34:30 -0700172
173 uint32_t tag = element->getTag();
174 if (tag) {
175 if (log_id == LOG_ID_SECURITY) {
176 securityTagTable.drop(tag, element);
177 } else {
178 tagTable.drop(tag, element);
179 }
180 }
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700181}
182
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700183// caller must own and free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800184const char* LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700185 // Local hard coded favourites
186 if (uid == AID_LOGD) {
187 return strdup("auditd");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800188 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700189
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700190 // Android system
191 if (uid < AID_APP) {
192 // in bionic, thread safe as long as we copy the results
Mark Salyzyn501c3732017-03-10 14:31:54 -0800193 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700194 if (pwd) {
195 return strdup(pwd->pw_name);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700196 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800197 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700198
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700199 // Parse /data/system/packages.list
Jeff Sharkeydff44702016-12-13 11:55:19 -0700200 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800201 const char* name = android::uidToName(userId);
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700202 if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
203 name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
204 }
Mark Salyzyn08739ba2015-03-16 08:26:05 -0700205 if (name) {
206 return name;
207 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700208
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700209 // Android application
210 if (uid >= AID_APP) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800211 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb8a95bd2016-04-07 11:06:31 -0700212 if (pwd) {
213 return strdup(pwd->pw_name);
214 }
215 }
216
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700217 // report uid -> pid(s) -> pidToName if unique
Mark Salyzyn501c3732017-03-10 14:31:54 -0800218 for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
219 ++it) {
220 const PidEntry& entry = it->second;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700221
222 if (entry.getUid() == uid) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800223 const char* nameTmp = entry.getName();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700224
Mark Salyzyn758058f2015-08-21 16:44:30 -0700225 if (nameTmp) {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700226 if (!name) {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700227 name = strdup(nameTmp);
Mark Salyzyn0eeb06b2016-12-02 10:08:48 -0800228 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800229 free(const_cast<char*>(name));
Mark Salyzyn023f51f2015-04-29 12:48:45 -0700230 name = NULL;
231 break;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700232 }
233 }
234 }
235 }
236
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700237 // No one
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700238 return name;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800239}
240
Mark Salyzyn501c3732017-03-10 14:31:54 -0800241std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700242 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800243 return formatLine(android::base::StringPrintf(name.c_str(),
244 android_log_id_to_name(id)),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700245 std::string("Size"),
Mark Salyzyn501c3732017-03-10 14:31:54 -0800246 std::string(isprune ? "+/- Pruned" : "")) +
247 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700248 std::string(isprune ? "NUM" : ""));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800249}
250
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700251// Helper to truncate name, if too long, and add name dressings
252static void formatTmp(const LogStatistics& stat, const char* nameTmp, uid_t uid,
253 std::string& name, std::string& size, size_t nameLen) {
254 const char* allocNameTmp = nullptr;
255 if (!nameTmp) nameTmp = allocNameTmp = stat.uidToName(uid);
256 if (nameTmp) {
257 size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
258 size_t len = EntryBaseConstants::total_len -
259 EntryBaseConstants::pruned_len - size.length() -
260 name.length() - lenSpace - 2;
261 size_t lenNameTmp = strlen(nameTmp);
262 while ((len < lenNameTmp) && (lenSpace > 1)) {
263 ++len;
264 --lenSpace;
265 }
266 name += android::base::StringPrintf("%*s", (int)lenSpace, "");
267 if (len < lenNameTmp) {
268 name += "...";
269 nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
270 }
271 name += nameTmp;
272 free(const_cast<char*>(allocNameTmp));
273 }
274}
275
Mark Salyzyn501c3732017-03-10 14:31:54 -0800276std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800277 uid_t uid = getUid();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700278 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700279 std::string size = android::base::StringPrintf("%zu", getSizes());
280
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700281 formatTmp(stat, nullptr, uid, name, size, 6);
282
Mark Salyzyn758058f2015-08-21 16:44:30 -0700283 std::string pruned = "";
Mark Salyzync723df82015-08-24 11:08:00 -0700284 if (worstUidEnabledForLogid(id)) {
285 size_t totalDropped = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800286 for (LogStatistics::uidTable_t::const_iterator it =
287 stat.uidTable[id].begin();
288 it != stat.uidTable[id].end(); ++it) {
Mark Salyzync723df82015-08-24 11:08:00 -0700289 totalDropped += it->second.getDropped();
290 }
291 size_t sizes = stat.sizes(id);
292 size_t totalSize = stat.sizesTotal(id);
293 size_t totalElements = stat.elementsTotal(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800294 float totalVirtualSize =
295 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzync723df82015-08-24 11:08:00 -0700296 size_t entrySize = getSizes();
297 float virtualEntrySize = entrySize;
298 int realPermille = virtualEntrySize * 1000.0 / sizes;
299 size_t dropped = getDropped();
300 if (dropped) {
301 pruned = android::base::StringPrintf("%zu", dropped);
302 virtualEntrySize += (float)dropped * totalSize / totalElements;
303 }
304 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800305 int permille =
306 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzync723df82015-08-24 11:08:00 -0700307 if ((permille < -1) || (1 < permille)) {
308 std::string change;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800309 const char* units = "%";
310 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzync723df82015-08-24 11:08:00 -0700311
312 if (permille > 999) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800313 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzync723df82015-08-24 11:08:00 -0700314 units = "X";
315 prefix = "";
316 }
317 if ((-99 < permille) && (permille < 99)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800318 change = android::base::StringPrintf(
319 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzync723df82015-08-24 11:08:00 -0700320 ((permille < 0) ? (-permille % 10) : (permille % 10)),
321 units);
322 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800323 change = android::base::StringPrintf(
324 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzync723df82015-08-24 11:08:00 -0700325 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800326 ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
327 pruned.length() - change.length();
Mark Salyzync723df82015-08-24 11:08:00 -0700328 if ((spaces <= 0) && pruned.length()) {
329 spaces = 1;
330 }
Mark Salyzynd966e222016-12-19 22:23:03 +0000331 if (spaces > 0) {
Mark Salyzync723df82015-08-24 11:08:00 -0700332 change += android::base::StringPrintf("%*s", (int)spaces, "");
333 }
334 pruned = change + pruned;
335 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700336 }
337
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700338 std::string output = formatLine(name, size, pruned);
339
340 if (uid != AID_SYSTEM) {
341 return output;
342 }
343
344 static const size_t maximum_sorted_entries = 32;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800345 std::unique_ptr<const PidEntry* []> sorted =
346 stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700347
348 if (!sorted.get()) {
349 return output;
350 }
351 std::string byPid;
352 size_t index;
353 bool hasDropped = false;
354 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800355 const PidEntry* entry = sorted[index];
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700356 if (!entry) {
357 break;
358 }
359 if (entry->getSizes() <= (getSizes() / 100)) {
360 break;
361 }
362 if (entry->getDropped()) {
363 hasDropped = true;
364 }
365 byPid += entry->format(stat, id);
366 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800367 if (index > 1) { // print this only if interesting
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700368 std::string ditto("\" ");
Mark Salyzyn501c3732017-03-10 14:31:54 -0800369 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
370 hasDropped ? ditto : std::string(""));
Mark Salyzynbec3c3d2015-08-28 08:02:59 -0700371 output += byPid;
372 }
373
374 return output;
Mark Salyzyn758058f2015-08-21 16:44:30 -0700375}
376
Mark Salyzyn501c3732017-03-10 14:31:54 -0800377std::string PidEntry::formatHeader(const std::string& name,
378 log_id_t /* id */) const {
379 return formatLine(name, std::string("Size"), std::string("Pruned")) +
380 formatLine(std::string(" PID/UID COMMAND LINE"),
381 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700382}
383
Mark Salyzyn501c3732017-03-10 14:31:54 -0800384std::string PidEntry::format(const LogStatistics& stat,
385 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700386 uid_t uid = getUid();
Mark Salyzynee3b8382015-12-17 09:58:43 -0800387 pid_t pid = getPid();
388 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800389 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700390
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700391 formatTmp(stat, getName(), uid, name, size, 12);
392
Mark Salyzyn758058f2015-08-21 16:44:30 -0700393 std::string pruned = "";
394 size_t dropped = getDropped();
395 if (dropped) {
396 pruned = android::base::StringPrintf("%zu", dropped);
397 }
398
399 return formatLine(name, size, pruned);
400}
401
Mark Salyzyn501c3732017-03-10 14:31:54 -0800402std::string TidEntry::formatHeader(const std::string& name,
403 log_id_t /* id */) const {
404 return formatLine(name, std::string("Size"), std::string("Pruned")) +
405 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn758058f2015-08-21 16:44:30 -0700406 std::string("NUM"));
407}
408
Mark Salyzyn501c3732017-03-10 14:31:54 -0800409std::string TidEntry::format(const LogStatistics& stat,
410 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700411 uid_t uid = getUid();
Mark Salyzyn501c3732017-03-10 14:31:54 -0800412 std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800413 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700414
Mark Salyzynf31ae3d2017-04-13 15:35:22 -0700415 formatTmp(stat, getName(), uid, name, size, 12);
416
Mark Salyzyn758058f2015-08-21 16:44:30 -0700417 std::string pruned = "";
418 size_t dropped = getDropped();
419 if (dropped) {
420 pruned = android::base::StringPrintf("%zu", dropped);
421 }
422
423 return formatLine(name, size, pruned);
424}
425
Mark Salyzyn501c3732017-03-10 14:31:54 -0800426std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700427 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800428 return formatLine(name, std::string("Size"),
429 std::string(isprune ? "Prune" : "")) +
430 formatLine(std::string(" TAG/UID TAGNAME"),
431 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn758058f2015-08-21 16:44:30 -0700432}
433
Mark Salyzyn501c3732017-03-10 14:31:54 -0800434std::string TagEntry::format(const LogStatistics& /* stat */,
435 log_id_t /* id */) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700436 std::string name;
437 uid_t uid = getUid();
438 if (uid == (uid_t)-1) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800439 name = android::base::StringPrintf("%7u", getKey());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700440 } else {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800441 name = android::base::StringPrintf("%7u/%u", getKey(), uid);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700442 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800443 const char* nameTmp = getName();
Mark Salyzyn758058f2015-08-21 16:44:30 -0700444 if (nameTmp) {
445 name += android::base::StringPrintf(
Mark Salyzyn501c3732017-03-10 14:31:54 -0800446 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700447 }
448
Mark Salyzyn501c3732017-03-10 14:31:54 -0800449 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn758058f2015-08-21 16:44:30 -0700450
451 std::string pruned = "";
Mark Salyzyn6a066942016-07-14 15:34:30 -0700452 size_t dropped = getDropped();
453 if (dropped) {
454 pruned = android::base::StringPrintf("%zu", dropped);
455 }
Mark Salyzyn758058f2015-08-21 16:44:30 -0700456
457 return formatLine(name, size, pruned);
458}
459
Mark Salyzynee3b8382015-12-17 09:58:43 -0800460std::string LogStatistics::format(uid_t uid, pid_t pid,
461 unsigned int logMask) const {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700462 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800463
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700464 // Report on total logging, current and for all time
Mark Salyzyn34facab2014-02-06 14:48:50 -0800465
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700466 std::string output = "size/num";
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700467 size_t oldLength;
468 short spaces = 1;
469
470 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700471 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700472 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700473 if (spaces < 0) spaces = 0;
Mark Salyzyndecbcd92015-08-19 15:33:01 -0700474 output += android::base::StringPrintf("%*s%s", spaces, "",
475 android_log_id_to_name(id));
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700476 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800477 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700478 if (spaces < 0) spaces = 0;
479 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzyn34facab2014-02-06 14:48:50 -0800480
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700481 static const char TotalStr[] = "\nTotal";
482 spaces = 10 - strlen(TotalStr);
483 output += TotalStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800484
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700485 size_t totalSize = 0;
486 size_t totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700487 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700488 if (!(logMask & (1 << id))) continue;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700489 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700490 if (spaces < 0) spaces = 0;
491 size_t szs = sizesTotal(id);
492 totalSize += szs;
493 size_t els = elementsTotal(id);
494 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800495 output +=
496 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700497 spaces += spaces_total + oldLength - output.length();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800498 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700499 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800500 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
501 totalEls);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800502
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700503 static const char NowStr[] = "\nNow";
504 spaces = 10 - strlen(NowStr);
505 output += NowStr;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800506
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700507 totalSize = 0;
508 totalEls = 0;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700509 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700510 if (!(logMask & (1 << id))) continue;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800511
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700512 size_t els = elements(id);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800513 if (els) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700514 oldLength = output.length();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700515 if (spaces < 0) spaces = 0;
516 size_t szs = sizes(id);
517 totalSize += szs;
518 totalEls += els;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800519 output +=
520 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700521 spaces -= output.length() - oldLength;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800522 }
523 spaces += spaces_total;
524 }
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700525 if (spaces < 0) spaces = 0;
Mark Salyzyn501c3732017-03-10 14:31:54 -0800526 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
527 totalEls);
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700528
529 static const char OverheadStr[] = "\nOverhead";
530 spaces = 10 - strlen(OverheadStr);
531 output += OverheadStr;
532
533 totalSize = 0;
534 log_id_for_each(id) {
535 if (!(logMask & (1 << id))) continue;
536
537 size_t els = elements(id);
538 if (els) {
539 oldLength = output.length();
540 if (spaces < 0) spaces = 0;
541 // estimate the std::list overhead.
542 static const size_t overhead =
543 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzyn501c3732017-03-10 14:31:54 -0800544 -sizeof(uint64_t)) +
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700545 sizeof(std::list<LogBufferElement*>);
546 size_t szs = sizes(id) + els * overhead;
547 totalSize += szs;
548 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
549 spaces -= output.length() - oldLength;
550 }
551 spaces += spaces_total;
552 }
Mark Salyzyn6d981af2016-10-06 09:55:21 -0700553 totalSize += sizeOf();
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700554 if (spaces < 0) spaces = 0;
555 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800556
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700557 // Report on Chattiest
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700558
Mark Salyzyn758058f2015-08-21 16:44:30 -0700559 std::string name;
560
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700561 // Chattiest by application (UID)
562 log_id_for_each(id) {
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700563 if (!(logMask & (1 << id))) continue;
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700564
Mark Salyzyn501c3732017-03-10 14:31:54 -0800565 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
566 : "Logging for your UID in %s log buffer:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800567 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700568 }
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700569
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700570 if (enable) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800571 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
572 : "Logging for this PID:";
Mark Salyzynee3b8382015-12-17 09:58:43 -0800573 output += pidTable.format(*this, uid, pid, name);
574 name = "Chattiest TIDs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700575 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800576 name += ":";
577 output += tidTable.format(*this, uid, pid, name);
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700578 }
579
Mark Salyzyn344bff42015-04-13 14:24:45 -0700580 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800581 name = "Chattiest events log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700582 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800583 name += ":";
584 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzyn344bff42015-04-13 14:24:45 -0700585 }
586
Mark Salyzyn083b0372015-12-04 10:59:45 -0800587 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynee3b8382015-12-17 09:58:43 -0800588 name = "Chattiest security log buffer TAGs";
Mark Salyzyn9af33ee2016-10-05 12:34:37 -0700589 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynee3b8382015-12-17 09:58:43 -0800590 name += ":";
Mark Salyzyn501c3732017-03-10 14:31:54 -0800591 output +=
592 securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn083b0372015-12-04 10:59:45 -0800593 }
594
Mark Salyzyn73160ac2015-08-20 10:01:44 -0700595 return output;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800596}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700597
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700598namespace android {
599
600uid_t pidToUid(pid_t pid) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700601 char buffer[512];
602 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzyn501c3732017-03-10 14:31:54 -0800603 FILE* fp = fopen(buffer, "r");
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700604 if (fp) {
605 while (fgets(buffer, sizeof(buffer), fp)) {
606 int uid;
Mark Salyzync32afdf2015-04-14 13:07:29 -0700607 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700608 fclose(fp);
609 return uid;
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700610 }
611 }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700612 fclose(fp);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700613 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800614 return AID_LOGD; // associate this with the logger
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700615}
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700616}
617
618uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn511338d2015-05-19 09:12:30 -0700619 return pidTable.add(pid)->second.getUid();
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700620}
621
622// caller must free character string
Mark Salyzyn501c3732017-03-10 14:31:54 -0800623const char* LogStatistics::pidToName(pid_t pid) const {
Mark Salyzyn758058f2015-08-21 16:44:30 -0700624 // An inconvenient truth ... getName() can alter the object
Mark Salyzyn501c3732017-03-10 14:31:54 -0800625 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
626 const char* name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700627 if (!name) {
628 return NULL;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700629 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700630 return strdup(name);
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700631}