blob: f60f3edb65e37b6059947e18f2f9eecbe881565d [file] [log] [blame]
Mark Salyzyn34facab2014-02-06 14:48:50 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LOGD_LOG_STATISTICS_H__
18#define _LOGD_LOG_STATISTICS_H__
19
Mark Salyzyn720f6d12015-03-16 08:26:05 -070020#include <memory>
21#include <stdlib.h>
Mark Salyzyn34facab2014-02-06 14:48:50 -080022#include <sys/types.h>
23
24#include <log/log.h>
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -070025#include <utils/BasicHashtable.h>
26
27#include "LogBufferElement.h"
Mark Salyzyn34facab2014-02-06 14:48:50 -080028
29#define log_id_for_each(i) \
30 for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))
31
Mark Salyzyn720f6d12015-03-16 08:26:05 -070032template <typename TKey, typename TEntry>
33class LogHashtable : public android::BasicHashtable<TKey, TEntry> {
34public:
35 std::unique_ptr<const TEntry *[]> sort(size_t n) {
36 if (!n) {
37 std::unique_ptr<const TEntry *[]> sorted(NULL);
38 return sorted;
39 }
40
41 const TEntry **retval = new const TEntry* [n];
42 memset(retval, 0, sizeof(*retval) * n);
43
44 ssize_t index = -1;
45 while ((index = android::BasicHashtable<TKey, TEntry>::next(index)) >= 0) {
46 const TEntry &entry = android::BasicHashtable<TKey, TEntry>::entryAt(index);
47 size_t s = entry.getSizes();
48 ssize_t i = n - 1;
49 while ((!retval[i] || (s > retval[i]->getSizes())) && (--i >= 0))
50 ;
51 if (++i < (ssize_t)n) {
52 size_t b = n - i - 1;
53 if (b) {
54 memmove(&retval[i+1], &retval[i], b * sizeof(retval[0]));
55 }
56 retval[i] = &entry;
57 }
58 }
59 std::unique_ptr<const TEntry *[]> sorted(retval);
60 return sorted;
61 }
62
63 // Iteration handler for the sort method output
64 static ssize_t next(ssize_t index, std::unique_ptr<const TEntry *[]> &sorted, size_t n) {
65 ++index;
66 if (!sorted.get() || (index < 0) || (n <= (size_t)index) || !sorted[index]
67 || (sorted[index]->getSizes() <= (sorted[0]->getSizes() / 100))) {
68 return -1;
69 }
70 return index;
71 }
72
73 ssize_t next(ssize_t index) {
74 return android::BasicHashtable<TKey, TEntry>::next(index);
75 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -070076
77 size_t add(TKey key, LogBufferElement *e) {
78 android::hash_t hash = android::hash_type(key);
79 ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, hash, key);
80 if (index == -1) {
81 return android::BasicHashtable<TKey, TEntry>::add(hash, TEntry(e));
82 }
83 android::BasicHashtable<TKey, TEntry>::editEntryAt(index).add(e);
84 return index;
85 }
86
87 inline size_t add(TKey key) {
88 android::hash_t hash = android::hash_type(key);
89 ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, hash, key);
90 if (index == -1) {
91 return android::BasicHashtable<TKey, TEntry>::add(hash, TEntry(key));
92 }
93 android::BasicHashtable<TKey, TEntry>::editEntryAt(index).add(key);
94 return index;
95 }
96
97 void subtract(TKey key, LogBufferElement *e) {
98 ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, android::hash_type(key), key);
99 if ((index != -1)
100 && android::BasicHashtable<TKey, TEntry>::editEntryAt(index).subtract(e)) {
101 android::BasicHashtable<TKey, TEntry>::removeAt(index);
102 }
103 }
104
105 inline void drop(TKey key, LogBufferElement *e) {
106 ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, android::hash_type(key), key);
107 if (index != -1) {
108 android::BasicHashtable<TKey, TEntry>::editEntryAt(index).drop(e);
109 }
110 }
111
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700112};
113
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700114struct EntryBase {
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700115 size_t size;
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700116
117 EntryBase():size(0) { }
118 EntryBase(LogBufferElement *e):size(e->getMsgLen()) { }
119
120 size_t getSizes() const { return size; }
121
122 inline void add(LogBufferElement *e) { size += e->getMsgLen(); }
123 inline bool subtract(LogBufferElement *e) { size -= e->getMsgLen(); return !size; }
124};
125
126struct EntryBaseDropped : public EntryBase {
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700127 size_t dropped;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800128
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700129 EntryBaseDropped():dropped(0) { }
130 EntryBaseDropped(LogBufferElement *e):EntryBase(e),dropped(e->getDropped()){ }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800131
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700132 size_t getDropped() const { return dropped; }
133
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700134 inline void add(LogBufferElement *e) {
135 dropped += e->getDropped();
136 EntryBase::add(e);
137 }
138 inline bool subtract(LogBufferElement *e) {
139 dropped -= e->getDropped();
140 return EntryBase::subtract(e) && !dropped;
141 }
142 inline void drop(LogBufferElement *e) {
143 dropped += 1;
144 EntryBase::subtract(e);
145 }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800146};
147
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700148struct UidEntry : public EntryBaseDropped {
149 const uid_t uid;
150
151 UidEntry(LogBufferElement *e):EntryBaseDropped(e),uid(e->getUid()) { }
152
153 inline const uid_t&getKey() const { return uid; }
154};
155
156namespace android {
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700157uid_t pidToUid(pid_t pid);
158}
159
160struct PidEntry : public EntryBaseDropped {
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700161 const pid_t pid;
162 uid_t uid;
163 char *name;
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700164
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700165 PidEntry(pid_t p):
166 EntryBaseDropped(),
167 pid(p),
168 uid(android::pidToUid(p)),
169 name(android::pidToName(pid)) { }
170 PidEntry(LogBufferElement *e):
171 EntryBaseDropped(e),
172 pid(e->getPid()),
173 uid(e->getUid()),
174 name(android::pidToName(e->getPid())) { }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700175 PidEntry(const PidEntry &c):
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700176 EntryBaseDropped(c),
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700177 pid(c.pid),
178 uid(c.uid),
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700179 name(c.name ? strdup(c.name) : NULL) { }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700180 ~PidEntry() { free(name); }
181
182 const pid_t&getKey() const { return pid; }
183 const uid_t&getUid() const { return uid; }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700184 const char*getName() const { return name; }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700185
186 inline void add(pid_t p) {
Mark Salyzynaa43ae22015-04-20 10:27:38 -0700187 if (name && !strncmp(name, "zygote", 6)) {
188 free(name);
189 name = NULL;
190 }
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700191 if (!name) {
192 char *n = android::pidToName(p);
193 if (n) {
194 name = n;
195 }
196 }
197 }
198
199 inline void add(LogBufferElement *e) {
200 uid_t u = e->getUid();
201 if (getUid() != u) {
202 uid = u;
203 free(name);
204 name = android::pidToName(e->getPid());
205 } else {
206 add(e->getPid());
207 }
208 EntryBaseDropped::add(e);
209 }
Mark Salyzyn344bff42015-04-13 14:24:45 -0700210};
Mark Salyzyn81b3eab2015-04-13 14:24:45 -0700211
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700212struct TidEntry : public EntryBaseDropped {
213 const pid_t tid;
214 uid_t uid;
215 char *name;
216
217 TidEntry(pid_t t):
218 EntryBaseDropped(),
219 tid(t),
220 uid(android::pidToUid(t)),
221 name(android::tidToName(tid)) { }
222 TidEntry(LogBufferElement *e):
223 EntryBaseDropped(e),
224 tid(e->getTid()),
225 uid(e->getUid()),
226 name(android::tidToName(e->getTid())) { }
227 TidEntry(const TidEntry &c):
228 EntryBaseDropped(c),
229 tid(c.tid),
230 uid(c.uid),
231 name(c.name ? strdup(c.name) : NULL) { }
232 ~TidEntry() { free(name); }
233
234 const pid_t&getKey() const { return tid; }
235 const uid_t&getUid() const { return uid; }
236 const char*getName() const { return name; }
237
238 inline void add(pid_t t) {
239 if (name && !strncmp(name, "zygote", 6)) {
240 free(name);
241 name = NULL;
242 }
243 if (!name) {
244 char *n = android::tidToName(t);
245 if (n) {
246 name = n;
247 }
248 }
249 }
250
251 inline void add(LogBufferElement *e) {
252 uid_t u = e->getUid();
253 if (getUid() != u) {
254 uid = u;
255 free(name);
256 name = android::tidToName(e->getTid());
257 } else {
258 add(e->getTid());
259 }
260 EntryBaseDropped::add(e);
261 }
262};
263
Mark Salyzyn344bff42015-04-13 14:24:45 -0700264struct TagEntry : public EntryBase {
265 const uint32_t tag;
266 uid_t uid;
267
268 TagEntry(LogBufferElement *e):
269 EntryBase(e),
270 tag(e->getTag()),
271 uid(e->getUid()) { }
272
273 const uint32_t&getKey() const { return tag; }
274 const uid_t&getUid() const { return uid; }
275 const char*getName() const { return android::tagToName(tag); }
276
277 inline void add(LogBufferElement *e) {
278 uid_t u = e->getUid();
279 if (uid != u) {
280 uid = -1;
281 }
282 EntryBase::add(e);
283 }
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700284};
285
Mark Salyzyn34facab2014-02-06 14:48:50 -0800286// Log Statistics
287class LogStatistics {
Mark Salyzyn34facab2014-02-06 14:48:50 -0800288 size_t mSizes[LOG_ID_MAX];
289 size_t mElements[LOG_ID_MAX];
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700290 size_t mSizesTotal[LOG_ID_MAX];
291 size_t mElementsTotal[LOG_ID_MAX];
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700292 bool enable;
Mark Salyzyn34facab2014-02-06 14:48:50 -0800293
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700294 // uid to size list
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700295 typedef LogHashtable<uid_t, UidEntry> uidTable_t;
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700296 uidTable_t uidTable[LOG_ID_MAX];
Mark Salyzyne457b742014-02-19 17:18:31 -0800297
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700298 // pid to uid list
299 typedef LogHashtable<pid_t, PidEntry> pidTable_t;
300 pidTable_t pidTable;
301
Mark Salyzyn17ed6792015-04-20 13:35:15 -0700302 // tid to uid list
303 typedef LogHashtable<pid_t, TidEntry> tidTable_t;
304 tidTable_t tidTable;
305
Mark Salyzyn344bff42015-04-13 14:24:45 -0700306 // tag list
307 typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
308 tagTable_t tagTable;
309
Mark Salyzyn34facab2014-02-06 14:48:50 -0800310public:
Mark Salyzyn34facab2014-02-06 14:48:50 -0800311 LogStatistics();
312
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700313 void enableStatistics() { enable = true; }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800314
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700315 void add(LogBufferElement *entry);
316 void subtract(LogBufferElement *entry);
Mark Salyzynab0dcf62015-03-16 12:04:09 -0700317 // entry->setDropped(1) must follow this call
318 void drop(LogBufferElement *entry);
319 // Correct for merging two entries referencing dropped content
320 void erase(LogBufferElement *e) { --mElements[e->getLogId()]; }
Mark Salyzyne457b742014-02-19 17:18:31 -0800321
Mark Salyzyn720f6d12015-03-16 08:26:05 -0700322 std::unique_ptr<const UidEntry *[]> sort(size_t n, log_id i) { return uidTable[i].sort(n); }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800323
324 // fast track current value by id only
325 size_t sizes(log_id_t id) const { return mSizes[id]; }
326 size_t elements(log_id_t id) const { return mElements[id]; }
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700327 size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
328 size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
Mark Salyzyn34facab2014-02-06 14:48:50 -0800329
330 // *strp = malloc, balance with free
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700331 void format(char **strp, uid_t uid, unsigned int logMask);
Mark Salyzyn9a038632014-04-07 07:05:40 -0700332
333 // helper
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700334 char *pidToName(pid_t pid);
Mark Salyzyn4ba03872014-04-07 07:15:33 -0700335 uid_t pidToUid(pid_t pid);
Mark Salyzyn97c1c2b2015-03-10 13:51:35 -0700336 char *uidToName(uid_t uid);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800337};
338
339#endif // _LOGD_LOG_STATISTICS_H__