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
This commit is contained in:
Mark Salyzyn 2015-12-17 09:58:43 -08:00
parent 5d8742feb6
commit ee3b838e13
6 changed files with 103 additions and 34 deletions

View File

@ -501,6 +501,14 @@ ssize_t android_logger_get_statistics(struct logger_list *logger_list,
remaining -= n;
cp += n;
}
if (logger_list->pid) {
n = snprintf(cp, remaining, " pid=%u", logger_list->pid);
n = min(n, remaining);
remaining -= n;
cp += n;
}
return send_log_msg(NULL, NULL, buf, len);
}

View File

@ -210,9 +210,20 @@ int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
}
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 @@ int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
}
}
cli->sendMsg(package_string(mBuf.formatStatistics(uid, logMask)).c_str());
cli->sendMsg(package_string(mBuf.formatStatistics(uid, pid,
logMask)).c_str());
return 0;
}

View File

@ -499,7 +499,8 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
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 @@ uint64_t LogBuffer::flushTo(
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);

View File

@ -86,7 +86,7 @@ public:
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();

View File

@ -205,7 +205,7 @@ std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
}
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::formatHeader(const std::string &name, log_id_t /* id */) c
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::formatHeader(const std::string &name, log_id_t /* id */) c
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 @@ std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */
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 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) const {
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;

View File

@ -47,7 +47,8 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 EntryBaseDropped : public EntryBase {
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 @@ struct PidEntry : public EntryBaseDropped {
~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 PidEntry : public EntryBaseDropped {
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 @@ struct TidEntry : public EntryBaseDropped {
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 TidEntry : public EntryBaseDropped {
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 @@ public:
--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 @@ public:
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;