diff options
author | Mark Salyzyn | 2015-03-16 14:04:09 -0500 |
---|---|---|
committer | Mark Salyzyn | 2015-04-10 17:45:08 -0500 |
commit | ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6 (patch) | |
tree | 7270dcf317cb23df7f8386afc6031053dd53b920 /logd/LogBufferElement.cpp | |
parent | 65937e9bac665e216268d7341094afcaa52ef8c1 (diff) | |
download | platform-system-core-ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6.tar.gz platform-system-core-ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6.tar.xz platform-system-core-ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6.zip |
logd: annotate worst-UID pruned entries
- internal dropped entries are associated by prune by worst UID
and are applied by UID and by PID
- track dropped entries by rewriting them in place
- merge similar dropped entries together for same UID(implied),
PID and TID so that blame can more clearly be placed
- allow aging of dropped entries by the general backgound pruning
- report individual dropped entries formatted to reader
- add statistics to track dropped entries by UID, the combination
of statistics and dropped logging can track over-the-top Chattiest
clients.
Bug: 19608965
Change-Id: Ibc68480df0c69c55703270cd70c6b26aea165853
Diffstat (limited to 'logd/LogBufferElement.cpp')
-rw-r--r-- | logd/LogBufferElement.cpp | 78 |
1 files changed, 72 insertions, 6 deletions
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp index 5e780b557..a173e63fe 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp | |||
@@ -14,14 +14,17 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <endian.h> | ||
17 | #include <stdio.h> | 18 | #include <stdio.h> |
18 | #include <string.h> | 19 | #include <string.h> |
19 | #include <time.h> | 20 | #include <time.h> |
20 | #include <unistd.h> | 21 | #include <unistd.h> |
21 | 22 | ||
22 | #include <log/logger.h> | 23 | #include <log/logger.h> |
24 | #include <private/android_logger.h> | ||
23 | 25 | ||
24 | #include "LogBufferElement.h" | 26 | #include "LogBufferElement.h" |
27 | #include "LogCommand.h" | ||
25 | #include "LogReader.h" | 28 | #include "LogReader.h" |
26 | 29 | ||
27 | const uint64_t LogBufferElement::FLUSH_ERROR(0); | 30 | const uint64_t LogBufferElement::FLUSH_ERROR(0); |
@@ -45,11 +48,59 @@ LogBufferElement::~LogBufferElement() { | |||
45 | delete [] mMsg; | 48 | delete [] mMsg; |
46 | } | 49 | } |
47 | 50 | ||
51 | // assumption: mMsg == NULL | ||
52 | size_t LogBufferElement::populateDroppedMessage(char *&buffer, bool privileged) { | ||
53 | static const char format_uid[] = "uid=%u dropped=%u"; | ||
54 | static const size_t unprivileged_offset = 7; | ||
55 | static const char tag[] = "logd"; | ||
56 | |||
57 | size_t len; | ||
58 | if (privileged) { | ||
59 | len = snprintf(NULL, 0, format_uid, mUid, mDropped); | ||
60 | } else { | ||
61 | len = snprintf(NULL, 0, format_uid + unprivileged_offset, mDropped); | ||
62 | } | ||
63 | |||
64 | size_t hdrLen; | ||
65 | if (mLogId == LOG_ID_EVENTS) { | ||
66 | hdrLen = sizeof(android_log_event_string_t); | ||
67 | } else { | ||
68 | hdrLen = 1 + sizeof(tag); | ||
69 | } | ||
70 | |||
71 | buffer = static_cast<char *>(calloc(1, hdrLen + len + 1)); | ||
72 | if (!buffer) { | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | size_t retval = hdrLen + len; | ||
77 | if (mLogId == LOG_ID_EVENTS) { | ||
78 | android_log_event_string_t *e = reinterpret_cast<android_log_event_string_t *>(buffer); | ||
79 | |||
80 | e->header.tag = htole32(LOGD_LOG_TAG); | ||
81 | e->type = EVENT_TYPE_STRING; | ||
82 | e->length = htole32(len); | ||
83 | } else { | ||
84 | ++retval; | ||
85 | buffer[0] = ANDROID_LOG_INFO; | ||
86 | strcpy(buffer + 1, tag); | ||
87 | } | ||
88 | |||
89 | if (privileged) { | ||
90 | snprintf(buffer + hdrLen, len + 1, format_uid, mUid, mDropped); | ||
91 | } else { | ||
92 | snprintf(buffer + hdrLen, len + 1, format_uid + unprivileged_offset, mDropped); | ||
93 | } | ||
94 | |||
95 | return retval; | ||
96 | } | ||
97 | |||
48 | uint64_t LogBufferElement::flushTo(SocketClient *reader) { | 98 | uint64_t LogBufferElement::flushTo(SocketClient *reader) { |
49 | struct logger_entry_v3 entry; | 99 | struct logger_entry_v3 entry; |
100 | |||
50 | memset(&entry, 0, sizeof(struct logger_entry_v3)); | 101 | memset(&entry, 0, sizeof(struct logger_entry_v3)); |
102 | |||
51 | entry.hdr_size = sizeof(struct logger_entry_v3); | 103 | entry.hdr_size = sizeof(struct logger_entry_v3); |
52 | entry.len = mMsgLen; | ||
53 | entry.lid = mLogId; | 104 | entry.lid = mLogId; |
54 | entry.pid = mPid; | 105 | entry.pid = mPid; |
55 | entry.tid = mTid; | 106 | entry.tid = mTid; |
@@ -59,11 +110,26 @@ uint64_t LogBufferElement::flushTo(SocketClient *reader) { | |||
59 | struct iovec iovec[2]; | 110 | struct iovec iovec[2]; |
60 | iovec[0].iov_base = &entry; | 111 | iovec[0].iov_base = &entry; |
61 | iovec[0].iov_len = sizeof(struct logger_entry_v3); | 112 | iovec[0].iov_len = sizeof(struct logger_entry_v3); |
62 | iovec[1].iov_base = mMsg; | 113 | |
63 | iovec[1].iov_len = mMsgLen; | 114 | char *buffer = NULL; |
64 | if (reader->sendDatav(iovec, 2)) { | 115 | |
65 | return FLUSH_ERROR; | 116 | if (!mMsg) { |
117 | entry.len = populateDroppedMessage(buffer, clientHasLogCredentials(reader)); | ||
118 | if (!entry.len) { | ||
119 | return mSequence; | ||
120 | } | ||
121 | iovec[1].iov_base = buffer; | ||
122 | } else { | ||
123 | entry.len = mMsgLen; | ||
124 | iovec[1].iov_base = mMsg; | ||
125 | } | ||
126 | iovec[1].iov_len = entry.len; | ||
127 | |||
128 | uint64_t retval = reader->sendDatav(iovec, 2) ? FLUSH_ERROR : mSequence; | ||
129 | |||
130 | if (buffer) { | ||
131 | free(buffer); | ||
66 | } | 132 | } |
67 | 133 | ||
68 | return mSequence; | 134 | return retval; |
69 | } | 135 | } |