logd: Add TID statistics

Bug: 19608965
Change-Id: Ifbf0b00c48ef12b5970b9f9f217bd1dd8f587f2c
This commit is contained in:
Mark Salyzyn 2015-04-20 13:35:15 -07:00
parent 344bff4391
commit 17ed6797df
4 changed files with 120 additions and 3 deletions

View File

@ -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);

View File

@ -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);

View File

@ -80,6 +80,7 @@ void LogStatistics::add(LogBufferElement *e) {
}
pidTable.add(e->getPid(), e);
tidTable.add(e->getTid(), e);
uint32_t tag = e->getTag();
if (tag) {
@ -100,6 +101,7 @@ void LogStatistics::subtract(LogBufferElement *e) {
}
pidTable.subtract(e->getPid(), e);
tidTable.subtract(e->getTid(), e);
uint32_t tag = e->getTag();
if (tag) {
@ -121,6 +123,7 @@ void LogStatistics::drop(LogBufferElement *e) {
}
pidTable.drop(e->getPid(), e);
tidTable.drop(e->getTid(), e);
}
// caller must own and free character string
@ -383,6 +386,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<const TidEntry *[]> 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;

View File

@ -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<pid_t, PidEntry> pidTable_t;
pidTable_t pidTable;
// tid to uid list
typedef LogHashtable<pid_t, TidEntry> tidTable_t;
tidTable_t tidTable;
// tag list
typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
tagTable_t tagTable;