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:
parent
5d8742feb6
commit
ee3b838e13
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue