blob: cc30f778367748ccce0630f8d6db3f9ae82f2226 [file] [log] [blame]
Mark Salyzynd774bce2014-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 Salyzyn5766f802014-04-07 07:05:40 -070017#include <fcntl.h>
Mark Salyzynb01933e2016-04-07 11:06:31 -070018#include <pwd.h>
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070019#include <stdio.h>
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070020#include <string.h>
Mark Salyzynb01933e2016-04-07 11:06:31 -070021#include <sys/types.h>
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070022#include <unistd.h>
Mark Salyzynd774bce2014-02-06 14:48:50 -080023
Mark Salyzyn6ed82492016-10-05 12:34:37 -070024#include <list>
25
Mark Salyzyn5ae7c342016-09-30 13:30:33 -070026#include <android/log.h>
Mark Salyzynd774bce2014-02-06 14:48:50 -080027
28#include "LogStatistics.h"
29
Mark Salyzyn150d41e2016-09-12 10:29:17 -070030size_t LogStatistics::SizesTotal;
31
Mark Salyzyncd766f92015-05-12 15:21:31 -070032LogStatistics::LogStatistics() : enable(false) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070033 log_id_for_each(id) {
34 mSizes[id] = 0;
35 mElements[id] = 0;
Mark Salyzynd745c722015-09-30 07:40:09 -070036 mDroppedElements[id] = 0;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070037 mSizesTotal[id] = 0;
38 mElementsTotal[id] = 0;
Mark Salyzynd774bce2014-02-06 14:48:50 -080039 }
40}
41
Mark Salyzyn1435b472015-03-16 08:26:05 -070042namespace android {
43
Mark Salyzynda65bcb2017-03-10 14:31:54 -080044size_t sizesTotal() {
45 return LogStatistics::sizesTotal();
46}
Mark Salyzyn150d41e2016-09-12 10:29:17 -070047
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070048// caller must own and free character string
Mark Salyzynda65bcb2017-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 Salyzyne73a18b2014-10-15 08:49:39 -070052 retval = strdup("logd");
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070053 } else {
Mark Salyzyn5766f802014-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 Salyzynda65bcb2017-03-10 14:31:54 -080060 buffer[sizeof(buffer) - 1] = '\0';
Mark Salyzyn5766f802014-04-07 07:05:40 -070061 // frameworks intermediate state
Mark Salyzyn292e1f92016-12-02 10:08:48 -080062 if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
Mark Salyzyn5766f802014-04-07 07:05:40 -070063 retval = strdup(buffer);
64 }
65 }
66 close(fd);
67 }
68 }
69 return retval;
70}
Mark Salyzyn1435b472015-03-16 08:26:05 -070071}
72
Mark Salyzynda65bcb2017-03-10 14:31:54 -080073void LogStatistics::add(LogBufferElement* element) {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -070074 log_id_t log_id = element->getLogId();
75 unsigned short size = element->getMsgLen();
Mark Salyzynd774bce2014-02-06 14:48:50 -080076 mSizes[log_id] += size;
77 ++mElements[log_id];
Mark Salyzyn9cf5d402015-03-10 13:51:35 -070078
Mark Salyzyn2456d042016-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 Salyzyn150d41e2016-09-12 10:29:17 -070088 SizesTotal += size;
Mark Salyzyn2456d042016-12-13 10:31:29 -080089 ++mElementsTotal[log_id];
90 }
Mark Salyzyn1435b472015-03-16 08:26:05 -070091
Mark Salyzyne73a18b2014-10-15 08:49:39 -070092 if (log_id == LOG_ID_KERNEL) {
93 return;
94 }
95
Mark Salyzyn34eb1b22015-08-21 16:44:30 -070096 uidTable[log_id].add(element->getUid(), element);
Mark Salyzyn538c6a92015-08-28 08:02:59 -070097 if (element->getUid() == AID_SYSTEM) {
98 pidSystemTable[log_id].add(element->getPid(), element);
99 }
Mark Salyzyne73a18b2014-10-15 08:49:39 -0700100
Mark Salyzyn1435b472015-03-16 08:26:05 -0700101 if (!enable) {
102 return;
103 }
104
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700105 pidTable.add(element->getPid(), element);
106 tidTable.add(element->getTid(), element);
Mark Salyzynf96ac902015-04-13 14:24:45 -0700107
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700108 uint32_t tag = element->getTag();
Mark Salyzynf96ac902015-04-13 14:24:45 -0700109 if (tag) {
Mark Salyzyn8885daf2015-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 Salyzynf96ac902015-04-13 14:24:45 -0700115 }
Mark Salyzynd774bce2014-02-06 14:48:50 -0800116}
117
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800118void LogStatistics::subtract(LogBufferElement* element) {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700119 log_id_t log_id = element->getLogId();
120 unsigned short size = element->getMsgLen();
Mark Salyzynd774bce2014-02-06 14:48:50 -0800121 mSizes[log_id] -= size;
122 --mElements[log_id];
Mark Salyzynd745c722015-09-30 07:40:09 -0700123 if (element->getDropped()) {
124 --mDroppedElements[log_id];
125 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700126
Mark Salyzyne73a18b2014-10-15 08:49:39 -0700127 if (log_id == LOG_ID_KERNEL) {
128 return;
129 }
130
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700131 uidTable[log_id].subtract(element->getUid(), element);
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700132 if (element->getUid() == AID_SYSTEM) {
133 pidSystemTable[log_id].subtract(element->getPid(), element);
134 }
Mark Salyzynd774bce2014-02-06 14:48:50 -0800135
Mark Salyzyn1435b472015-03-16 08:26:05 -0700136 if (!enable) {
137 return;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800138 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700139
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700140 pidTable.subtract(element->getPid(), element);
141 tidTable.subtract(element->getTid(), element);
Mark Salyzynf96ac902015-04-13 14:24:45 -0700142
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700143 uint32_t tag = element->getTag();
Mark Salyzynf96ac902015-04-13 14:24:45 -0700144 if (tag) {
Mark Salyzyn8885daf2015-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 Salyzynf96ac902015-04-13 14:24:45 -0700150 }
Mark Salyzynd774bce2014-02-06 14:48:50 -0800151}
152
Mark Salyzyna69d5a42015-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 Salyzynda65bcb2017-03-10 14:31:54 -0800155void LogStatistics::drop(LogBufferElement* element) {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700156 log_id_t log_id = element->getLogId();
157 unsigned short size = element->getMsgLen();
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700158 mSizes[log_id] -= size;
Mark Salyzynd745c722015-09-30 07:40:09 -0700159 ++mDroppedElements[log_id];
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700160
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700161 uidTable[log_id].drop(element->getUid(), element);
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700162 if (element->getUid() == AID_SYSTEM) {
163 pidSystemTable[log_id].drop(element->getPid(), element);
164 }
Mark Salyzyna69d5a42015-03-16 12:04:09 -0700165
166 if (!enable) {
167 return;
168 }
169
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700170 pidTable.drop(element->getPid(), element);
171 tidTable.drop(element->getTid(), element);
Mark Salyzync572fc62016-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 Salyzyna69d5a42015-03-16 12:04:09 -0700181}
182
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700183// caller must own and free character string
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800184const char* LogStatistics::uidToName(uid_t uid) const {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700185 // Local hard coded favourites
186 if (uid == AID_LOGD) {
187 return strdup("auditd");
Mark Salyzynd774bce2014-02-06 14:48:50 -0800188 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700189
Mark Salyzynb01933e2016-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 Salyzynda65bcb2017-03-10 14:31:54 -0800193 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb01933e2016-04-07 11:06:31 -0700194 if (pwd) {
195 return strdup(pwd->pw_name);
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700196 }
Mark Salyzynd774bce2014-02-06 14:48:50 -0800197 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700198
Mark Salyzyn9018bc92015-03-16 08:26:05 -0700199 // Parse /data/system/packages.list
Jeff Sharkeyeff4d582016-12-13 11:55:19 -0700200 uid_t userId = uid % AID_USER_OFFSET;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800201 const char* name = android::uidToName(userId);
Mark Salyzynf9908b02015-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 Salyzyn9018bc92015-03-16 08:26:05 -0700205 if (name) {
206 return name;
207 }
Mark Salyzyn1435b472015-03-16 08:26:05 -0700208
Mark Salyzynb01933e2016-04-07 11:06:31 -0700209 // Android application
210 if (uid >= AID_APP) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800211 struct passwd* pwd = getpwuid(uid);
Mark Salyzynb01933e2016-04-07 11:06:31 -0700212 if (pwd) {
213 return strdup(pwd->pw_name);
214 }
215 }
216
Mark Salyzyn1435b472015-03-16 08:26:05 -0700217 // report uid -> pid(s) -> pidToName if unique
Mark Salyzynda65bcb2017-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 Salyzyn1435b472015-03-16 08:26:05 -0700221
222 if (entry.getUid() == uid) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800223 const char* nameTmp = entry.getName();
Mark Salyzyn1435b472015-03-16 08:26:05 -0700224
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700225 if (nameTmp) {
Mark Salyzyn1435b472015-03-16 08:26:05 -0700226 if (!name) {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700227 name = strdup(nameTmp);
Mark Salyzyn292e1f92016-12-02 10:08:48 -0800228 } else if (fastcmp<strcmp>(name, nameTmp)) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800229 free(const_cast<char*>(name));
Mark Salyzynf9908b02015-04-29 12:48:45 -0700230 name = NULL;
231 break;
Mark Salyzyn1435b472015-03-16 08:26:05 -0700232 }
233 }
234 }
235 }
236
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700237 // No one
Mark Salyzyn1435b472015-03-16 08:26:05 -0700238 return name;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800239}
240
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800241std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700242 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800243 return formatLine(android::base::StringPrintf(name.c_str(),
244 android_log_id_to_name(id)),
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700245 std::string("Size"),
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800246 std::string(isprune ? "+/- Pruned" : "")) +
247 formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700248 std::string(isprune ? "NUM" : ""));
Mark Salyzynd774bce2014-02-06 14:48:50 -0800249}
250
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800251std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const {
Mark Salyzynb921ab52015-12-17 09:58:43 -0800252 uid_t uid = getUid();
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700253 std::string name = android::base::StringPrintf("%u", uid);
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800254 const char* nameTmp = stat.uidToName(uid);
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700255 if (nameTmp) {
256 name += android::base::StringPrintf(
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800257 "%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", nameTmp);
258 free(const_cast<char*>(nameTmp));
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700259 }
260
261 std::string size = android::base::StringPrintf("%zu", getSizes());
262
263 std::string pruned = "";
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700264 if (worstUidEnabledForLogid(id)) {
265 size_t totalDropped = 0;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800266 for (LogStatistics::uidTable_t::const_iterator it =
267 stat.uidTable[id].begin();
268 it != stat.uidTable[id].end(); ++it) {
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700269 totalDropped += it->second.getDropped();
270 }
271 size_t sizes = stat.sizes(id);
272 size_t totalSize = stat.sizesTotal(id);
273 size_t totalElements = stat.elementsTotal(id);
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800274 float totalVirtualSize =
275 (float)sizes + (float)totalDropped * totalSize / totalElements;
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700276 size_t entrySize = getSizes();
277 float virtualEntrySize = entrySize;
278 int realPermille = virtualEntrySize * 1000.0 / sizes;
279 size_t dropped = getDropped();
280 if (dropped) {
281 pruned = android::base::StringPrintf("%zu", dropped);
282 virtualEntrySize += (float)dropped * totalSize / totalElements;
283 }
284 int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800285 int permille =
286 (realPermille - virtualPermille) * 1000L / (virtualPermille ?: 1);
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700287 if ((permille < -1) || (1 < permille)) {
288 std::string change;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800289 const char* units = "%";
290 const char* prefix = (permille > 0) ? "+" : "";
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700291
292 if (permille > 999) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800293 permille = (permille + 1000) / 100; // Now tenths fold
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700294 units = "X";
295 prefix = "";
296 }
297 if ((-99 < permille) && (permille < 99)) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800298 change = android::base::StringPrintf(
299 "%s%d.%u%s", prefix, permille / 10,
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700300 ((permille < 0) ? (-permille % 10) : (permille % 10)),
301 units);
302 } else {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800303 change = android::base::StringPrintf(
304 "%s%d%s", prefix, (permille + 5) / 10, units);
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700305 }
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800306 ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
307 pruned.length() - change.length();
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700308 if ((spaces <= 0) && pruned.length()) {
309 spaces = 1;
310 }
Mark Salyzyn2154ac32016-12-19 22:23:03 +0000311 if (spaces > 0) {
Mark Salyzyn6b477ef2015-08-24 11:08:00 -0700312 change += android::base::StringPrintf("%*s", (int)spaces, "");
313 }
314 pruned = change + pruned;
315 }
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700316 }
317
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700318 std::string output = formatLine(name, size, pruned);
319
320 if (uid != AID_SYSTEM) {
321 return output;
322 }
323
324 static const size_t maximum_sorted_entries = 32;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800325 std::unique_ptr<const PidEntry* []> sorted =
326 stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700327
328 if (!sorted.get()) {
329 return output;
330 }
331 std::string byPid;
332 size_t index;
333 bool hasDropped = false;
334 for (index = 0; index < maximum_sorted_entries; ++index) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800335 const PidEntry* entry = sorted[index];
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700336 if (!entry) {
337 break;
338 }
339 if (entry->getSizes() <= (getSizes() / 100)) {
340 break;
341 }
342 if (entry->getDropped()) {
343 hasDropped = true;
344 }
345 byPid += entry->format(stat, id);
346 }
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800347 if (index > 1) { // print this only if interesting
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700348 std::string ditto("\" ");
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800349 output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto,
350 hasDropped ? ditto : std::string(""));
Mark Salyzyn538c6a92015-08-28 08:02:59 -0700351 output += byPid;
352 }
353
354 return output;
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700355}
356
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800357std::string PidEntry::formatHeader(const std::string& name,
358 log_id_t /* id */) const {
359 return formatLine(name, std::string("Size"), std::string("Pruned")) +
360 formatLine(std::string(" PID/UID COMMAND LINE"),
361 std::string("BYTES"), std::string("NUM"));
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700362}
363
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800364std::string PidEntry::format(const LogStatistics& stat,
365 log_id_t /* id */) const {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700366 uid_t uid = getUid();
Mark Salyzynb921ab52015-12-17 09:58:43 -0800367 pid_t pid = getPid();
368 std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800369 const char* nameTmp = getName();
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700370 if (nameTmp) {
371 name += android::base::StringPrintf(
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800372 "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700373 } else if ((nameTmp = stat.uidToName(uid))) {
374 name += android::base::StringPrintf(
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800375 "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp);
376 free(const_cast<char*>(nameTmp));
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700377 }
378
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800379 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700380
381 std::string pruned = "";
382 size_t dropped = getDropped();
383 if (dropped) {
384 pruned = android::base::StringPrintf("%zu", dropped);
385 }
386
387 return formatLine(name, size, pruned);
388}
389
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800390std::string TidEntry::formatHeader(const std::string& name,
391 log_id_t /* id */) const {
392 return formatLine(name, std::string("Size"), std::string("Pruned")) +
393 formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700394 std::string("NUM"));
395}
396
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800397std::string TidEntry::format(const LogStatistics& stat,
398 log_id_t /* id */) const {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700399 uid_t uid = getUid();
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800400 std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
401 const char* nameTmp = getName();
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700402 if (nameTmp) {
403 name += android::base::StringPrintf(
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800404 "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700405 } else if ((nameTmp = stat.uidToName(uid))) {
406 // if we do not have a PID name, lets punt to try UID name?
407 name += android::base::StringPrintf(
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800408 "%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", nameTmp);
409 free(const_cast<char*>(nameTmp));
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700410 // We tried, better to not have a name at all, we still
411 // have TID/UID by number to report in any case.
412 }
413
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800414 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700415
416 std::string pruned = "";
417 size_t dropped = getDropped();
418 if (dropped) {
419 pruned = android::base::StringPrintf("%zu", dropped);
420 }
421
422 return formatLine(name, size, pruned);
423}
424
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800425std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700426 bool isprune = worstUidEnabledForLogid(id);
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800427 return formatLine(name, std::string("Size"),
428 std::string(isprune ? "Prune" : "")) +
429 formatLine(std::string(" TAG/UID TAGNAME"),
430 std::string("BYTES"), std::string(isprune ? "NUM" : ""));
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700431}
432
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800433std::string TagEntry::format(const LogStatistics& /* stat */,
434 log_id_t /* id */) const {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700435 std::string name;
436 uid_t uid = getUid();
437 if (uid == (uid_t)-1) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800438 name = android::base::StringPrintf("%7u", getKey());
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700439 } else {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800440 name = android::base::StringPrintf("%7u/%u", getKey(), uid);
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700441 }
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800442 const char* nameTmp = getName();
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700443 if (nameTmp) {
444 name += android::base::StringPrintf(
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800445 "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700446 }
447
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800448 std::string size = android::base::StringPrintf("%zu", getSizes());
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700449
450 std::string pruned = "";
Mark Salyzync572fc62016-07-14 15:34:30 -0700451 size_t dropped = getDropped();
452 if (dropped) {
453 pruned = android::base::StringPrintf("%zu", dropped);
454 }
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700455
456 return formatLine(name, size, pruned);
457}
458
Mark Salyzynb921ab52015-12-17 09:58:43 -0800459std::string LogStatistics::format(uid_t uid, pid_t pid,
460 unsigned int logMask) const {
Mark Salyzyn5766f802014-04-07 07:05:40 -0700461 static const unsigned short spaces_total = 19;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800462
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700463 // Report on total logging, current and for all time
Mark Salyzynd774bce2014-02-06 14:48:50 -0800464
Mark Salyzyn09a91e22015-08-19 15:33:01 -0700465 std::string output = "size/num";
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700466 size_t oldLength;
467 short spaces = 1;
468
469 log_id_for_each(id) {
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700470 if (!(logMask & (1 << id))) continue;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700471 oldLength = output.length();
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700472 if (spaces < 0) spaces = 0;
Mark Salyzyn09a91e22015-08-19 15:33:01 -0700473 output += android::base::StringPrintf("%*s%s", spaces, "",
474 android_log_id_to_name(id));
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700475 spaces += spaces_total + oldLength - output.length();
Mark Salyzynd774bce2014-02-06 14:48:50 -0800476 }
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700477 if (spaces < 0) spaces = 0;
478 output += android::base::StringPrintf("%*sTotal", spaces, "");
Mark Salyzynd774bce2014-02-06 14:48:50 -0800479
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700480 static const char TotalStr[] = "\nTotal";
481 spaces = 10 - strlen(TotalStr);
482 output += TotalStr;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800483
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700484 size_t totalSize = 0;
485 size_t totalEls = 0;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700486 log_id_for_each(id) {
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700487 if (!(logMask & (1 << id))) continue;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700488 oldLength = output.length();
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700489 if (spaces < 0) spaces = 0;
490 size_t szs = sizesTotal(id);
491 totalSize += szs;
492 size_t els = elementsTotal(id);
493 totalEls += els;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800494 output +=
495 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700496 spaces += spaces_total + oldLength - output.length();
Mark Salyzynd774bce2014-02-06 14:48:50 -0800497 }
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700498 if (spaces < 0) spaces = 0;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800499 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
500 totalEls);
Mark Salyzynd774bce2014-02-06 14:48:50 -0800501
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700502 static const char NowStr[] = "\nNow";
503 spaces = 10 - strlen(NowStr);
504 output += NowStr;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800505
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700506 totalSize = 0;
507 totalEls = 0;
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700508 log_id_for_each(id) {
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700509 if (!(logMask & (1 << id))) continue;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800510
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700511 size_t els = elements(id);
Mark Salyzynd774bce2014-02-06 14:48:50 -0800512 if (els) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700513 oldLength = output.length();
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700514 if (spaces < 0) spaces = 0;
515 size_t szs = sizes(id);
516 totalSize += szs;
517 totalEls += els;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800518 output +=
519 android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700520 spaces -= output.length() - oldLength;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800521 }
522 spaces += spaces_total;
523 }
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700524 if (spaces < 0) spaces = 0;
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800525 output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
526 totalEls);
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700527
528 static const char OverheadStr[] = "\nOverhead";
529 spaces = 10 - strlen(OverheadStr);
530 output += OverheadStr;
531
532 totalSize = 0;
533 log_id_for_each(id) {
534 if (!(logMask & (1 << id))) continue;
535
536 size_t els = elements(id);
537 if (els) {
538 oldLength = output.length();
539 if (spaces < 0) spaces = 0;
540 // estimate the std::list overhead.
541 static const size_t overhead =
542 ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800543 -sizeof(uint64_t)) +
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700544 sizeof(std::list<LogBufferElement*>);
545 size_t szs = sizes(id) + els * overhead;
546 totalSize += szs;
547 output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
548 spaces -= output.length() - oldLength;
549 }
550 spaces += spaces_total;
551 }
Mark Salyzyne2232382016-10-06 09:55:21 -0700552 totalSize += sizeOf();
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700553 if (spaces < 0) spaces = 0;
554 output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
Mark Salyzynd774bce2014-02-06 14:48:50 -0800555
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700556 // Report on Chattiest
Mark Salyzyn692e3c32014-03-26 10:46:39 -0700557
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700558 std::string name;
559
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700560 // Chattiest by application (UID)
561 log_id_for_each(id) {
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700562 if (!(logMask & (1 << id))) continue;
Mark Salyzyn692e3c32014-03-26 10:46:39 -0700563
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800564 name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
565 : "Logging for your UID in %s log buffer:";
Mark Salyzynb921ab52015-12-17 09:58:43 -0800566 output += uidTable[id].format(*this, uid, pid, name, id);
Mark Salyzyn1435b472015-03-16 08:26:05 -0700567 }
Mark Salyzyn692e3c32014-03-26 10:46:39 -0700568
Mark Salyzyn1435b472015-03-16 08:26:05 -0700569 if (enable) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800570 name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
571 : "Logging for this PID:";
Mark Salyzynb921ab52015-12-17 09:58:43 -0800572 output += pidTable.format(*this, uid, pid, name);
573 name = "Chattiest TIDs";
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700574 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynb921ab52015-12-17 09:58:43 -0800575 name += ":";
576 output += tidTable.format(*this, uid, pid, name);
Mark Salyzynaf5c67f2015-04-20 13:35:15 -0700577 }
578
Mark Salyzynf96ac902015-04-13 14:24:45 -0700579 if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
Mark Salyzynb921ab52015-12-17 09:58:43 -0800580 name = "Chattiest events log buffer TAGs";
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700581 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynb921ab52015-12-17 09:58:43 -0800582 name += ":";
583 output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
Mark Salyzynf96ac902015-04-13 14:24:45 -0700584 }
585
Mark Salyzyn8885daf2015-12-04 10:59:45 -0800586 if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
Mark Salyzynb921ab52015-12-17 09:58:43 -0800587 name = "Chattiest security log buffer TAGs";
Mark Salyzyn6ed82492016-10-05 12:34:37 -0700588 if (pid) name += android::base::StringPrintf(" for PID %d", pid);
Mark Salyzynb921ab52015-12-17 09:58:43 -0800589 name += ":";
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800590 output +=
591 securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
Mark Salyzyn8885daf2015-12-04 10:59:45 -0800592 }
593
Mark Salyzyn1c7b6fb2015-08-20 10:01:44 -0700594 return output;
Mark Salyzynd774bce2014-02-06 14:48:50 -0800595}
Mark Salyzynf67c3792014-04-07 07:15:33 -0700596
Mark Salyzyn1435b472015-03-16 08:26:05 -0700597namespace android {
598
599uid_t pidToUid(pid_t pid) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700600 char buffer[512];
601 snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800602 FILE* fp = fopen(buffer, "r");
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700603 if (fp) {
604 while (fgets(buffer, sizeof(buffer), fp)) {
605 int uid;
Mark Salyzyn8f5f8962015-04-14 13:07:29 -0700606 if (sscanf(buffer, "Uid: %d", &uid) == 1) {
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700607 fclose(fp);
608 return uid;
Mark Salyzynf67c3792014-04-07 07:15:33 -0700609 }
610 }
Mark Salyzyn9cf5d402015-03-10 13:51:35 -0700611 fclose(fp);
Mark Salyzynf67c3792014-04-07 07:15:33 -0700612 }
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800613 return AID_LOGD; // associate this with the logger
Mark Salyzynf67c3792014-04-07 07:15:33 -0700614}
Mark Salyzyn1435b472015-03-16 08:26:05 -0700615}
616
617uid_t LogStatistics::pidToUid(pid_t pid) {
Mark Salyzyn6a404192015-05-19 09:12:30 -0700618 return pidTable.add(pid)->second.getUid();
Mark Salyzyn1435b472015-03-16 08:26:05 -0700619}
620
621// caller must free character string
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800622const char* LogStatistics::pidToName(pid_t pid) const {
Mark Salyzyn34eb1b22015-08-21 16:44:30 -0700623 // An inconvenient truth ... getName() can alter the object
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800624 pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
625 const char* name = writablePidTable.add(pid)->second.getName();
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700626 if (!name) {
627 return NULL;
Mark Salyzyn1435b472015-03-16 08:26:05 -0700628 }
Mark Salyzyn14d39b32015-04-13 14:24:45 -0700629 return strdup(name);
Mark Salyzyn1435b472015-03-16 08:26:05 -0700630}