1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker *
4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker *
8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker *
10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker */
16*598139dcSAndroid Build Coastguard Worker
17*598139dcSAndroid Build Coastguard Worker #include "LogStatistics.h"
18*598139dcSAndroid Build Coastguard Worker
19*598139dcSAndroid Build Coastguard Worker #include <ctype.h>
20*598139dcSAndroid Build Coastguard Worker #include <fcntl.h>
21*598139dcSAndroid Build Coastguard Worker #include <inttypes.h>
22*598139dcSAndroid Build Coastguard Worker #include <pwd.h>
23*598139dcSAndroid Build Coastguard Worker #include <stdio.h>
24*598139dcSAndroid Build Coastguard Worker #include <string.h>
25*598139dcSAndroid Build Coastguard Worker #include <sys/types.h>
26*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
27*598139dcSAndroid Build Coastguard Worker
28*598139dcSAndroid Build Coastguard Worker #include <list>
29*598139dcSAndroid Build Coastguard Worker #include <vector>
30*598139dcSAndroid Build Coastguard Worker
31*598139dcSAndroid Build Coastguard Worker #include <android-base/logging.h>
32*598139dcSAndroid Build Coastguard Worker #include <android-base/strings.h>
33*598139dcSAndroid Build Coastguard Worker #include <private/android_logger.h>
34*598139dcSAndroid Build Coastguard Worker
35*598139dcSAndroid Build Coastguard Worker #include "LogBufferElement.h"
36*598139dcSAndroid Build Coastguard Worker
37*598139dcSAndroid Build Coastguard Worker static const uint64_t hourSec = 60 * 60;
38*598139dcSAndroid Build Coastguard Worker static const uint64_t monthSec = 31 * 24 * hourSec;
39*598139dcSAndroid Build Coastguard Worker
40*598139dcSAndroid Build Coastguard Worker std::atomic<size_t> LogStatistics::SizesTotal;
41*598139dcSAndroid Build Coastguard Worker
TagNameKey(const LogStatisticsElement & element)42*598139dcSAndroid Build Coastguard Worker static std::string TagNameKey(const LogStatisticsElement& element) {
43*598139dcSAndroid Build Coastguard Worker if (IsBinary(element.log_id)) {
44*598139dcSAndroid Build Coastguard Worker uint32_t tag = element.tag;
45*598139dcSAndroid Build Coastguard Worker if (tag) {
46*598139dcSAndroid Build Coastguard Worker const char* cp = android::tagToName(tag);
47*598139dcSAndroid Build Coastguard Worker if (cp) {
48*598139dcSAndroid Build Coastguard Worker return std::string(cp);
49*598139dcSAndroid Build Coastguard Worker }
50*598139dcSAndroid Build Coastguard Worker }
51*598139dcSAndroid Build Coastguard Worker return android::base::StringPrintf("[%" PRIu32 "]", tag);
52*598139dcSAndroid Build Coastguard Worker }
53*598139dcSAndroid Build Coastguard Worker const char* msg = element.msg;
54*598139dcSAndroid Build Coastguard Worker ++msg;
55*598139dcSAndroid Build Coastguard Worker uint16_t len = element.msg_len;
56*598139dcSAndroid Build Coastguard Worker len = (len <= 1) ? 0 : strnlen(msg, len - 1);
57*598139dcSAndroid Build Coastguard Worker if (!len) {
58*598139dcSAndroid Build Coastguard Worker return "<NULL>";
59*598139dcSAndroid Build Coastguard Worker }
60*598139dcSAndroid Build Coastguard Worker return std::string(msg, len);
61*598139dcSAndroid Build Coastguard Worker }
62*598139dcSAndroid Build Coastguard Worker
LogStatistics(bool enable_statistics,bool track_total_size,std::optional<log_time> start_time)63*598139dcSAndroid Build Coastguard Worker LogStatistics::LogStatistics(bool enable_statistics, bool track_total_size,
64*598139dcSAndroid Build Coastguard Worker std::optional<log_time> start_time)
65*598139dcSAndroid Build Coastguard Worker : enable(enable_statistics), track_total_size_(track_total_size) {
66*598139dcSAndroid Build Coastguard Worker log_time now(CLOCK_REALTIME);
67*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
68*598139dcSAndroid Build Coastguard Worker mSizes[id] = 0;
69*598139dcSAndroid Build Coastguard Worker mElements[id] = 0;
70*598139dcSAndroid Build Coastguard Worker mSizesTotal[id] = 0;
71*598139dcSAndroid Build Coastguard Worker mElementsTotal[id] = 0;
72*598139dcSAndroid Build Coastguard Worker if (start_time) {
73*598139dcSAndroid Build Coastguard Worker mOldest[id] = *start_time;
74*598139dcSAndroid Build Coastguard Worker mNewest[id] = *start_time;
75*598139dcSAndroid Build Coastguard Worker } else {
76*598139dcSAndroid Build Coastguard Worker mOldest[id] = now;
77*598139dcSAndroid Build Coastguard Worker mNewest[id] = now;
78*598139dcSAndroid Build Coastguard Worker }
79*598139dcSAndroid Build Coastguard Worker }
80*598139dcSAndroid Build Coastguard Worker }
81*598139dcSAndroid Build Coastguard Worker
82*598139dcSAndroid Build Coastguard Worker namespace android {
83*598139dcSAndroid Build Coastguard Worker
sizesTotal()84*598139dcSAndroid Build Coastguard Worker size_t sizesTotal() {
85*598139dcSAndroid Build Coastguard Worker return LogStatistics::sizesTotal();
86*598139dcSAndroid Build Coastguard Worker }
87*598139dcSAndroid Build Coastguard Worker
88*598139dcSAndroid Build Coastguard Worker // caller must own and free character string
pidToName(pid_t pid)89*598139dcSAndroid Build Coastguard Worker char* pidToName(pid_t pid) {
90*598139dcSAndroid Build Coastguard Worker char* retval = nullptr;
91*598139dcSAndroid Build Coastguard Worker if (pid == 0) { // special case from auditd/klogd for kernel
92*598139dcSAndroid Build Coastguard Worker retval = strdup("logd");
93*598139dcSAndroid Build Coastguard Worker } else {
94*598139dcSAndroid Build Coastguard Worker char buffer[512];
95*598139dcSAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
96*598139dcSAndroid Build Coastguard Worker int fd = open(buffer, O_RDONLY | O_CLOEXEC);
97*598139dcSAndroid Build Coastguard Worker if (fd >= 0) {
98*598139dcSAndroid Build Coastguard Worker ssize_t ret = read(fd, buffer, sizeof(buffer));
99*598139dcSAndroid Build Coastguard Worker if (ret > 0) {
100*598139dcSAndroid Build Coastguard Worker buffer[sizeof(buffer) - 1] = '\0';
101*598139dcSAndroid Build Coastguard Worker // frameworks intermediate state
102*598139dcSAndroid Build Coastguard Worker if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
103*598139dcSAndroid Build Coastguard Worker retval = strdup(buffer);
104*598139dcSAndroid Build Coastguard Worker }
105*598139dcSAndroid Build Coastguard Worker }
106*598139dcSAndroid Build Coastguard Worker close(fd);
107*598139dcSAndroid Build Coastguard Worker }
108*598139dcSAndroid Build Coastguard Worker }
109*598139dcSAndroid Build Coastguard Worker return retval;
110*598139dcSAndroid Build Coastguard Worker }
111*598139dcSAndroid Build Coastguard Worker }
112*598139dcSAndroid Build Coastguard Worker
AddTotal(log_id_t log_id,uint16_t size)113*598139dcSAndroid Build Coastguard Worker void LogStatistics::AddTotal(log_id_t log_id, uint16_t size) {
114*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
115*598139dcSAndroid Build Coastguard Worker
116*598139dcSAndroid Build Coastguard Worker mSizesTotal[log_id] += size;
117*598139dcSAndroid Build Coastguard Worker SizesTotal += size;
118*598139dcSAndroid Build Coastguard Worker ++mElementsTotal[log_id];
119*598139dcSAndroid Build Coastguard Worker }
120*598139dcSAndroid Build Coastguard Worker
Add(LogStatisticsElement element)121*598139dcSAndroid Build Coastguard Worker void LogStatistics::Add(LogStatisticsElement element) {
122*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
123*598139dcSAndroid Build Coastguard Worker
124*598139dcSAndroid Build Coastguard Worker if (!track_total_size_) {
125*598139dcSAndroid Build Coastguard Worker element.total_len = element.msg_len;
126*598139dcSAndroid Build Coastguard Worker }
127*598139dcSAndroid Build Coastguard Worker
128*598139dcSAndroid Build Coastguard Worker log_id_t log_id = element.log_id;
129*598139dcSAndroid Build Coastguard Worker uint16_t size = element.total_len;
130*598139dcSAndroid Build Coastguard Worker mSizes[log_id] += size;
131*598139dcSAndroid Build Coastguard Worker ++mElements[log_id];
132*598139dcSAndroid Build Coastguard Worker
133*598139dcSAndroid Build Coastguard Worker mSizesTotal[log_id] += size;
134*598139dcSAndroid Build Coastguard Worker SizesTotal += size;
135*598139dcSAndroid Build Coastguard Worker ++mElementsTotal[log_id];
136*598139dcSAndroid Build Coastguard Worker
137*598139dcSAndroid Build Coastguard Worker log_time stamp(element.realtime);
138*598139dcSAndroid Build Coastguard Worker if (mNewest[log_id] < stamp) {
139*598139dcSAndroid Build Coastguard Worker // A major time update invalidates the statistics :-(
140*598139dcSAndroid Build Coastguard Worker log_time diff = stamp - mNewest[log_id];
141*598139dcSAndroid Build Coastguard Worker mNewest[log_id] = stamp;
142*598139dcSAndroid Build Coastguard Worker
143*598139dcSAndroid Build Coastguard Worker if (diff.tv_sec > hourSec) {
144*598139dcSAndroid Build Coastguard Worker // approximate Do-Your-Best fixup
145*598139dcSAndroid Build Coastguard Worker diff += mOldest[log_id];
146*598139dcSAndroid Build Coastguard Worker if ((diff > stamp) && ((diff - stamp).tv_sec < hourSec)) {
147*598139dcSAndroid Build Coastguard Worker diff = stamp;
148*598139dcSAndroid Build Coastguard Worker }
149*598139dcSAndroid Build Coastguard Worker if (diff <= stamp) {
150*598139dcSAndroid Build Coastguard Worker mOldest[log_id] = diff;
151*598139dcSAndroid Build Coastguard Worker }
152*598139dcSAndroid Build Coastguard Worker }
153*598139dcSAndroid Build Coastguard Worker }
154*598139dcSAndroid Build Coastguard Worker
155*598139dcSAndroid Build Coastguard Worker if (log_id == LOG_ID_KERNEL) {
156*598139dcSAndroid Build Coastguard Worker return;
157*598139dcSAndroid Build Coastguard Worker }
158*598139dcSAndroid Build Coastguard Worker
159*598139dcSAndroid Build Coastguard Worker uidTable[log_id].Add(element.uid, element);
160*598139dcSAndroid Build Coastguard Worker if (element.uid == AID_SYSTEM) {
161*598139dcSAndroid Build Coastguard Worker pidSystemTable[log_id].Add(element.pid, element);
162*598139dcSAndroid Build Coastguard Worker }
163*598139dcSAndroid Build Coastguard Worker
164*598139dcSAndroid Build Coastguard Worker if (!enable) {
165*598139dcSAndroid Build Coastguard Worker return;
166*598139dcSAndroid Build Coastguard Worker }
167*598139dcSAndroid Build Coastguard Worker
168*598139dcSAndroid Build Coastguard Worker pidTable.Add(element.pid, element);
169*598139dcSAndroid Build Coastguard Worker tidTable.Add(element.tid, element);
170*598139dcSAndroid Build Coastguard Worker
171*598139dcSAndroid Build Coastguard Worker uint32_t tag = element.tag;
172*598139dcSAndroid Build Coastguard Worker if (tag) {
173*598139dcSAndroid Build Coastguard Worker if (log_id == LOG_ID_SECURITY) {
174*598139dcSAndroid Build Coastguard Worker securityTagTable.Add(tag, element);
175*598139dcSAndroid Build Coastguard Worker } else {
176*598139dcSAndroid Build Coastguard Worker tagTable.Add(tag, element);
177*598139dcSAndroid Build Coastguard Worker }
178*598139dcSAndroid Build Coastguard Worker }
179*598139dcSAndroid Build Coastguard Worker
180*598139dcSAndroid Build Coastguard Worker tagNameTable.Add(TagNameKey(element), element);
181*598139dcSAndroid Build Coastguard Worker }
182*598139dcSAndroid Build Coastguard Worker
Subtract(LogStatisticsElement element)183*598139dcSAndroid Build Coastguard Worker void LogStatistics::Subtract(LogStatisticsElement element) {
184*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
185*598139dcSAndroid Build Coastguard Worker
186*598139dcSAndroid Build Coastguard Worker if (!track_total_size_) {
187*598139dcSAndroid Build Coastguard Worker element.total_len = element.msg_len;
188*598139dcSAndroid Build Coastguard Worker }
189*598139dcSAndroid Build Coastguard Worker
190*598139dcSAndroid Build Coastguard Worker log_id_t log_id = element.log_id;
191*598139dcSAndroid Build Coastguard Worker uint16_t size = element.total_len;
192*598139dcSAndroid Build Coastguard Worker mSizes[log_id] -= size;
193*598139dcSAndroid Build Coastguard Worker --mElements[log_id];
194*598139dcSAndroid Build Coastguard Worker
195*598139dcSAndroid Build Coastguard Worker if (mOldest[log_id] < element.realtime) {
196*598139dcSAndroid Build Coastguard Worker mOldest[log_id] = element.realtime;
197*598139dcSAndroid Build Coastguard Worker }
198*598139dcSAndroid Build Coastguard Worker
199*598139dcSAndroid Build Coastguard Worker if (log_id == LOG_ID_KERNEL) {
200*598139dcSAndroid Build Coastguard Worker return;
201*598139dcSAndroid Build Coastguard Worker }
202*598139dcSAndroid Build Coastguard Worker
203*598139dcSAndroid Build Coastguard Worker uidTable[log_id].Subtract(element.uid, element);
204*598139dcSAndroid Build Coastguard Worker if (element.uid == AID_SYSTEM) {
205*598139dcSAndroid Build Coastguard Worker pidSystemTable[log_id].Subtract(element.pid, element);
206*598139dcSAndroid Build Coastguard Worker }
207*598139dcSAndroid Build Coastguard Worker
208*598139dcSAndroid Build Coastguard Worker if (!enable) {
209*598139dcSAndroid Build Coastguard Worker return;
210*598139dcSAndroid Build Coastguard Worker }
211*598139dcSAndroid Build Coastguard Worker
212*598139dcSAndroid Build Coastguard Worker pidTable.Subtract(element.pid, element);
213*598139dcSAndroid Build Coastguard Worker tidTable.Subtract(element.tid, element);
214*598139dcSAndroid Build Coastguard Worker
215*598139dcSAndroid Build Coastguard Worker uint32_t tag = element.tag;
216*598139dcSAndroid Build Coastguard Worker if (tag) {
217*598139dcSAndroid Build Coastguard Worker if (log_id == LOG_ID_SECURITY) {
218*598139dcSAndroid Build Coastguard Worker securityTagTable.Subtract(tag, element);
219*598139dcSAndroid Build Coastguard Worker } else {
220*598139dcSAndroid Build Coastguard Worker tagTable.Subtract(tag, element);
221*598139dcSAndroid Build Coastguard Worker }
222*598139dcSAndroid Build Coastguard Worker }
223*598139dcSAndroid Build Coastguard Worker
224*598139dcSAndroid Build Coastguard Worker tagNameTable.Subtract(TagNameKey(element), element);
225*598139dcSAndroid Build Coastguard Worker }
226*598139dcSAndroid Build Coastguard Worker
UidToName(uid_t uid) const227*598139dcSAndroid Build Coastguard Worker const char* LogStatistics::UidToName(uid_t uid) const {
228*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
229*598139dcSAndroid Build Coastguard Worker return UidToNameLocked(uid);
230*598139dcSAndroid Build Coastguard Worker }
231*598139dcSAndroid Build Coastguard Worker
232*598139dcSAndroid Build Coastguard Worker // caller must own and free character string
UidToNameLocked(uid_t uid) const233*598139dcSAndroid Build Coastguard Worker const char* LogStatistics::UidToNameLocked(uid_t uid) const {
234*598139dcSAndroid Build Coastguard Worker // Local hard coded favourites
235*598139dcSAndroid Build Coastguard Worker if (uid == AID_LOGD) {
236*598139dcSAndroid Build Coastguard Worker return strdup("auditd");
237*598139dcSAndroid Build Coastguard Worker }
238*598139dcSAndroid Build Coastguard Worker
239*598139dcSAndroid Build Coastguard Worker // Android system
240*598139dcSAndroid Build Coastguard Worker if (uid < AID_APP) {
241*598139dcSAndroid Build Coastguard Worker // in bionic, thread safe as long as we copy the results
242*598139dcSAndroid Build Coastguard Worker struct passwd* pwd = getpwuid(uid);
243*598139dcSAndroid Build Coastguard Worker if (pwd) {
244*598139dcSAndroid Build Coastguard Worker return strdup(pwd->pw_name);
245*598139dcSAndroid Build Coastguard Worker }
246*598139dcSAndroid Build Coastguard Worker }
247*598139dcSAndroid Build Coastguard Worker
248*598139dcSAndroid Build Coastguard Worker // Parse /data/system/packages.list
249*598139dcSAndroid Build Coastguard Worker uid_t userId = uid % AID_USER_OFFSET;
250*598139dcSAndroid Build Coastguard Worker const char* name = android::uidToName(userId);
251*598139dcSAndroid Build Coastguard Worker if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
252*598139dcSAndroid Build Coastguard Worker name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
253*598139dcSAndroid Build Coastguard Worker }
254*598139dcSAndroid Build Coastguard Worker if (name) {
255*598139dcSAndroid Build Coastguard Worker return name;
256*598139dcSAndroid Build Coastguard Worker }
257*598139dcSAndroid Build Coastguard Worker
258*598139dcSAndroid Build Coastguard Worker // Android application
259*598139dcSAndroid Build Coastguard Worker if (uid >= AID_APP) {
260*598139dcSAndroid Build Coastguard Worker struct passwd* pwd = getpwuid(uid);
261*598139dcSAndroid Build Coastguard Worker if (pwd) {
262*598139dcSAndroid Build Coastguard Worker return strdup(pwd->pw_name);
263*598139dcSAndroid Build Coastguard Worker }
264*598139dcSAndroid Build Coastguard Worker }
265*598139dcSAndroid Build Coastguard Worker
266*598139dcSAndroid Build Coastguard Worker // report uid -> pid(s) -> pidToName if unique
267*598139dcSAndroid Build Coastguard Worker for (pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end();
268*598139dcSAndroid Build Coastguard Worker ++it) {
269*598139dcSAndroid Build Coastguard Worker const PidEntry& entry = it->second;
270*598139dcSAndroid Build Coastguard Worker
271*598139dcSAndroid Build Coastguard Worker if (entry.uid() == uid) {
272*598139dcSAndroid Build Coastguard Worker const char* nameTmp = entry.name();
273*598139dcSAndroid Build Coastguard Worker
274*598139dcSAndroid Build Coastguard Worker if (nameTmp) {
275*598139dcSAndroid Build Coastguard Worker if (!name) {
276*598139dcSAndroid Build Coastguard Worker name = strdup(nameTmp);
277*598139dcSAndroid Build Coastguard Worker } else if (fastcmp<strcmp>(name, nameTmp)) {
278*598139dcSAndroid Build Coastguard Worker free(const_cast<char*>(name));
279*598139dcSAndroid Build Coastguard Worker name = nullptr;
280*598139dcSAndroid Build Coastguard Worker break;
281*598139dcSAndroid Build Coastguard Worker }
282*598139dcSAndroid Build Coastguard Worker }
283*598139dcSAndroid Build Coastguard Worker }
284*598139dcSAndroid Build Coastguard Worker }
285*598139dcSAndroid Build Coastguard Worker
286*598139dcSAndroid Build Coastguard Worker // No one
287*598139dcSAndroid Build Coastguard Worker return name;
288*598139dcSAndroid Build Coastguard Worker }
289*598139dcSAndroid Build Coastguard Worker
290*598139dcSAndroid Build Coastguard Worker // Prune at most 10% of the log entries or maxPrune, whichever is less.
ShouldPrune(log_id id,unsigned long max_size,unsigned long * prune_rows) const291*598139dcSAndroid Build Coastguard Worker bool LogStatistics::ShouldPrune(log_id id, unsigned long max_size,
292*598139dcSAndroid Build Coastguard Worker unsigned long* prune_rows) const {
293*598139dcSAndroid Build Coastguard Worker static constexpr size_t kMinPrune = 4;
294*598139dcSAndroid Build Coastguard Worker static constexpr size_t kMaxPrune = 256;
295*598139dcSAndroid Build Coastguard Worker
296*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
297*598139dcSAndroid Build Coastguard Worker size_t sizes = mSizes[id];
298*598139dcSAndroid Build Coastguard Worker if (sizes <= max_size) {
299*598139dcSAndroid Build Coastguard Worker return false;
300*598139dcSAndroid Build Coastguard Worker }
301*598139dcSAndroid Build Coastguard Worker size_t size_over = sizes - ((max_size * 9) / 10);
302*598139dcSAndroid Build Coastguard Worker size_t elements = mElements[id];
303*598139dcSAndroid Build Coastguard Worker size_t min_elements = elements / 100;
304*598139dcSAndroid Build Coastguard Worker if (min_elements < kMinPrune) {
305*598139dcSAndroid Build Coastguard Worker min_elements = kMinPrune;
306*598139dcSAndroid Build Coastguard Worker }
307*598139dcSAndroid Build Coastguard Worker *prune_rows = elements * size_over / sizes;
308*598139dcSAndroid Build Coastguard Worker if (*prune_rows < min_elements) {
309*598139dcSAndroid Build Coastguard Worker *prune_rows = min_elements;
310*598139dcSAndroid Build Coastguard Worker }
311*598139dcSAndroid Build Coastguard Worker if (*prune_rows > kMaxPrune) {
312*598139dcSAndroid Build Coastguard Worker *prune_rows = kMaxPrune;
313*598139dcSAndroid Build Coastguard Worker }
314*598139dcSAndroid Build Coastguard Worker
315*598139dcSAndroid Build Coastguard Worker return true;
316*598139dcSAndroid Build Coastguard Worker }
317*598139dcSAndroid Build Coastguard Worker
formatHeader(const std::string & name,log_id_t id) const318*598139dcSAndroid Build Coastguard Worker std::string UidEntry::formatHeader(const std::string& name, log_id_t id) const {
319*598139dcSAndroid Build Coastguard Worker bool isprune = worstUidEnabledForLogid(id);
320*598139dcSAndroid Build Coastguard Worker return formatLine(android::base::StringPrintf(name.c_str(),
321*598139dcSAndroid Build Coastguard Worker android_log_id_to_name(id)),
322*598139dcSAndroid Build Coastguard Worker std::string("Size"),
323*598139dcSAndroid Build Coastguard Worker std::string(isprune ? "+/- Pruned" : "")) +
324*598139dcSAndroid Build Coastguard Worker formatLine(std::string("UID PACKAGE"), std::string("BYTES"),
325*598139dcSAndroid Build Coastguard Worker std::string(isprune ? "NUM" : ""));
326*598139dcSAndroid Build Coastguard Worker }
327*598139dcSAndroid Build Coastguard Worker
328*598139dcSAndroid Build Coastguard Worker // Helper to truncate name, if too long, and add name dressings
FormatTmp(const char * nameTmp,uid_t uid,std::string & name,std::string & size,size_t nameLen) const329*598139dcSAndroid Build Coastguard Worker void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name, std::string& size,
330*598139dcSAndroid Build Coastguard Worker size_t nameLen) const {
331*598139dcSAndroid Build Coastguard Worker const char* allocNameTmp = nullptr;
332*598139dcSAndroid Build Coastguard Worker if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid);
333*598139dcSAndroid Build Coastguard Worker if (nameTmp) {
334*598139dcSAndroid Build Coastguard Worker size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
335*598139dcSAndroid Build Coastguard Worker size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
336*598139dcSAndroid Build Coastguard Worker lenSpace - 2;
337*598139dcSAndroid Build Coastguard Worker size_t lenNameTmp = strlen(nameTmp);
338*598139dcSAndroid Build Coastguard Worker while ((len < lenNameTmp) && (lenSpace > 1)) {
339*598139dcSAndroid Build Coastguard Worker ++len;
340*598139dcSAndroid Build Coastguard Worker --lenSpace;
341*598139dcSAndroid Build Coastguard Worker }
342*598139dcSAndroid Build Coastguard Worker name += android::base::StringPrintf("%*s", (int)lenSpace, "");
343*598139dcSAndroid Build Coastguard Worker if (len < lenNameTmp) {
344*598139dcSAndroid Build Coastguard Worker name += "...";
345*598139dcSAndroid Build Coastguard Worker nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
346*598139dcSAndroid Build Coastguard Worker }
347*598139dcSAndroid Build Coastguard Worker name += nameTmp;
348*598139dcSAndroid Build Coastguard Worker free(const_cast<char*>(allocNameTmp));
349*598139dcSAndroid Build Coastguard Worker }
350*598139dcSAndroid Build Coastguard Worker }
351*598139dcSAndroid Build Coastguard Worker
format(const LogStatistics & stat,log_id_t id,uid_t uid) const352*598139dcSAndroid Build Coastguard Worker std::string UidEntry::format(const LogStatistics& stat, log_id_t id, uid_t uid) const
353*598139dcSAndroid Build Coastguard Worker REQUIRES(stat.lock_) {
354*598139dcSAndroid Build Coastguard Worker std::string name = android::base::StringPrintf("%u", uid);
355*598139dcSAndroid Build Coastguard Worker std::string size = android::base::StringPrintf("%zu", getSizes());
356*598139dcSAndroid Build Coastguard Worker
357*598139dcSAndroid Build Coastguard Worker stat.FormatTmp(nullptr, uid, name, size, 6);
358*598139dcSAndroid Build Coastguard Worker
359*598139dcSAndroid Build Coastguard Worker std::string pruned = "";
360*598139dcSAndroid Build Coastguard Worker std::string output = formatLine(name, size, pruned);
361*598139dcSAndroid Build Coastguard Worker
362*598139dcSAndroid Build Coastguard Worker if (uid != AID_SYSTEM) {
363*598139dcSAndroid Build Coastguard Worker return output;
364*598139dcSAndroid Build Coastguard Worker }
365*598139dcSAndroid Build Coastguard Worker
366*598139dcSAndroid Build Coastguard Worker static const size_t maximum_sorted_entries = 32;
367*598139dcSAndroid Build Coastguard Worker std::array<const pid_t*, maximum_sorted_entries> sorted_pids;
368*598139dcSAndroid Build Coastguard Worker std::array<const PidEntry*, maximum_sorted_entries> sorted_entries;
369*598139dcSAndroid Build Coastguard Worker stat.pidSystemTable[id].MaxEntries(uid, 0, sorted_pids, sorted_entries);
370*598139dcSAndroid Build Coastguard Worker
371*598139dcSAndroid Build Coastguard Worker std::string byPid;
372*598139dcSAndroid Build Coastguard Worker size_t index;
373*598139dcSAndroid Build Coastguard Worker for (index = 0; index < maximum_sorted_entries; ++index) {
374*598139dcSAndroid Build Coastguard Worker const PidEntry* entry = sorted_entries[index];
375*598139dcSAndroid Build Coastguard Worker if (!entry) {
376*598139dcSAndroid Build Coastguard Worker break;
377*598139dcSAndroid Build Coastguard Worker }
378*598139dcSAndroid Build Coastguard Worker if (entry->getSizes() <= (getSizes() / 100)) {
379*598139dcSAndroid Build Coastguard Worker break;
380*598139dcSAndroid Build Coastguard Worker }
381*598139dcSAndroid Build Coastguard Worker byPid += entry->format(stat, id, *sorted_pids[index]);
382*598139dcSAndroid Build Coastguard Worker }
383*598139dcSAndroid Build Coastguard Worker if (index > 1) { // print this only if interesting
384*598139dcSAndroid Build Coastguard Worker std::string ditto("\" ");
385*598139dcSAndroid Build Coastguard Worker output += formatLine(std::string(" PID/UID COMMAND LINE"), ditto, std::string(""));
386*598139dcSAndroid Build Coastguard Worker output += byPid;
387*598139dcSAndroid Build Coastguard Worker }
388*598139dcSAndroid Build Coastguard Worker
389*598139dcSAndroid Build Coastguard Worker return output;
390*598139dcSAndroid Build Coastguard Worker }
391*598139dcSAndroid Build Coastguard Worker
formatHeader(const std::string & name,log_id_t) const392*598139dcSAndroid Build Coastguard Worker std::string PidEntry::formatHeader(const std::string& name,
393*598139dcSAndroid Build Coastguard Worker log_id_t /* id */) const {
394*598139dcSAndroid Build Coastguard Worker return formatLine(name, std::string("Size"), std::string("Pruned")) +
395*598139dcSAndroid Build Coastguard Worker formatLine(std::string(" PID/UID COMMAND LINE"),
396*598139dcSAndroid Build Coastguard Worker std::string("BYTES"), std::string("NUM"));
397*598139dcSAndroid Build Coastguard Worker }
398*598139dcSAndroid Build Coastguard Worker
format(const LogStatistics & stat,log_id_t,pid_t pid) const399*598139dcSAndroid Build Coastguard Worker std::string PidEntry::format(const LogStatistics& stat, log_id_t, pid_t pid) const
400*598139dcSAndroid Build Coastguard Worker REQUIRES(stat.lock_) {
401*598139dcSAndroid Build Coastguard Worker std::string name = android::base::StringPrintf("%5u/%u", pid, uid_);
402*598139dcSAndroid Build Coastguard Worker std::string size = android::base::StringPrintf("%zu", getSizes());
403*598139dcSAndroid Build Coastguard Worker
404*598139dcSAndroid Build Coastguard Worker stat.FormatTmp(name_, uid_, name, size, 12);
405*598139dcSAndroid Build Coastguard Worker
406*598139dcSAndroid Build Coastguard Worker std::string pruned = "";
407*598139dcSAndroid Build Coastguard Worker return formatLine(name, size, pruned);
408*598139dcSAndroid Build Coastguard Worker }
409*598139dcSAndroid Build Coastguard Worker
formatHeader(const std::string & name,log_id_t) const410*598139dcSAndroid Build Coastguard Worker std::string TidEntry::formatHeader(const std::string& name,
411*598139dcSAndroid Build Coastguard Worker log_id_t /* id */) const {
412*598139dcSAndroid Build Coastguard Worker return formatLine(name, std::string("Size"), std::string("Pruned")) +
413*598139dcSAndroid Build Coastguard Worker formatLine(std::string(" TID/UID COMM"), std::string("BYTES"),
414*598139dcSAndroid Build Coastguard Worker std::string("NUM"));
415*598139dcSAndroid Build Coastguard Worker }
416*598139dcSAndroid Build Coastguard Worker
format(const LogStatistics & stat,log_id_t,pid_t tid) const417*598139dcSAndroid Build Coastguard Worker std::string TidEntry::format(const LogStatistics& stat, log_id_t, pid_t tid) const
418*598139dcSAndroid Build Coastguard Worker REQUIRES(stat.lock_) {
419*598139dcSAndroid Build Coastguard Worker std::string name = android::base::StringPrintf("%5u/%u", tid, uid_);
420*598139dcSAndroid Build Coastguard Worker std::string size = android::base::StringPrintf("%zu", getSizes());
421*598139dcSAndroid Build Coastguard Worker
422*598139dcSAndroid Build Coastguard Worker stat.FormatTmp(name_, uid_, name, size, 12);
423*598139dcSAndroid Build Coastguard Worker
424*598139dcSAndroid Build Coastguard Worker std::string pruned = "";
425*598139dcSAndroid Build Coastguard Worker return formatLine(name, size, pruned);
426*598139dcSAndroid Build Coastguard Worker }
427*598139dcSAndroid Build Coastguard Worker
formatHeader(const std::string & name,log_id_t id) const428*598139dcSAndroid Build Coastguard Worker std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const {
429*598139dcSAndroid Build Coastguard Worker bool isprune = worstUidEnabledForLogid(id);
430*598139dcSAndroid Build Coastguard Worker return formatLine(name, std::string("Size"),
431*598139dcSAndroid Build Coastguard Worker std::string(isprune ? "Prune" : "")) +
432*598139dcSAndroid Build Coastguard Worker formatLine(std::string(" TAG/UID TAGNAME"),
433*598139dcSAndroid Build Coastguard Worker std::string("BYTES"), std::string(isprune ? "NUM" : ""));
434*598139dcSAndroid Build Coastguard Worker }
435*598139dcSAndroid Build Coastguard Worker
format(const LogStatistics &,log_id_t,uint32_t) const436*598139dcSAndroid Build Coastguard Worker std::string TagEntry::format(const LogStatistics&, log_id_t, uint32_t) const {
437*598139dcSAndroid Build Coastguard Worker std::string name;
438*598139dcSAndroid Build Coastguard Worker if (uid_ == (uid_t)-1) {
439*598139dcSAndroid Build Coastguard Worker name = android::base::StringPrintf("%7u", key());
440*598139dcSAndroid Build Coastguard Worker } else {
441*598139dcSAndroid Build Coastguard Worker name = android::base::StringPrintf("%7u/%u", key(), uid_);
442*598139dcSAndroid Build Coastguard Worker }
443*598139dcSAndroid Build Coastguard Worker const char* nameTmp = this->name();
444*598139dcSAndroid Build Coastguard Worker if (nameTmp) {
445*598139dcSAndroid Build Coastguard Worker name += android::base::StringPrintf(
446*598139dcSAndroid Build Coastguard Worker "%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
447*598139dcSAndroid Build Coastguard Worker }
448*598139dcSAndroid Build Coastguard Worker
449*598139dcSAndroid Build Coastguard Worker std::string size = android::base::StringPrintf("%zu", getSizes());
450*598139dcSAndroid Build Coastguard Worker
451*598139dcSAndroid Build Coastguard Worker std::string pruned = "";
452*598139dcSAndroid Build Coastguard Worker return formatLine(name, size, pruned);
453*598139dcSAndroid Build Coastguard Worker }
454*598139dcSAndroid Build Coastguard Worker
formatHeader(const std::string & name,log_id_t) const455*598139dcSAndroid Build Coastguard Worker std::string TagNameEntry::formatHeader(const std::string& name,
456*598139dcSAndroid Build Coastguard Worker log_id_t /* id */) const {
457*598139dcSAndroid Build Coastguard Worker return formatLine(name, std::string("Size"), std::string("")) +
458*598139dcSAndroid Build Coastguard Worker formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
459*598139dcSAndroid Build Coastguard Worker std::string("BYTES"), std::string(""));
460*598139dcSAndroid Build Coastguard Worker }
461*598139dcSAndroid Build Coastguard Worker
format(const LogStatistics &,log_id_t,const std::string & key_name) const462*598139dcSAndroid Build Coastguard Worker std::string TagNameEntry::format(const LogStatistics&, log_id_t,
463*598139dcSAndroid Build Coastguard Worker const std::string& key_name) const {
464*598139dcSAndroid Build Coastguard Worker std::string name;
465*598139dcSAndroid Build Coastguard Worker std::string pidstr;
466*598139dcSAndroid Build Coastguard Worker if (pid_ != (pid_t)-1) {
467*598139dcSAndroid Build Coastguard Worker pidstr = android::base::StringPrintf("%u", pid_);
468*598139dcSAndroid Build Coastguard Worker if (tid_ != (pid_t)-1 && tid_ != pid_) pidstr = "/" + pidstr;
469*598139dcSAndroid Build Coastguard Worker }
470*598139dcSAndroid Build Coastguard Worker int len = 9 - pidstr.length();
471*598139dcSAndroid Build Coastguard Worker if (len < 0) len = 0;
472*598139dcSAndroid Build Coastguard Worker if (tid_ == (pid_t)-1 || tid_ == pid_) {
473*598139dcSAndroid Build Coastguard Worker name = android::base::StringPrintf("%*s", len, "");
474*598139dcSAndroid Build Coastguard Worker } else {
475*598139dcSAndroid Build Coastguard Worker name = android::base::StringPrintf("%*u", len, tid_);
476*598139dcSAndroid Build Coastguard Worker }
477*598139dcSAndroid Build Coastguard Worker name += pidstr;
478*598139dcSAndroid Build Coastguard Worker if (uid_ != (uid_t)-1) {
479*598139dcSAndroid Build Coastguard Worker name += android::base::StringPrintf("/%u", uid_);
480*598139dcSAndroid Build Coastguard Worker }
481*598139dcSAndroid Build Coastguard Worker
482*598139dcSAndroid Build Coastguard Worker std::string size = android::base::StringPrintf("%zu", getSizes());
483*598139dcSAndroid Build Coastguard Worker
484*598139dcSAndroid Build Coastguard Worker const char* nameTmp = key_name.data();
485*598139dcSAndroid Build Coastguard Worker if (nameTmp) {
486*598139dcSAndroid Build Coastguard Worker size_t lenSpace = std::max(16 - name.length(), (size_t)1);
487*598139dcSAndroid Build Coastguard Worker size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
488*598139dcSAndroid Build Coastguard Worker lenSpace - 2;
489*598139dcSAndroid Build Coastguard Worker size_t lenNameTmp = strlen(nameTmp);
490*598139dcSAndroid Build Coastguard Worker while ((len < lenNameTmp) && (lenSpace > 1)) {
491*598139dcSAndroid Build Coastguard Worker ++len;
492*598139dcSAndroid Build Coastguard Worker --lenSpace;
493*598139dcSAndroid Build Coastguard Worker }
494*598139dcSAndroid Build Coastguard Worker name += android::base::StringPrintf("%*s", (int)lenSpace, "");
495*598139dcSAndroid Build Coastguard Worker if (len < lenNameTmp) {
496*598139dcSAndroid Build Coastguard Worker name += "...";
497*598139dcSAndroid Build Coastguard Worker nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
498*598139dcSAndroid Build Coastguard Worker }
499*598139dcSAndroid Build Coastguard Worker name += nameTmp;
500*598139dcSAndroid Build Coastguard Worker }
501*598139dcSAndroid Build Coastguard Worker
502*598139dcSAndroid Build Coastguard Worker std::string pruned = "";
503*598139dcSAndroid Build Coastguard Worker
504*598139dcSAndroid Build Coastguard Worker return formatLine(name, size, pruned);
505*598139dcSAndroid Build Coastguard Worker }
506*598139dcSAndroid Build Coastguard Worker
formatMsec(uint64_t val)507*598139dcSAndroid Build Coastguard Worker static std::string formatMsec(uint64_t val) {
508*598139dcSAndroid Build Coastguard Worker static const unsigned subsecDigits = 3;
509*598139dcSAndroid Build Coastguard Worker static const uint64_t sec = MS_PER_SEC;
510*598139dcSAndroid Build Coastguard Worker
511*598139dcSAndroid Build Coastguard Worker static const uint64_t minute = 60 * sec;
512*598139dcSAndroid Build Coastguard Worker static const uint64_t hour = 60 * minute;
513*598139dcSAndroid Build Coastguard Worker static const uint64_t day = 24 * hour;
514*598139dcSAndroid Build Coastguard Worker
515*598139dcSAndroid Build Coastguard Worker std::string output;
516*598139dcSAndroid Build Coastguard Worker if (val < sec) return output;
517*598139dcSAndroid Build Coastguard Worker
518*598139dcSAndroid Build Coastguard Worker if (val >= day) {
519*598139dcSAndroid Build Coastguard Worker output = android::base::StringPrintf("%" PRIu64 "d ", val / day);
520*598139dcSAndroid Build Coastguard Worker val = (val % day) + day;
521*598139dcSAndroid Build Coastguard Worker }
522*598139dcSAndroid Build Coastguard Worker if (val >= minute) {
523*598139dcSAndroid Build Coastguard Worker if (val >= hour) {
524*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%" PRIu64 ":",
525*598139dcSAndroid Build Coastguard Worker (val / hour) % (day / hour));
526*598139dcSAndroid Build Coastguard Worker }
527*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf(
528*598139dcSAndroid Build Coastguard Worker (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
529*598139dcSAndroid Build Coastguard Worker (val / minute) % (hour / minute));
530*598139dcSAndroid Build Coastguard Worker }
531*598139dcSAndroid Build Coastguard Worker output +=
532*598139dcSAndroid Build Coastguard Worker android::base::StringPrintf((val >= minute) ? "%02" PRIu64 : "%" PRIu64,
533*598139dcSAndroid Build Coastguard Worker (val / sec) % (minute / sec));
534*598139dcSAndroid Build Coastguard Worker val %= sec;
535*598139dcSAndroid Build Coastguard Worker unsigned digits = subsecDigits;
536*598139dcSAndroid Build Coastguard Worker while (digits && ((val % 10) == 0)) {
537*598139dcSAndroid Build Coastguard Worker val /= 10;
538*598139dcSAndroid Build Coastguard Worker --digits;
539*598139dcSAndroid Build Coastguard Worker }
540*598139dcSAndroid Build Coastguard Worker if (digits) {
541*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf(".%0*" PRIu64, digits, val);
542*598139dcSAndroid Build Coastguard Worker }
543*598139dcSAndroid Build Coastguard Worker return output;
544*598139dcSAndroid Build Coastguard Worker }
545*598139dcSAndroid Build Coastguard Worker
546*598139dcSAndroid Build Coastguard Worker template <typename TKey, typename TEntry>
FormatTable(const LogHashtable<TKey,TEntry> & table,uid_t uid,pid_t pid,const std::string & name,log_id_t id) const547*598139dcSAndroid Build Coastguard Worker std::string LogStatistics::FormatTable(const LogHashtable<TKey, TEntry>& table, uid_t uid,
548*598139dcSAndroid Build Coastguard Worker pid_t pid, const std::string& name, log_id_t id) const
549*598139dcSAndroid Build Coastguard Worker REQUIRES(lock_) {
550*598139dcSAndroid Build Coastguard Worker static const size_t maximum_sorted_entries = 32;
551*598139dcSAndroid Build Coastguard Worker std::string output;
552*598139dcSAndroid Build Coastguard Worker std::array<const TKey*, maximum_sorted_entries> sorted_keys;
553*598139dcSAndroid Build Coastguard Worker std::array<const TEntry*, maximum_sorted_entries> sorted_entries;
554*598139dcSAndroid Build Coastguard Worker table.MaxEntries(uid, pid, sorted_keys, sorted_entries);
555*598139dcSAndroid Build Coastguard Worker bool header_printed = false;
556*598139dcSAndroid Build Coastguard Worker for (size_t index = 0; index < maximum_sorted_entries; ++index) {
557*598139dcSAndroid Build Coastguard Worker const TEntry* entry = sorted_entries[index];
558*598139dcSAndroid Build Coastguard Worker if (!entry) {
559*598139dcSAndroid Build Coastguard Worker break;
560*598139dcSAndroid Build Coastguard Worker }
561*598139dcSAndroid Build Coastguard Worker if (entry->getSizes() <= (sorted_entries[0]->getSizes() / 100)) {
562*598139dcSAndroid Build Coastguard Worker break;
563*598139dcSAndroid Build Coastguard Worker }
564*598139dcSAndroid Build Coastguard Worker if (!header_printed) {
565*598139dcSAndroid Build Coastguard Worker output += "\n\n";
566*598139dcSAndroid Build Coastguard Worker output += entry->formatHeader(name, id);
567*598139dcSAndroid Build Coastguard Worker header_printed = true;
568*598139dcSAndroid Build Coastguard Worker }
569*598139dcSAndroid Build Coastguard Worker output += entry->format(*this, id, *sorted_keys[index]);
570*598139dcSAndroid Build Coastguard Worker }
571*598139dcSAndroid Build Coastguard Worker return output;
572*598139dcSAndroid Build Coastguard Worker }
573*598139dcSAndroid Build Coastguard Worker
ReportInteresting() const574*598139dcSAndroid Build Coastguard Worker std::string LogStatistics::ReportInteresting() const {
575*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
576*598139dcSAndroid Build Coastguard Worker
577*598139dcSAndroid Build Coastguard Worker std::vector<std::string> items;
578*598139dcSAndroid Build Coastguard Worker
579*598139dcSAndroid Build Coastguard Worker log_id_for_each(i) { items.emplace_back(std::to_string(mElements[i])); }
580*598139dcSAndroid Build Coastguard Worker
581*598139dcSAndroid Build Coastguard Worker log_id_for_each(i) { items.emplace_back(std::to_string(mSizes[i])); }
582*598139dcSAndroid Build Coastguard Worker
583*598139dcSAndroid Build Coastguard Worker log_id_for_each(i) {
584*598139dcSAndroid Build Coastguard Worker items.emplace_back(std::to_string(overhead_[i] ? *overhead_[i] : mSizes[i]));
585*598139dcSAndroid Build Coastguard Worker }
586*598139dcSAndroid Build Coastguard Worker
587*598139dcSAndroid Build Coastguard Worker log_id_for_each(i) {
588*598139dcSAndroid Build Coastguard Worker uint64_t oldest = mOldest[i].msec() / 1000;
589*598139dcSAndroid Build Coastguard Worker uint64_t newest = mNewest[i].msec() / 1000;
590*598139dcSAndroid Build Coastguard Worker
591*598139dcSAndroid Build Coastguard Worker int span = newest - oldest;
592*598139dcSAndroid Build Coastguard Worker
593*598139dcSAndroid Build Coastguard Worker items.emplace_back(std::to_string(span));
594*598139dcSAndroid Build Coastguard Worker }
595*598139dcSAndroid Build Coastguard Worker
596*598139dcSAndroid Build Coastguard Worker return android::base::Join(items, ",");
597*598139dcSAndroid Build Coastguard Worker }
598*598139dcSAndroid Build Coastguard Worker
Format(uid_t uid,pid_t pid,unsigned int logMask) const599*598139dcSAndroid Build Coastguard Worker std::string LogStatistics::Format(uid_t uid, pid_t pid, unsigned int logMask) const {
600*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
601*598139dcSAndroid Build Coastguard Worker
602*598139dcSAndroid Build Coastguard Worker static const uint16_t spaces_total = 19;
603*598139dcSAndroid Build Coastguard Worker
604*598139dcSAndroid Build Coastguard Worker // Report on total logging, current and for all time
605*598139dcSAndroid Build Coastguard Worker
606*598139dcSAndroid Build Coastguard Worker std::string output = "size/num";
607*598139dcSAndroid Build Coastguard Worker size_t oldLength;
608*598139dcSAndroid Build Coastguard Worker int16_t spaces = 1;
609*598139dcSAndroid Build Coastguard Worker
610*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
611*598139dcSAndroid Build Coastguard Worker if (!(logMask & (1 << id))) continue;
612*598139dcSAndroid Build Coastguard Worker oldLength = output.length();
613*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
614*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%s", spaces, "",
615*598139dcSAndroid Build Coastguard Worker android_log_id_to_name(id));
616*598139dcSAndroid Build Coastguard Worker spaces += spaces_total + oldLength - output.length();
617*598139dcSAndroid Build Coastguard Worker }
618*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
619*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*sTotal", spaces, "");
620*598139dcSAndroid Build Coastguard Worker
621*598139dcSAndroid Build Coastguard Worker static const char TotalStr[] = "\nTotal";
622*598139dcSAndroid Build Coastguard Worker spaces = 10 - strlen(TotalStr);
623*598139dcSAndroid Build Coastguard Worker output += TotalStr;
624*598139dcSAndroid Build Coastguard Worker
625*598139dcSAndroid Build Coastguard Worker size_t totalSize = 0;
626*598139dcSAndroid Build Coastguard Worker size_t totalEls = 0;
627*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
628*598139dcSAndroid Build Coastguard Worker if (!(logMask & (1 << id))) continue;
629*598139dcSAndroid Build Coastguard Worker oldLength = output.length();
630*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
631*598139dcSAndroid Build Coastguard Worker size_t szs = mSizesTotal[id];
632*598139dcSAndroid Build Coastguard Worker totalSize += szs;
633*598139dcSAndroid Build Coastguard Worker size_t els = mElementsTotal[id];
634*598139dcSAndroid Build Coastguard Worker totalEls += els;
635*598139dcSAndroid Build Coastguard Worker output +=
636*598139dcSAndroid Build Coastguard Worker android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
637*598139dcSAndroid Build Coastguard Worker spaces += spaces_total + oldLength - output.length();
638*598139dcSAndroid Build Coastguard Worker }
639*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
640*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
641*598139dcSAndroid Build Coastguard Worker totalEls);
642*598139dcSAndroid Build Coastguard Worker
643*598139dcSAndroid Build Coastguard Worker static const char NowStr[] = "\nNow";
644*598139dcSAndroid Build Coastguard Worker spaces = 10 - strlen(NowStr);
645*598139dcSAndroid Build Coastguard Worker output += NowStr;
646*598139dcSAndroid Build Coastguard Worker
647*598139dcSAndroid Build Coastguard Worker totalSize = 0;
648*598139dcSAndroid Build Coastguard Worker totalEls = 0;
649*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
650*598139dcSAndroid Build Coastguard Worker if (!(logMask & (1 << id))) continue;
651*598139dcSAndroid Build Coastguard Worker
652*598139dcSAndroid Build Coastguard Worker size_t els = mElements[id];
653*598139dcSAndroid Build Coastguard Worker oldLength = output.length();
654*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
655*598139dcSAndroid Build Coastguard Worker size_t szs = mSizes[id];
656*598139dcSAndroid Build Coastguard Worker totalSize += szs;
657*598139dcSAndroid Build Coastguard Worker totalEls += els;
658*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
659*598139dcSAndroid Build Coastguard Worker spaces -= output.length() - oldLength;
660*598139dcSAndroid Build Coastguard Worker spaces += spaces_total;
661*598139dcSAndroid Build Coastguard Worker }
662*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
663*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize,
664*598139dcSAndroid Build Coastguard Worker totalEls);
665*598139dcSAndroid Build Coastguard Worker
666*598139dcSAndroid Build Coastguard Worker static const char SpanStr[] = "\nLogspan";
667*598139dcSAndroid Build Coastguard Worker spaces = 10 - strlen(SpanStr);
668*598139dcSAndroid Build Coastguard Worker output += SpanStr;
669*598139dcSAndroid Build Coastguard Worker
670*598139dcSAndroid Build Coastguard Worker // Total reports the greater of the individual maximum time span, or the
671*598139dcSAndroid Build Coastguard Worker // validated minimum start and maximum end time span if it makes sense.
672*598139dcSAndroid Build Coastguard Worker uint64_t minTime = UINT64_MAX;
673*598139dcSAndroid Build Coastguard Worker uint64_t maxTime = 0;
674*598139dcSAndroid Build Coastguard Worker uint64_t maxSpan = 0;
675*598139dcSAndroid Build Coastguard Worker totalSize = 0;
676*598139dcSAndroid Build Coastguard Worker
677*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
678*598139dcSAndroid Build Coastguard Worker if (!(logMask & (1 << id))) continue;
679*598139dcSAndroid Build Coastguard Worker
680*598139dcSAndroid Build Coastguard Worker // validity checking
681*598139dcSAndroid Build Coastguard Worker uint64_t oldest = mOldest[id].msec();
682*598139dcSAndroid Build Coastguard Worker uint64_t newest = mNewest[id].msec();
683*598139dcSAndroid Build Coastguard Worker if (newest <= oldest) {
684*598139dcSAndroid Build Coastguard Worker spaces += spaces_total;
685*598139dcSAndroid Build Coastguard Worker continue;
686*598139dcSAndroid Build Coastguard Worker }
687*598139dcSAndroid Build Coastguard Worker
688*598139dcSAndroid Build Coastguard Worker uint64_t span = newest - oldest;
689*598139dcSAndroid Build Coastguard Worker if (span > (monthSec * MS_PER_SEC)) {
690*598139dcSAndroid Build Coastguard Worker spaces += spaces_total;
691*598139dcSAndroid Build Coastguard Worker continue;
692*598139dcSAndroid Build Coastguard Worker }
693*598139dcSAndroid Build Coastguard Worker
694*598139dcSAndroid Build Coastguard Worker // total span
695*598139dcSAndroid Build Coastguard Worker if (minTime > oldest) minTime = oldest;
696*598139dcSAndroid Build Coastguard Worker if (maxTime < newest) maxTime = newest;
697*598139dcSAndroid Build Coastguard Worker if (span > maxSpan) maxSpan = span;
698*598139dcSAndroid Build Coastguard Worker totalSize += span;
699*598139dcSAndroid Build Coastguard Worker
700*598139dcSAndroid Build Coastguard Worker oldLength = output.length();
701*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%s", spaces, "", formatMsec(span).c_str());
702*598139dcSAndroid Build Coastguard Worker spaces -= output.length() - oldLength;
703*598139dcSAndroid Build Coastguard Worker spaces += spaces_total;
704*598139dcSAndroid Build Coastguard Worker }
705*598139dcSAndroid Build Coastguard Worker if ((maxTime > minTime) && ((maxTime -= minTime) < totalSize) &&
706*598139dcSAndroid Build Coastguard Worker (maxTime > maxSpan)) {
707*598139dcSAndroid Build Coastguard Worker maxSpan = maxTime;
708*598139dcSAndroid Build Coastguard Worker }
709*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
710*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%s", spaces, "",
711*598139dcSAndroid Build Coastguard Worker formatMsec(maxSpan).c_str());
712*598139dcSAndroid Build Coastguard Worker
713*598139dcSAndroid Build Coastguard Worker static const char OverheadStr[] = "\nOverhead";
714*598139dcSAndroid Build Coastguard Worker spaces = 10 - strlen(OverheadStr);
715*598139dcSAndroid Build Coastguard Worker output += OverheadStr;
716*598139dcSAndroid Build Coastguard Worker
717*598139dcSAndroid Build Coastguard Worker totalSize = 0;
718*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
719*598139dcSAndroid Build Coastguard Worker if (!(logMask & (1 << id))) continue;
720*598139dcSAndroid Build Coastguard Worker
721*598139dcSAndroid Build Coastguard Worker size_t els = mElements[id];
722*598139dcSAndroid Build Coastguard Worker if (els) {
723*598139dcSAndroid Build Coastguard Worker oldLength = output.length();
724*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
725*598139dcSAndroid Build Coastguard Worker size_t szs = 0;
726*598139dcSAndroid Build Coastguard Worker if (overhead_[id]) {
727*598139dcSAndroid Build Coastguard Worker szs = *overhead_[id];
728*598139dcSAndroid Build Coastguard Worker } else {
729*598139dcSAndroid Build Coastguard Worker CHECK(track_total_size_);
730*598139dcSAndroid Build Coastguard Worker szs = mSizes[id];
731*598139dcSAndroid Build Coastguard Worker }
732*598139dcSAndroid Build Coastguard Worker totalSize += szs;
733*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
734*598139dcSAndroid Build Coastguard Worker spaces -= output.length() - oldLength;
735*598139dcSAndroid Build Coastguard Worker }
736*598139dcSAndroid Build Coastguard Worker spaces += spaces_total;
737*598139dcSAndroid Build Coastguard Worker }
738*598139dcSAndroid Build Coastguard Worker totalSize += sizeOf();
739*598139dcSAndroid Build Coastguard Worker if (spaces < 0) spaces = 0;
740*598139dcSAndroid Build Coastguard Worker output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
741*598139dcSAndroid Build Coastguard Worker
742*598139dcSAndroid Build Coastguard Worker // Report on Chattiest
743*598139dcSAndroid Build Coastguard Worker
744*598139dcSAndroid Build Coastguard Worker std::string name;
745*598139dcSAndroid Build Coastguard Worker
746*598139dcSAndroid Build Coastguard Worker // Chattiest by application (UID)
747*598139dcSAndroid Build Coastguard Worker log_id_for_each(id) {
748*598139dcSAndroid Build Coastguard Worker if (!(logMask & (1 << id))) continue;
749*598139dcSAndroid Build Coastguard Worker
750*598139dcSAndroid Build Coastguard Worker name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:"
751*598139dcSAndroid Build Coastguard Worker : "Logging for your UID in %s log buffer:";
752*598139dcSAndroid Build Coastguard Worker output += FormatTable(uidTable[id], uid, pid, name, id);
753*598139dcSAndroid Build Coastguard Worker }
754*598139dcSAndroid Build Coastguard Worker
755*598139dcSAndroid Build Coastguard Worker if (enable) {
756*598139dcSAndroid Build Coastguard Worker name = ((uid == AID_ROOT) && !pid) ? "Chattiest PIDs:"
757*598139dcSAndroid Build Coastguard Worker : "Logging for this PID:";
758*598139dcSAndroid Build Coastguard Worker output += FormatTable(pidTable, uid, pid, name);
759*598139dcSAndroid Build Coastguard Worker name = "Chattiest TIDs";
760*598139dcSAndroid Build Coastguard Worker if (pid) name += android::base::StringPrintf(" for PID %d", pid);
761*598139dcSAndroid Build Coastguard Worker name += ":";
762*598139dcSAndroid Build Coastguard Worker output += FormatTable(tidTable, uid, pid, name);
763*598139dcSAndroid Build Coastguard Worker }
764*598139dcSAndroid Build Coastguard Worker
765*598139dcSAndroid Build Coastguard Worker if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
766*598139dcSAndroid Build Coastguard Worker name = "Chattiest events log buffer TAGs";
767*598139dcSAndroid Build Coastguard Worker if (pid) name += android::base::StringPrintf(" for PID %d", pid);
768*598139dcSAndroid Build Coastguard Worker name += ":";
769*598139dcSAndroid Build Coastguard Worker output += FormatTable(tagTable, uid, pid, name, LOG_ID_EVENTS);
770*598139dcSAndroid Build Coastguard Worker }
771*598139dcSAndroid Build Coastguard Worker
772*598139dcSAndroid Build Coastguard Worker if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
773*598139dcSAndroid Build Coastguard Worker name = "Chattiest security log buffer TAGs";
774*598139dcSAndroid Build Coastguard Worker if (pid) name += android::base::StringPrintf(" for PID %d", pid);
775*598139dcSAndroid Build Coastguard Worker name += ":";
776*598139dcSAndroid Build Coastguard Worker output += FormatTable(securityTagTable, uid, pid, name, LOG_ID_SECURITY);
777*598139dcSAndroid Build Coastguard Worker }
778*598139dcSAndroid Build Coastguard Worker
779*598139dcSAndroid Build Coastguard Worker if (enable) {
780*598139dcSAndroid Build Coastguard Worker name = "Chattiest TAGs";
781*598139dcSAndroid Build Coastguard Worker if (pid) name += android::base::StringPrintf(" for PID %d", pid);
782*598139dcSAndroid Build Coastguard Worker name += ":";
783*598139dcSAndroid Build Coastguard Worker output += FormatTable(tagNameTable, uid, pid, name);
784*598139dcSAndroid Build Coastguard Worker }
785*598139dcSAndroid Build Coastguard Worker
786*598139dcSAndroid Build Coastguard Worker return output;
787*598139dcSAndroid Build Coastguard Worker }
788*598139dcSAndroid Build Coastguard Worker
789*598139dcSAndroid Build Coastguard Worker namespace android {
790*598139dcSAndroid Build Coastguard Worker
pidToUid(pid_t pid)791*598139dcSAndroid Build Coastguard Worker uid_t pidToUid(pid_t pid) {
792*598139dcSAndroid Build Coastguard Worker char buffer[512];
793*598139dcSAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
794*598139dcSAndroid Build Coastguard Worker FILE* fp = fopen(buffer, "re");
795*598139dcSAndroid Build Coastguard Worker if (fp) {
796*598139dcSAndroid Build Coastguard Worker while (fgets(buffer, sizeof(buffer), fp)) {
797*598139dcSAndroid Build Coastguard Worker int uid = AID_LOGD;
798*598139dcSAndroid Build Coastguard Worker char space = 0;
799*598139dcSAndroid Build Coastguard Worker if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
800*598139dcSAndroid Build Coastguard Worker isspace(space)) {
801*598139dcSAndroid Build Coastguard Worker fclose(fp);
802*598139dcSAndroid Build Coastguard Worker return uid;
803*598139dcSAndroid Build Coastguard Worker }
804*598139dcSAndroid Build Coastguard Worker }
805*598139dcSAndroid Build Coastguard Worker fclose(fp);
806*598139dcSAndroid Build Coastguard Worker }
807*598139dcSAndroid Build Coastguard Worker return AID_LOGD; // associate this with the logger
808*598139dcSAndroid Build Coastguard Worker }
809*598139dcSAndroid Build Coastguard Worker }
810*598139dcSAndroid Build Coastguard Worker
PidToUid(pid_t pid)811*598139dcSAndroid Build Coastguard Worker uid_t LogStatistics::PidToUid(pid_t pid) {
812*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
813*598139dcSAndroid Build Coastguard Worker return pidTable.Add(pid)->second.uid();
814*598139dcSAndroid Build Coastguard Worker }
815*598139dcSAndroid Build Coastguard Worker
816*598139dcSAndroid Build Coastguard Worker // caller must free character string
PidToName(pid_t pid) const817*598139dcSAndroid Build Coastguard Worker const char* LogStatistics::PidToName(pid_t pid) const {
818*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{lock_};
819*598139dcSAndroid Build Coastguard Worker // An inconvenient truth ... getName() can alter the object
820*598139dcSAndroid Build Coastguard Worker pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
821*598139dcSAndroid Build Coastguard Worker const char* name = writablePidTable.Add(pid)->second.name();
822*598139dcSAndroid Build Coastguard Worker if (!name) {
823*598139dcSAndroid Build Coastguard Worker return nullptr;
824*598139dcSAndroid Build Coastguard Worker }
825*598139dcSAndroid Build Coastguard Worker return strdup(name);
826*598139dcSAndroid Build Coastguard Worker }
827