From 654904f0f9c42458cae2b1931265f97f8fb6cb95 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 20 Apr 2015 13:35:15 -0700 Subject: [PATCH] logd: Add TID statistics (cherry pick from commit 17ed6797df722464eb5cc6dfc3e1e32aec284b70) Bug: 19608965 Change-Id: Ifbf0b00c48ef12b5970b9f9f217bd1dd8f587f2c --- logd/LogBufferElement.cpp | 6 ++-- logd/LogBufferElement.h | 1 + logd/LogStatistics.cpp | 60 +++++++++++++++++++++++++++++++++++++++ logd/LogStatistics.h | 56 ++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp index f98d5cdc1..3d7237e24 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp @@ -58,7 +58,7 @@ uint32_t LogBufferElement::getTag() const { } // caller must own and free character string -static char *tidToName(pid_t tid) { +char *android::tidToName(pid_t tid) { char *retval = NULL; char buffer[256]; snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid); @@ -108,9 +108,9 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, static const char format_uid[] = "uid=%u%s too chatty%s, expire %u line%s"; char *name = parent->uidToName(mUid); - char *commName = tidToName(mTid); + char *commName = android::tidToName(mTid); if (!commName && (mTid != mPid)) { - commName = tidToName(mPid); + commName = android::tidToName(mPid); } if (!commName) { commName = parent->pidToName(mPid); diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h index bca30438e..5dabaac2d 100644 --- a/logd/LogBufferElement.h +++ b/logd/LogBufferElement.h @@ -35,6 +35,7 @@ char *uidToName(uid_t uid); // Furnished in LogStatistics.cpp. Caller must own and free returned value char *pidToName(pid_t pid); +char *tidToName(pid_t tid); // Furnished in main.cpp. Thread safe. const char *tagToName(uint32_t tag); diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp index 675b69274..90c49c0ee 100644 --- a/logd/LogStatistics.cpp +++ b/logd/LogStatistics.cpp @@ -83,6 +83,7 @@ void LogStatistics::add(LogBufferElement *e) { } pidTable.add(e->getPid(), e); + tidTable.add(e->getTid(), e); uint32_t tag = e->getTag(); if (tag) { @@ -107,6 +108,7 @@ void LogStatistics::subtract(LogBufferElement *e) { } pidTable.subtract(e->getPid(), e); + tidTable.subtract(e->getTid(), e); uint32_t tag = e->getTag(); if (tag) { @@ -128,6 +130,7 @@ void LogStatistics::drop(LogBufferElement *e) { } pidTable.drop(e->getPid(), e); + tidTable.drop(e->getTid(), e); } // caller must own and free character string @@ -390,6 +393,63 @@ void LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) { } } + if (enable) { + // Tid table + bool headerPrinted = false; + // sort() returns list of references, unique_ptr makes sure self-delete + std::unique_ptr sorted = tidTable.sort(maximum_sorted_entries); + ssize_t index = -1; + while ((index = tidTable.next(index, sorted, maximum_sorted_entries)) >= 0) { + const TidEntry *entry = sorted[index]; + uid_t u = entry->getUid(); + if ((uid != AID_ROOT) && (u != uid)) { + continue; + } + + if (!headerPrinted) { // Only print header if we have table to print + output.appendFormat("\n\n"); + android::String8 name("Chattiest TIDs:"); + android::String8 size("Size"); + android::String8 pruned("Pruned"); + format_line(output, name, size, pruned); + + name.setTo(" TID/UID COMM"); + size.setTo("BYTES"); + pruned.setTo("LINES"); + format_line(output, name, size, pruned); + + headerPrinted = true; + } + + android::String8 name(""); + name.appendFormat("%5u/%u", entry->getKey(), u); + const char *n = entry->getName(); + if (n) { + name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n); + } else { + // if we do not have a PID name, lets punt to try UID name? + char *un = uidToName(u); + if (un) { + name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un); + free(un); + } + // We tried, better to not have a name at all, we still + // have TID/UID by number to report in any case. + } + + android::String8 size(""); + size.appendFormat("%zu", entry->getSizes()); + + android::String8 pruned(""); + size_t dropped = entry->getDropped(); + if (dropped) { + pruned.appendFormat("%zu", dropped); + } + + format_line(output, name, size, pruned); + } + } + if (enable && (logMask & (1 << LOG_ID_EVENTS))) { // Tag table bool headerPrinted = false; diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h index d21a75bfe..f60f3edb6 100644 --- a/logd/LogStatistics.h +++ b/logd/LogStatistics.h @@ -209,6 +209,58 @@ struct PidEntry : public EntryBaseDropped { } }; +struct TidEntry : public EntryBaseDropped { + const pid_t tid; + uid_t uid; + char *name; + + TidEntry(pid_t t): + EntryBaseDropped(), + tid(t), + uid(android::pidToUid(t)), + name(android::tidToName(tid)) { } + TidEntry(LogBufferElement *e): + EntryBaseDropped(e), + tid(e->getTid()), + uid(e->getUid()), + name(android::tidToName(e->getTid())) { } + TidEntry(const TidEntry &c): + EntryBaseDropped(c), + tid(c.tid), + uid(c.uid), + name(c.name ? strdup(c.name) : NULL) { } + ~TidEntry() { free(name); } + + const pid_t&getKey() const { return tid; } + const uid_t&getUid() const { return uid; } + const char*getName() const { return name; } + + inline void add(pid_t t) { + if (name && !strncmp(name, "zygote", 6)) { + free(name); + name = NULL; + } + if (!name) { + char *n = android::tidToName(t); + if (n) { + name = n; + } + } + } + + inline void add(LogBufferElement *e) { + uid_t u = e->getUid(); + if (getUid() != u) { + uid = u; + free(name); + name = android::tidToName(e->getTid()); + } else { + add(e->getTid()); + } + EntryBaseDropped::add(e); + } +}; + struct TagEntry : public EntryBase { const uint32_t tag; uid_t uid; @@ -247,6 +299,10 @@ class LogStatistics { typedef LogHashtable pidTable_t; pidTable_t pidTable; + // tid to uid list + typedef LogHashtable tidTable_t; + tidTable_t tidTable; + // tag list typedef LogHashtable tagTable_t; tagTable_t tagTable;