logd: statistics per-pid filter
Primarily gives access to the Chattiest TIDs and TAGs
associated with a pid.
Has a secondary effect of allowing us to pull out the
command line, comm and in some cases the associated
PACKAGE for a specific pid while the logs are still
present even if the executable is gone.
Bug: 26029733
Bug: 21615139
Change-Id: I1ea63165a680a9318360579b70b1512078ed5682
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index e103359..7394f11 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -210,9 +210,20 @@
}
unsigned int logMask = -1;
+ pid_t pid = 0;
if (argc > 1) {
logMask = 0;
for (int i = 1; i < argc; ++i) {
+ static const char _pid[] = "pid=";
+ if (!strncmp(argv[i], _pid, sizeof(_pid) - 1)) {
+ pid = atol(argv[i] + sizeof(_pid) - 1);
+ if (pid == 0) {
+ cli->sendMsg("PID Error");
+ return 0;
+ }
+ continue;
+ }
+
int id = atoi(argv[i]);
if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
cli->sendMsg("Range Error");
@@ -222,7 +233,8 @@
}
}
- cli->sendMsg(package_string(mBuf.formatStatistics(uid, logMask)).c_str());
+ cli->sendMsg(package_string(mBuf.formatStatistics(uid, pid,
+ logMask)).c_str());
return 0;
}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 5922f16..12aa84e 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -499,7 +499,8 @@
size_t second_worst_sizes = 0;
if (worstUidEnabledForLogid(id) && mPrune.worstUidEnabled()) {
- std::unique_ptr<const UidEntry *[]> sorted = stats.sort(2, id);
+ std::unique_ptr<const UidEntry *[]> sorted = stats.sort(
+ AID_ROOT, (pid_t)0, 2, id);
if (sorted.get()) {
if (sorted[0] && sorted[1]) {
@@ -866,10 +867,11 @@
return max;
}
-std::string LogBuffer::formatStatistics(uid_t uid, unsigned int logMask) {
+std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
+ unsigned int logMask) {
pthread_mutex_lock(&mLogElementsLock);
- std::string ret = stats.format(uid, logMask);
+ std::string ret = stats.format(uid, pid, logMask);
pthread_mutex_unlock(&mLogElementsLock);
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index c1fec73..c1614e8 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -86,7 +86,7 @@
int setSize(log_id_t id, unsigned long size);
unsigned long getSizeUsed(log_id_t id);
// *strp uses malloc, use free to release.
- std::string formatStatistics(uid_t uid, unsigned int logMask);
+ std::string formatStatistics(uid_t uid, pid_t pid, unsigned int logMask);
void enableStatistics() {
stats.enableStatistics();
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index bf0e30b..afaefc2 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -205,7 +205,7 @@
}
std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
- uid_t uid = getKey();
+ uid_t uid = getUid();
std::string name = android::base::StringPrintf("%u", uid);
const char *nameTmp = stat.uidToName(uid);
if (nameTmp) {
@@ -287,8 +287,8 @@
std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
uid_t uid = getUid();
- std::string name = android::base::StringPrintf("%5u/%u",
- getKey(), uid);
+ pid_t pid = getPid();
+ std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
const char *nameTmp = getName();
if (nameTmp) {
name += android::base::StringPrintf(
@@ -325,7 +325,7 @@
std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
uid_t uid = getUid();
std::string name = android::base::StringPrintf("%5u/%u",
- getKey(), uid);
+ getTid(), uid);
const char *nameTmp = getName();
if (nameTmp) {
name += android::base::StringPrintf(
@@ -388,7 +388,8 @@
return formatLine(name, size, pruned);
}
-std::string LogStatistics::format(uid_t uid, unsigned int logMask) const {
+std::string LogStatistics::format(uid_t uid, pid_t pid,
+ unsigned int logMask) const {
static const unsigned short spaces_total = 19;
// Report on total logging, current and for all time
@@ -461,24 +462,38 @@
name = (uid == AID_ROOT)
? "Chattiest UIDs in %s log buffer:"
: "Logging for your UID in %s log buffer:";
- output += uidTable[id].format(*this, uid, name, id);
+ output += uidTable[id].format(*this, uid, pid, name, id);
}
if (enable) {
- name = (uid == AID_ROOT) ? "Chattiest PIDs:" : "Logging for this PID:";
- output += pidTable.format(*this, uid, name);
- name = "Chattiest TIDs:";
- output += tidTable.format(*this, uid, name);
+ name = ((uid == AID_ROOT) && !pid)
+ ? "Chattiest PIDs:"
+ : "Logging for this PID:";
+ output += pidTable.format(*this, uid, pid, name);
+ name = "Chattiest TIDs";
+ if (pid) {
+ name += android::base::StringPrintf(" for PID %d", pid);
+ }
+ name += ":";
+ output += tidTable.format(*this, uid, pid, name);
}
if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
- name = "Chattiest events log buffer TAGs:";
- output += tagTable.format(*this, uid, name, LOG_ID_EVENTS);
+ name = "Chattiest events log buffer TAGs";
+ if (pid) {
+ name += android::base::StringPrintf(" for PID %d", pid);
+ }
+ name += ":";
+ output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
}
if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
- name = "Chattiest security log buffer TAGs:";
- output += securityTagTable.format(*this, uid, name, LOG_ID_SECURITY);
+ name = "Chattiest security log buffer TAGs";
+ if (pid) {
+ name += android::base::StringPrintf(" for PID %d", pid);
+ }
+ name += ":";
+ output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
}
return output;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 8558b06..6d999d2 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -47,7 +47,8 @@
typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
- std::unique_ptr<const TEntry *[]> sort(size_t len) const {
+ std::unique_ptr<const TEntry *[]> sort(uid_t uid, pid_t pid,
+ size_t len) const {
if (!len) {
std::unique_ptr<const TEntry *[]> sorted(NULL);
return sorted;
@@ -58,6 +59,14 @@
for(const_iterator it = map.begin(); it != map.end(); ++it) {
const TEntry &entry = it->second;
+
+ if ((uid != AID_ROOT) && (uid != entry.getUid())) {
+ continue;
+ }
+ if (pid && entry.getPid() && (pid != entry.getPid())) {
+ continue;
+ }
+
size_t sizes = entry.getSizes();
ssize_t index = len - 1;
while ((!retval[index] || (sizes > retval[index]->getSizes()))
@@ -118,12 +127,13 @@
std::string format(
const LogStatistics &stat,
uid_t uid,
+ pid_t pid,
const std::string &name = std::string(""),
log_id_t id = LOG_ID_MAX) const {
static const size_t maximum_sorted_entries = 32;
std::string output;
- std::unique_ptr<const TEntry *[]> sorted = sort(maximum_sorted_entries);
-
+ std::unique_ptr<const TEntry *[]> sorted = sort(uid, pid,
+ maximum_sorted_entries);
if (!sorted.get()) {
return output;
}
@@ -136,9 +146,6 @@
if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
break;
}
- if ((uid != AID_ROOT) && (uid != entry->getUid())) {
- continue;
- }
if (!headerPrinted) {
output += "\n\n";
output += entry->formatHeader(name, id);
@@ -217,14 +224,24 @@
struct UidEntry : public EntryBaseDropped {
const uid_t uid;
+ pid_t pid;
UidEntry(LogBufferElement *element):
EntryBaseDropped(element),
- uid(element->getUid()) {
+ uid(element->getUid()),
+ pid(element->getPid()) {
}
inline const uid_t&getKey() const { return uid; }
- inline const uid_t&getUid() const { return uid; }
+ inline const uid_t&getUid() const { return getKey(); }
+ inline const pid_t&getPid() const { return pid; }
+
+ inline void add(LogBufferElement *element) {
+ if (pid != element->getPid()) {
+ pid = -1;
+ }
+ EntryBase::add(element);
+ }
std::string formatHeader(const std::string &name, log_id_t id) const;
std::string format(const LogStatistics &stat, log_id_t id) const;
@@ -260,6 +277,7 @@
~PidEntry() { free(name); }
const pid_t&getKey() const { return pid; }
+ const pid_t&getPid() const { return getKey(); }
const uid_t&getUid() const { return uid; }
const char*getName() const { return name; }
@@ -291,30 +309,36 @@
struct TidEntry : public EntryBaseDropped {
const pid_t tid;
+ pid_t pid;
uid_t uid;
char *name;
- TidEntry(pid_t tid):
+ TidEntry(pid_t tid, pid_t pid):
EntryBaseDropped(),
tid(tid),
+ pid(pid),
uid(android::pidToUid(tid)),
name(android::tidToName(tid)) {
}
TidEntry(LogBufferElement *element):
EntryBaseDropped(element),
tid(element->getTid()),
+ pid(element->getPid()),
uid(element->getUid()),
name(android::tidToName(tid)) {
}
TidEntry(const TidEntry &element):
EntryBaseDropped(element),
tid(element.tid),
+ pid(element.pid),
uid(element.uid),
name(element.name ? strdup(element.name) : NULL) {
}
~TidEntry() { free(name); }
const pid_t&getKey() const { return tid; }
+ const pid_t&getTid() const { return getKey(); }
+ const pid_t&getPid() const { return pid; }
const uid_t&getUid() const { return uid; }
const char*getName() const { return name; }
@@ -330,8 +354,10 @@
inline void add(LogBufferElement *element) {
uid_t incomingUid = element->getUid();
- if (getUid() != incomingUid) {
+ pid_t incomingPid = element->getPid();
+ if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
uid = incomingUid;
+ pid = incomingPid;
free(name);
name = android::tidToName(element->getTid());
} else {
@@ -346,23 +372,28 @@
struct TagEntry : public EntryBase {
const uint32_t tag;
+ pid_t pid;
uid_t uid;
TagEntry(LogBufferElement *element):
EntryBase(element),
tag(element->getTag()),
+ pid(element->getPid()),
uid(element->getUid()) {
}
const uint32_t&getKey() const { return tag; }
+ const pid_t&getPid() const { return pid; }
const uid_t&getUid() const { return uid; }
const char*getName() const { return android::tagToName(tag); }
inline void add(LogBufferElement *element) {
- uid_t incomingUid = element->getUid();
- if (uid != incomingUid) {
+ if (uid != element->getUid()) {
uid = -1;
}
+ if (pid != element->getPid()) {
+ pid = -1;
+ }
EntryBase::add(element);
}
@@ -416,8 +447,9 @@
--mDroppedElements[log_id];
}
- std::unique_ptr<const UidEntry *[]> sort(size_t len, log_id id) {
- return uidTable[id].sort(len);
+ std::unique_ptr<const UidEntry *[]> sort(uid_t uid, pid_t pid,
+ size_t len, log_id id) {
+ return uidTable[id].sort(uid, pid, len);
}
// fast track current value by id only
@@ -429,7 +461,7 @@
size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
- std::string format(uid_t uid, unsigned int logMask) const;
+ std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
// helper (must be locked directly or implicitly by mLogElementsLock)
const char *pidToName(pid_t pid) const;