blob: f44f56782b02057a58bc767cb73fe2a433f3e462 [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 Salyzyn34facab2014-02-06 14:48:50 -080018#include <stdarg.h>
19#include <time.h>
20
21#include <log/logger.h>
22#include <private/android_filesystem_config.h>
23#include <utils/String8.h>
24
25#include "LogStatistics.h"
26
Mark Salyzyn9a038632014-04-07 07:05:40 -070027PidStatistics::PidStatistics(pid_t pid, char *name)
Mark Salyzyn34facab2014-02-06 14:48:50 -080028 : pid(pid)
29 , mSizesTotal(0)
30 , mElementsTotal(0)
31 , mSizes(0)
Mark Salyzyn9a038632014-04-07 07:05:40 -070032 , mElements(0)
33 , name(name)
34{ }
35
36#ifdef DO_NOT_ERROR_IF_PIDSTATISTICS_USES_A_COPY_CONSTRUCTOR
37PidStatistics::PidStatistics(const PidStatistics &copy)
38 : pid(copy->pid)
39 , name(copy->name ? strdup(copy->name) : NULL)
40 , mSizesTotal(copy->mSizesTotal)
41 , mElementsTotal(copy->mElementsTotal)
42 , mSizes(copy->mSizes)
43 , mElements(copy->mElements)
44{ }
45#endif
46
47PidStatistics::~PidStatistics() {
48 free(name);
49}
50
51void PidStatistics::setName(char *new_name) {
52 free(name);
53 name = new_name;
54}
Mark Salyzyn34facab2014-02-06 14:48:50 -080055
56void PidStatistics::add(unsigned short size) {
57 mSizesTotal += size;
58 ++mElementsTotal;
59 mSizes += size;
60 ++mElements;
61}
62
63bool PidStatistics::subtract(unsigned short size) {
64 mSizes -= size;
65 --mElements;
Mark Salyzyn8e72c532014-03-26 10:46:39 -070066 return (mElements == 0) && kill(pid, 0) && (errno != EPERM);
Mark Salyzyn34facab2014-02-06 14:48:50 -080067}
68
69void PidStatistics::addTotal(size_t size, size_t element) {
70 if (pid == gone) {
71 mSizesTotal += size;
72 mElementsTotal += element;
73 }
74}
75
Mark Salyzyn9a038632014-04-07 07:05:40 -070076// must call free to release return value
77char *PidStatistics::pidToName(pid_t pid) {
78 char *retval = NULL;
79 if (pid != PidStatistics::gone) {
80 char buffer[512];
81 snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
82 int fd = open(buffer, O_RDONLY);
83 if (fd >= 0) {
84 ssize_t ret = read(fd, buffer, sizeof(buffer));
85 if (ret > 0) {
86 buffer[sizeof(buffer)-1] = '\0';
87 // frameworks intermediate state
88 if (strcmp(buffer, "<pre-initialized>")) {
89 retval = strdup(buffer);
90 }
91 }
92 close(fd);
93 }
94 }
95 return retval;
96}
97
Mark Salyzyn34facab2014-02-06 14:48:50 -080098UidStatistics::UidStatistics(uid_t uid)
Mark Salyzync8a576c2014-04-04 16:35:59 -070099 : uid(uid)
100 , mSizes(0)
101 , mElements(0) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800102 Pids.clear();
103}
104
105UidStatistics::~UidStatistics() {
106 PidStatisticsCollection::iterator it;
107 for (it = begin(); it != end();) {
108 delete (*it);
109 it = Pids.erase(it);
110 }
111}
112
113void UidStatistics::add(unsigned short size, pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700114 mSizes += size;
115 ++mElements;
116
Mark Salyzyn34facab2014-02-06 14:48:50 -0800117 PidStatistics *p;
118 PidStatisticsCollection::iterator last;
119 PidStatisticsCollection::iterator it;
120 for (last = it = begin(); it != end(); last = it, ++it) {
121 p = *it;
122 if (pid == p->getPid()) {
123 p->add(size);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800124 return;
125 }
126 }
Mark Salyzync8a576c2014-04-04 16:35:59 -0700127 // insert if the gone entry.
128 bool insert = (last != it) && (p->getPid() == p->gone);
Mark Salyzyn9a038632014-04-07 07:05:40 -0700129 p = new PidStatistics(pid, pidToName(pid));
Mark Salyzyn34facab2014-02-06 14:48:50 -0800130 if (insert) {
131 Pids.insert(last, p);
132 } else {
133 Pids.push_back(p);
134 }
135 p->add(size);
136}
137
138void UidStatistics::subtract(unsigned short size, pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700139 mSizes -= size;
140 --mElements;
141
Mark Salyzyn34facab2014-02-06 14:48:50 -0800142 PidStatisticsCollection::iterator it;
143 for (it = begin(); it != end(); ++it) {
144 PidStatistics *p = *it;
145 if (pid == p->getPid()) {
146 if (p->subtract(size)) {
147 size_t szsTotal = p->sizesTotal();
148 size_t elsTotal = p->elementsTotal();
149 delete p;
150 Pids.erase(it);
151 it = end();
152 --it;
153 if (it == end()) {
154 p = new PidStatistics(p->gone);
155 Pids.push_back(p);
156 } else {
157 p = *it;
158 if (p->getPid() != p->gone) {
159 p = new PidStatistics(p->gone);
160 Pids.push_back(p);
161 }
162 }
163 p->addTotal(szsTotal, elsTotal);
164 }
165 return;
166 }
167 }
168}
169
Mark Salyzync8a576c2014-04-04 16:35:59 -0700170void UidStatistics::sort() {
171 for (bool pass = true; pass;) {
172 pass = false;
173 PidStatisticsCollection::iterator it = begin();
174 if (it != end()) {
175 PidStatisticsCollection::iterator lt = it;
176 PidStatistics *l = (*lt);
177 while (++it != end()) {
178 PidStatistics *n = (*it);
179 if ((n->getPid() != n->gone) && (n->sizes() > l->sizes())) {
180 pass = true;
181 Pids.erase(it);
182 Pids.insert(lt, n);
183 it = lt;
184 n = l;
185 }
186 lt = it;
187 l = n;
188 }
189 }
190 }
191}
192
Mark Salyzyn34facab2014-02-06 14:48:50 -0800193size_t UidStatistics::sizes(pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700194 if (pid == pid_all) {
195 return sizes();
196 }
197
Mark Salyzyn34facab2014-02-06 14:48:50 -0800198 PidStatisticsCollection::iterator it;
199 for (it = begin(); it != end(); ++it) {
200 PidStatistics *p = *it;
Mark Salyzync8a576c2014-04-04 16:35:59 -0700201 if (pid == p->getPid()) {
202 return p->sizes();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800203 }
204 }
Mark Salyzync8a576c2014-04-04 16:35:59 -0700205 return 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800206}
207
208size_t UidStatistics::elements(pid_t pid) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700209 if (pid == pid_all) {
210 return elements();
211 }
212
Mark Salyzyn34facab2014-02-06 14:48:50 -0800213 PidStatisticsCollection::iterator it;
214 for (it = begin(); it != end(); ++it) {
215 PidStatistics *p = *it;
Mark Salyzync8a576c2014-04-04 16:35:59 -0700216 if (pid == p->getPid()) {
217 return p->elements();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800218 }
219 }
Mark Salyzync8a576c2014-04-04 16:35:59 -0700220 return 0;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800221}
222
223size_t UidStatistics::sizesTotal(pid_t pid) {
224 size_t sizes = 0;
225 PidStatisticsCollection::iterator it;
226 for (it = begin(); it != end(); ++it) {
227 PidStatistics *p = *it;
228 if ((pid == pid_all) || (pid == p->getPid())) {
229 sizes += p->sizesTotal();
230 }
231 }
232 return sizes;
233}
234
235size_t UidStatistics::elementsTotal(pid_t pid) {
236 size_t elements = 0;
237 PidStatisticsCollection::iterator it;
238 for (it = begin(); it != end(); ++it) {
239 PidStatistics *p = *it;
240 if ((pid == pid_all) || (pid == p->getPid())) {
241 elements += p->elementsTotal();
242 }
243 }
244 return elements;
245}
246
247LidStatistics::LidStatistics() {
248 Uids.clear();
249}
250
251LidStatistics::~LidStatistics() {
252 UidStatisticsCollection::iterator it;
253 for (it = begin(); it != end();) {
254 delete (*it);
255 it = Uids.erase(it);
256 }
257}
258
259void LidStatistics::add(unsigned short size, uid_t uid, pid_t pid) {
260 UidStatistics *u;
261 UidStatisticsCollection::iterator it;
262 UidStatisticsCollection::iterator last;
263
264 if (uid == (uid_t) -1) { // init
265 uid = (uid_t) AID_ROOT;
266 }
267
268 for (last = it = begin(); it != end(); last = it, ++it) {
269 u = *it;
270 if (uid == u->getUid()) {
271 u->add(size, pid);
272 if ((last != it) && ((*last)->sizesTotal() < u->sizesTotal())) {
273 Uids.erase(it);
274 Uids.insert(last, u);
275 }
276 return;
277 }
278 }
279 u = new UidStatistics(uid);
280 if ((last != it) && ((*last)->sizesTotal() < (size_t) size)) {
281 Uids.insert(last, u);
282 } else {
283 Uids.push_back(u);
284 }
285 u->add(size, pid);
286}
287
288void LidStatistics::subtract(unsigned short size, uid_t uid, pid_t pid) {
289 UidStatisticsCollection::iterator it;
290 for (it = begin(); it != end(); ++it) {
291 UidStatistics *u = *it;
292 if (uid == u->getUid()) {
293 u->subtract(size, pid);
294 return;
295 }
296 }
297}
298
Mark Salyzync8a576c2014-04-04 16:35:59 -0700299void LidStatistics::sort() {
300 for (bool pass = true; pass;) {
301 pass = false;
302 UidStatisticsCollection::iterator it = begin();
303 if (it != end()) {
304 UidStatisticsCollection::iterator lt = it;
305 UidStatistics *l = (*lt);
306 while (++it != end()) {
307 UidStatistics *n = (*it);
308 if (n->sizes() > l->sizes()) {
309 pass = true;
310 Uids.erase(it);
311 Uids.insert(lt, n);
312 it = lt;
313 n = l;
314 }
315 lt = it;
316 l = n;
317 }
318 }
319 }
320}
321
Mark Salyzyn34facab2014-02-06 14:48:50 -0800322size_t LidStatistics::sizes(uid_t uid, pid_t pid) {
323 size_t sizes = 0;
324 UidStatisticsCollection::iterator it;
325 for (it = begin(); it != end(); ++it) {
326 UidStatistics *u = *it;
327 if ((uid == uid_all) || (uid == u->getUid())) {
328 sizes += u->sizes(pid);
329 }
330 }
331 return sizes;
332}
333
334size_t LidStatistics::elements(uid_t uid, pid_t pid) {
335 size_t elements = 0;
336 UidStatisticsCollection::iterator it;
337 for (it = begin(); it != end(); ++it) {
338 UidStatistics *u = *it;
339 if ((uid == uid_all) || (uid == u->getUid())) {
340 elements += u->elements(pid);
341 }
342 }
343 return elements;
344}
345
346size_t LidStatistics::sizesTotal(uid_t uid, pid_t pid) {
347 size_t sizes = 0;
348 UidStatisticsCollection::iterator it;
349 for (it = begin(); it != end(); ++it) {
350 UidStatistics *u = *it;
351 if ((uid == uid_all) || (uid == u->getUid())) {
352 sizes += u->sizesTotal(pid);
353 }
354 }
355 return sizes;
356}
357
358size_t LidStatistics::elementsTotal(uid_t uid, pid_t pid) {
359 size_t elements = 0;
360 UidStatisticsCollection::iterator it;
361 for (it = begin(); it != end(); ++it) {
362 UidStatistics *u = *it;
363 if ((uid == uid_all) || (uid == u->getUid())) {
364 elements += u->elementsTotal(pid);
365 }
366 }
367 return elements;
368}
369
370LogStatistics::LogStatistics()
371 : start(CLOCK_MONOTONIC) {
372 log_id_for_each(i) {
373 mSizes[i] = 0;
374 mElements[i] = 0;
375 }
Mark Salyzyne457b742014-02-19 17:18:31 -0800376
377 dgram_qlen_statistics = false;
378 for(unsigned short bucket = 0; dgram_qlen(bucket); ++bucket) {
379 mMinimum[bucket].tv_sec = (uint32_t)-1;
380 mMinimum[bucket].tv_nsec = 999999999UL;
381 }
382}
383
384// Each bucket below represents a dgram_qlen of log messages. By
385// finding the minimum period of time from start to finish
386// of each dgram_qlen, we can get a performance expectation for
387// the user space logger. The net result is that the period
388// of time divided by the dgram_qlen will give us the average time
389// between log messages; at the point where the average time
390// is greater than the throughput capability of the logger
391// we will not longer require the benefits of the FIFO formed
392// by max_dgram_qlen. We will also expect to see a very visible
393// knee in the average time between log messages at this point,
394// so we do not necessarily have to compare the rate against the
395// measured performance (BM_log_maximum_retry) of the logger.
396//
397// for example (reformatted):
398//
399// Minimum time between log events per dgram_qlen:
400// 1 2 3 5 10 20 30 50 100 200 300 400 500 600
401// 5u2 12u 13u 15u 16u 27u 30u 36u 407u 3m1 3m3 3m9 3m9 5m5
402//
403// demonstrates a clear knee rising at 100, so this means that for this
404// case max_dgram_qlen = 100 would be more than sufficient to handle the
405// worst that the system could stuff into the logger. The
406// BM_log_maximum_retry performance (derated by the log collection) on the
407// same system was 33.2us so we would almost be fine with max_dgram_qlen = 50.
408// BM_log_maxumum_retry with statistics off is roughly 20us, so
409// max_dgram_qlen = 20 would work. We will be more than willing to have
410// a large engineering margin so the rule of thumb that lead us to 100 is
411// fine.
412//
413// bucket dgram_qlen are tuned for /proc/sys/net/unix/max_dgram_qlen = 300
414const unsigned short LogStatistics::mBuckets[] = {
415 1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 400, 500, 600
416};
417
418unsigned short LogStatistics::dgram_qlen(unsigned short bucket) {
419 if (bucket >= sizeof(mBuckets) / sizeof(mBuckets[0])) {
420 return 0;
421 }
422 return mBuckets[bucket];
423}
424
425unsigned long long LogStatistics::minimum(unsigned short bucket) {
426 if (mMinimum[bucket].tv_sec == LONG_MAX) {
427 return 0;
428 }
429 return mMinimum[bucket].nsec();
430}
431
432void LogStatistics::recordDiff(log_time diff, unsigned short bucket) {
433 if ((diff.tv_sec || diff.tv_nsec) && (mMinimum[bucket] > diff)) {
434 mMinimum[bucket] = diff;
435 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800436}
437
438void LogStatistics::add(unsigned short size,
439 log_id_t log_id, uid_t uid, pid_t pid) {
440 mSizes[log_id] += size;
441 ++mElements[log_id];
442 id(log_id).add(size, uid, pid);
443}
444
445void LogStatistics::subtract(unsigned short size,
446 log_id_t log_id, uid_t uid, pid_t pid) {
447 mSizes[log_id] -= size;
448 --mElements[log_id];
449 id(log_id).subtract(size, uid, pid);
450}
451
452size_t LogStatistics::sizes(log_id_t log_id, uid_t uid, pid_t pid) {
453 if (log_id != log_id_all) {
454 return id(log_id).sizes(uid, pid);
455 }
456 size_t sizes = 0;
457 log_id_for_each(i) {
458 sizes += id(i).sizes(uid, pid);
459 }
460 return sizes;
461}
462
463size_t LogStatistics::elements(log_id_t log_id, uid_t uid, pid_t pid) {
464 if (log_id != log_id_all) {
465 return id(log_id).elements(uid, pid);
466 }
467 size_t elements = 0;
468 log_id_for_each(i) {
469 elements += id(i).elements(uid, pid);
470 }
471 return elements;
472}
473
474size_t LogStatistics::sizesTotal(log_id_t log_id, uid_t uid, pid_t pid) {
475 if (log_id != log_id_all) {
476 return id(log_id).sizesTotal(uid, pid);
477 }
478 size_t sizes = 0;
479 log_id_for_each(i) {
480 sizes += id(i).sizesTotal(uid, pid);
481 }
482 return sizes;
483}
484
485size_t LogStatistics::elementsTotal(log_id_t log_id, uid_t uid, pid_t pid) {
486 if (log_id != log_id_all) {
487 return id(log_id).elementsTotal(uid, pid);
488 }
489 size_t elements = 0;
490 log_id_for_each(i) {
491 elements += id(i).elementsTotal(uid, pid);
492 }
493 return elements;
494}
495
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800496void LogStatistics::format(char **buf,
497 uid_t uid, unsigned int logMask, log_time oldest) {
Mark Salyzyn9a038632014-04-07 07:05:40 -0700498 static const unsigned short spaces_current = 13;
499 static const unsigned short spaces_total = 19;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800500
501 if (*buf) {
Greg Hackmann239605e2014-04-06 21:25:58 -0700502 free(*buf);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800503 *buf = NULL;
504 }
505
506 android::String8 string(" span -> size/num");
507 size_t oldLength;
508 short spaces = 2;
509
510 log_id_for_each(i) {
Mark Salyzync8a576c2014-04-04 16:35:59 -0700511 if (!logMask & (1 << i)) {
512 continue;
513 }
514 oldLength = string.length();
515 if (spaces < 0) {
516 spaces = 0;
517 }
518 string.appendFormat("%*s%s", spaces, "", android_log_id_to_name(i));
519 spaces += spaces_total + oldLength - string.length();
520
521 LidStatistics &l = id(i);
522 l.sort();
523
524 UidStatisticsCollection::iterator iu;
525 for (iu = l.begin(); iu != l.end(); ++iu) {
526 (*iu)->sort();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800527 }
528 }
529
530 spaces = 1;
531 log_time t(CLOCK_MONOTONIC);
532 unsigned long long d = t.nsec() - start.nsec();
533 string.appendFormat("\nTotal%4llu:%02llu:%02llu.%09llu",
534 d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
535 (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
536
537 log_id_for_each(i) {
538 if (!(logMask & (1 << i))) {
539 continue;
540 }
541 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800542 if (spaces < 0) {
543 spaces = 0;
544 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800545 string.appendFormat("%*s%zu/%zu", spaces, "",
546 sizesTotal(i), elementsTotal(i));
547 spaces += spaces_total + oldLength - string.length();
548 }
549
550 spaces = 1;
551 d = t.nsec() - oldest.nsec();
552 string.appendFormat("\nNow%6llu:%02llu:%02llu.%09llu",
553 d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
554 (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
555
556 log_id_for_each(i) {
557 if (!(logMask & (1 << i))) {
558 continue;
559 }
560
561 size_t els = elements(i);
562 if (els) {
563 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800564 if (spaces < 0) {
565 spaces = 0;
566 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800567 string.appendFormat("%*s%zu/%zu", spaces, "", sizes(i), els);
568 spaces -= string.length() - oldLength;
569 }
570 spaces += spaces_total;
571 }
572
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700573 // Construct list of worst spammers by Pid
574 static const unsigned char num_spammers = 10;
575 bool header = false;
576
577 log_id_for_each(i) {
578 if (!(logMask & (1 << i))) {
579 continue;
580 }
581
582 PidStatisticsCollection pids;
583 pids.clear();
584
585 LidStatistics &l = id(i);
586 UidStatisticsCollection::iterator iu;
587 for (iu = l.begin(); iu != l.end(); ++iu) {
588 UidStatistics &u = *(*iu);
589 PidStatisticsCollection::iterator ip;
590 for (ip = u.begin(); ip != u.end(); ++ip) {
591 PidStatistics *p = (*ip);
592 if (p->getPid() == p->gone) {
593 break;
594 }
595
596 size_t mySizes = p->sizes();
597
598 PidStatisticsCollection::iterator q;
599 unsigned char num = 0;
600 for (q = pids.begin(); q != pids.end(); ++q) {
601 if (mySizes > (*q)->sizes()) {
602 pids.insert(q, p);
603 break;
604 }
605 // do we need to traverse deeper in the list?
606 if (++num > num_spammers) {
607 break;
608 }
609 }
610 if (q == pids.end()) {
611 pids.push_back(p);
612 }
613 }
614 }
615
616 size_t threshold = sizes(i);
617 if (threshold < 65536) {
618 threshold = 65536;
619 }
620 threshold /= 100;
621
622 PidStatisticsCollection::iterator pt = pids.begin();
623
624 for(int line = 0;
625 (pt != pids.end()) && (line < num_spammers);
626 ++line, pt = pids.erase(pt)) {
627 PidStatistics *p = *pt;
628
629 size_t sizes = p->sizes();
630 if (sizes < threshold) {
631 break;
632 }
633
634 char *name = p->getName();
635 pid_t pid = p->getPid();
636 if (!name || !*name) {
637 name = pidToName(pid);
638 if (name) {
639 if (*name) {
640 p->setName(name);
641 } else {
642 free(name);
643 name = NULL;
644 }
645 }
646 }
647
648 if (!header) {
649 string.appendFormat("\n\nChattiest clients:\n"
650 "log id %-*s PID[?] name",
651 spaces_total, "size/total");
652 header = true;
653 }
654
655 size_t sizesTotal = p->sizesTotal();
656
657 android::String8 sz("");
658 sz.appendFormat((sizes != sizesTotal) ? "%zu/%zu" : "%zu",
659 sizes, sizesTotal);
660
661 android::String8 pd("");
662 pd.appendFormat("%u%c", pid,
663 (kill(pid, 0) && (errno != EPERM)) ? '?' : ' ');
664
665 string.appendFormat("\n%-7s%-*s %-7s%s",
666 line ? "" : android_log_id_to_name(i),
667 spaces_total, sz.string(), pd.string(),
668 name ? name : "");
669 }
670
671 pids.clear();
672 }
673
Mark Salyzyne457b742014-02-19 17:18:31 -0800674 if (dgram_qlen_statistics) {
675 const unsigned short spaces_time = 6;
676 const unsigned long long max_seconds = 100000;
677 spaces = 0;
678 string.append("\n\nMinimum time between log events per dgram_qlen:\n");
679 for(unsigned short i = 0; dgram_qlen(i); ++i) {
680 oldLength = string.length();
681 if (spaces < 0) {
682 spaces = 0;
683 }
684 string.appendFormat("%*s%u", spaces, "", dgram_qlen(i));
685 spaces += spaces_time + oldLength - string.length();
686 }
687 string.append("\n");
688 spaces = 0;
689 unsigned short n;
690 for(unsigned short i = 0; (n = dgram_qlen(i)); ++i) {
691 unsigned long long duration = minimum(i);
692 if (duration) {
693 duration /= n;
694 if (duration >= (NS_PER_SEC * max_seconds)) {
695 duration = NS_PER_SEC * (max_seconds - 1);
696 }
697 oldLength = string.length();
698 if (spaces < 0) {
699 spaces = 0;
700 }
701 string.appendFormat("%*s", spaces, "");
702 if (duration >= (NS_PER_SEC * 10)) {
703 string.appendFormat("%llu",
704 (duration + (NS_PER_SEC / 2))
705 / NS_PER_SEC);
706 } else if (duration >= (NS_PER_SEC / (1000 / 10))) {
707 string.appendFormat("%llum",
708 (duration + (NS_PER_SEC / 2 / 1000))
709 / (NS_PER_SEC / 1000));
710 } else if (duration >= (NS_PER_SEC / (1000000 / 10))) {
711 string.appendFormat("%lluu",
712 (duration + (NS_PER_SEC / 2 / 1000000))
713 / (NS_PER_SEC / 1000000));
714 } else {
715 string.appendFormat("%llun", duration);
716 }
717 spaces -= string.length() - oldLength;
718 }
719 spaces += spaces_time;
720 }
721 }
722
Mark Salyzyn34facab2014-02-06 14:48:50 -0800723 log_id_for_each(i) {
724 if (!(logMask & (1 << i))) {
725 continue;
726 }
727
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700728 header = false;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800729 bool first = true;
730
731 UidStatisticsCollection::iterator ut;
732 for(ut = id(i).begin(); ut != id(i).end(); ++ut) {
733 UidStatistics *up = *ut;
734 if ((uid != AID_ROOT) && (uid != up->getUid())) {
735 continue;
736 }
737
738 PidStatisticsCollection::iterator pt = up->begin();
739 if (pt == up->end()) {
740 continue;
741 }
742
743 android::String8 intermediate;
744
745 if (!header) {
746 // header below tuned to match spaces_total and spaces_current
747 spaces = 0;
748 intermediate = string.format("%s: UID/PID Total size/num",
749 android_log_id_to_name(i));
750 string.appendFormat("\n\n%-31sNow "
751 "UID/PID[?] Total Now",
752 intermediate.string());
753 intermediate.clear();
754 header = true;
755 }
756
757 bool oneline = ++pt == up->end();
758 --pt;
759
760 if (!oneline) {
761 first = true;
Mark Salyzyne457b742014-02-19 17:18:31 -0800762 } else if (!first && (spaces > 0)) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800763 string.appendFormat("%*s", spaces, "");
764 }
765 spaces = 0;
766
767 uid_t u = up->getUid();
768 pid_t p = (*pt)->getPid();
769
770 intermediate = string.format(oneline
771 ? ((p == PidStatistics::gone)
772 ? "%d/?"
773 : "%d/%d")
774 : "%d",
775 u, p);
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700776 string.appendFormat(first ? "\n%-12s" : "%-12s",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800777 intermediate.string());
778 intermediate.clear();
779
780 size_t elsTotal = up->elementsTotal();
781 oldLength = string.length();
782 string.appendFormat("%zu/%zu", up->sizesTotal(), elsTotal);
783 spaces += spaces_total + oldLength - string.length();
784
785 size_t els = up->elements();
786 if (els == elsTotal) {
Mark Salyzyne457b742014-02-19 17:18:31 -0800787 if (spaces < 0) {
788 spaces = 0;
789 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800790 string.appendFormat("%*s=", spaces, "");
791 spaces = -1;
792 } else if (els) {
793 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800794 if (spaces < 0) {
795 spaces = 0;
796 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800797 string.appendFormat("%*s%zu/%zu", spaces, "", up->sizes(), els);
798 spaces -= string.length() - oldLength;
799 }
800 spaces += spaces_current;
801
802 first = !first;
803
804 if (oneline) {
805 continue;
806 }
807
808 size_t gone_szs = 0;
809 size_t gone_els = 0;
810
811 for(; pt != up->end(); ++pt) {
812 PidStatistics *pp = *pt;
813 pid_t p = pp->getPid();
814
815 // If a PID no longer has any current logs, and is not
816 // active anymore, skip & report totals for gone.
817 elsTotal = pp->elementsTotal();
818 size_t szsTotal = pp->sizesTotal();
819 if (p == pp->gone) {
820 gone_szs += szsTotal;
821 gone_els += elsTotal;
822 continue;
823 }
824 els = pp->elements();
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700825 bool gone = kill(p, 0) && (errno != EPERM);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800826 if (gone && (els == 0)) {
827 // ToDo: garbage collection: move this statistical bucket
828 // from its current UID/PID to UID/? (races and
829 // wrap around are our achilles heel). Below is
830 // merely lipservice to catch PIDs that were still
831 // around when the stats were pruned to zero.
832 gone_szs += szsTotal;
833 gone_els += elsTotal;
834 continue;
835 }
836
Mark Salyzyne457b742014-02-19 17:18:31 -0800837 if (!first && (spaces > 0)) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800838 string.appendFormat("%*s", spaces, "");
839 }
840 spaces = 0;
841
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700842 intermediate = string.format(gone ? "%d/%d?" : "%d/%d", u, p);
843 string.appendFormat(first ? "\n%-12s" : "%-12s",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800844 intermediate.string());
845 intermediate.clear();
846
847 oldLength = string.length();
848 string.appendFormat("%zu/%zu", szsTotal, elsTotal);
849 spaces += spaces_total + oldLength - string.length();
850
851 if (els == elsTotal) {
Mark Salyzyne457b742014-02-19 17:18:31 -0800852 if (spaces < 0) {
853 spaces = 0;
854 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800855 string.appendFormat("%*s=", spaces, "");
856 spaces = -1;
857 } else if (els) {
858 oldLength = string.length();
Mark Salyzyne457b742014-02-19 17:18:31 -0800859 if (spaces < 0) {
860 spaces = 0;
861 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800862 string.appendFormat("%*s%zu/%zu", spaces, "",
863 pp->sizes(), els);
864 spaces -= string.length() - oldLength;
865 }
866 spaces += spaces_current;
867
868 first = !first;
869 }
870
871 if (gone_els) {
Mark Salyzyne457b742014-02-19 17:18:31 -0800872 if (!first && (spaces > 0)) {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800873 string.appendFormat("%*s", spaces, "");
874 }
875
876 intermediate = string.format("%d/?", u);
Mark Salyzyn8e72c532014-03-26 10:46:39 -0700877 string.appendFormat(first ? "\n%-12s" : "%-12s",
Mark Salyzyn34facab2014-02-06 14:48:50 -0800878 intermediate.string());
879 intermediate.clear();
880
881 spaces = spaces_total + spaces_current;
882
883 oldLength = string.length();
884 string.appendFormat("%zu/%zu", gone_szs, gone_els);
885 spaces -= string.length() - oldLength;
886
887 first = !first;
888 }
889 }
890 }
891
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800892 *buf = strdup(string.string());
Mark Salyzyn34facab2014-02-06 14:48:50 -0800893}
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700894
895uid_t LogStatistics::pidToUid(pid_t pid) {
896 log_id_for_each(i) {
897 LidStatistics &l = id(i);
898 UidStatisticsCollection::iterator iu;
899 for (iu = l.begin(); iu != l.end(); ++iu) {
900 UidStatistics &u = *(*iu);
901 PidStatisticsCollection::iterator ip;
902 for (ip = u.begin(); ip != u.end(); ++ip) {
903 if ((*ip)->getPid() == pid) {
904 return u.getUid();
905 }
906 }
907 }
908 }
909 return getuid(); // associate this with the logger
910}