1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstring>
17 #include <iostream>
18 #include <queue>
19 #include <vector>
20 #include <regex>
21 #include <iomanip>
22
23 #include <securec.h>
24 #include <hilog/log.h>
25 #include <log_utils.h>
26 #include <hilog_cmd.h>
27
28 #include "log_display.h"
29
30 namespace OHOS {
31 namespace HiviewDFX {
32 using namespace std;
33 static constexpr char colCmd = ' ';
34 static constexpr int LOGTYPE_W = 8;
35 static constexpr int DOMAIN_TITLE_W = 10;
36 static constexpr int DOMAIN_W = (DOMAIN_TITLE_W - 2);
37 static constexpr int PID_W = 7;
38 static constexpr int PNAME_W = 32;
39 static constexpr int TAG_W = 32;
40 static constexpr int FREQ_W = 10;
41 static constexpr int TIME_W = 20;
42 static constexpr int TP_W = 10;
43 static constexpr int LINES_W = 10;
44 static constexpr int LENGTH_W = 10;
45 static constexpr int DROPPED_W = 10;
46 static constexpr int FLOAT_PRECSION = 2;
47 static constexpr int STATS_W = 60;
48 static constexpr int MIN2SEC = 60;
49 static constexpr int HOUR2MIN = 60;
50 static constexpr int HOUR2SEC = MIN2SEC * HOUR2MIN;
51 static constexpr int NS2MS = 1000 * 1000;
TimeStr(uint32_t tv_sec,uint32_t tv_nsec)52 static string TimeStr(uint32_t tv_sec, uint32_t tv_nsec)
53 {
54 char buffer[TIME_W] = {0};
55 int len = 0;
56 int ret = 0;
57 time_t ts = tv_sec;
58 struct tm tmLocal;
59 if (localtime_r(&ts, &tmLocal) == nullptr) {
60 return 0;
61 }
62 len += strftime(buffer, TIME_W, "%m-%d %H:%M:%S", &tmLocal);
63 ret = snprintf_s(buffer + len, TIME_W - len, TIME_W - len - 1, ".%03u", tv_nsec / NS2MS);
64 if (ret <= 0) {
65 return "ERROR";
66 }
67 return buffer;
68 }
69
PrintDomainTitle()70 static void PrintDomainTitle()
71 {
72 cout << setw(LOGTYPE_W) << "LOGTYPE" << colCmd;
73 cout << setw(DOMAIN_TITLE_W) << "DOMAIN" << colCmd;
74 }
75
PrintPidTitle()76 static void PrintPidTitle()
77 {
78 cout << setw(LOGTYPE_W) << "LOGTYPE" << colCmd;
79 cout << setw(PID_W) << "PID" << colCmd;
80 cout << setw(PNAME_W) << "NAME" << colCmd;
81 }
82
PrintStatsTitile()83 static void PrintStatsTitile()
84 {
85 cout << setw(TAG_W) << "TAG" << colCmd;
86 cout << setw(FREQ_W) << "MAX_FREQ" << colCmd;
87 cout << setw(TIME_W) << "TIME" << colCmd;
88 cout << setw(TP_W) << "MAX_TP" << colCmd;
89 cout << setw(TIME_W) << "TIME" << colCmd;
90 cout << setw(LINES_W) << "LINES" << colCmd;
91 cout << setw(LENGTH_W) << "LENGTH" << colCmd;
92 cout << setw(DROPPED_W) << "DROPPED" << colCmd;
93 }
94
GetTotalLines(const StatsRsp & rsp)95 static uint32_t GetTotalLines(const StatsRsp &rsp)
96 {
97 uint16_t i = 0;
98 uint32_t lines = 0;
99 for (i = 0; i < LevelNum; i++) {
100 lines += rsp.lines[i];
101 }
102 return lines;
103 }
104
GetTotalLen(const StatsRsp & rsp)105 static uint64_t GetTotalLen(const StatsRsp &rsp)
106 {
107 uint16_t i = 0;
108 uint64_t len = 0;
109 for (i = 0; i < LevelNum; i++) {
110 len += rsp.len[i];
111 }
112 return len;
113 }
114
PrintStats(const StatsRsp & rsp)115 static void PrintStats(const StatsRsp &rsp)
116 {
117 cout << fixed;
118 cout << setw(FREQ_W) << setprecision(FLOAT_PRECSION) << rsp.freqMax << colCmd;
119 cout << setw(TIME_W) << TimeStr(rsp.freqMaxSec, rsp.freqMaxNsec) << colCmd;
120 cout << setw(TP_W) << setprecision(FLOAT_PRECSION) << rsp.throughputMax << colCmd;
121 cout << setw(TIME_W) << TimeStr(rsp.tpMaxSec, rsp.tpMaxNsec) << colCmd;
122 cout << setw(LINES_W) << GetTotalLines(rsp) << colCmd;
123 cout << setw(LENGTH_W) << Size2Str(GetTotalLen(rsp)) << colCmd;
124 cout << setw(DROPPED_W) << rsp.dropped << colCmd;
125 }
126
DurationStr(uint32_t tv_sec,uint32_t tv_nsec)127 static string DurationStr(uint32_t tv_sec, uint32_t tv_nsec)
128 {
129 char buffer[TIME_W] = {0};
130 uint32_t tmp = tv_sec;
131 uint32_t hour = tmp / HOUR2SEC;
132 tmp -= (hour * HOUR2SEC);
133 uint32_t min = tmp / MIN2SEC;
134 uint32_t sec = tmp - (min * MIN2SEC);
135 uint32_t msec = tv_nsec / NS2MS;
136 int ret = 0;
137 ret = snprintf_s(buffer, TIME_W, TIME_W - 1, "%uh%um%us.%u", hour, min, sec, msec);
138 if (ret <= 0) {
139 return "ERROR";
140 }
141 return buffer;
142 }
143
144 template<typename T>
SortByLens(vector<T> & v,const T * list,int num)145 static void SortByLens(vector<T>& v, const T* list, int num)
146 {
147 v.insert(v.begin(), list, list + num);
148 std::sort(v.begin(), v.end(), [](T& a, T& b) {
149 return GetTotalLen(a.stats) > GetTotalLen(b.stats);
150 });
151 }
152
SortDomainList(vector<DomainStatsRsp> & vd,const DomainStatsRsp * domainList,int num)153 static void SortDomainList(vector<DomainStatsRsp>& vd, const DomainStatsRsp* domainList, int num)
154 {
155 SortByLens(vd, domainList, num);
156 }
157
SortProcList(vector<ProcStatsRsp> & vp,const ProcStatsRsp * procList,int num)158 static void SortProcList(vector<ProcStatsRsp>& vp, const ProcStatsRsp* procList, int num)
159 {
160 SortByLens(vp, procList, num);
161 }
162
SortTagList(vector<TagStatsRsp> & vt,const TagStatsRsp * tagList,int num)163 static void SortTagList(vector<TagStatsRsp>& vt, const TagStatsRsp* tagList, int num)
164 {
165 SortByLens(vt, tagList, num);
166 }
167
HilogShowDomainStatsInfo(const StatsQueryRsp & rsp)168 static void HilogShowDomainStatsInfo(const StatsQueryRsp& rsp)
169 {
170 cout << "Domain Table:" << endl;
171 PrintDomainTitle();
172 PrintStatsTitile();
173 cout << endl;
174 uint16_t i = 0;
175 for (i = 0; i < rsp.typeNum; i++) {
176 LogTypeDomainStatsRsp &ldStats = rsp.ldStats[i];
177 uint16_t j = 0;
178 if (ldStats.dStats == nullptr) {
179 continue;
180 }
181 vector<DomainStatsRsp> vd; // sort domain list
182 SortDomainList(vd, ldStats.dStats, ldStats.domainNum);
183 for (j = 0; j < ldStats.domainNum; j++) {
184 DomainStatsRsp &dStats = vd[j];
185 cout << setw(LOGTYPE_W) << LogType2Str(ldStats.type) << colCmd;
186 cout << std::hex << "0x" << setw(DOMAIN_W) << dStats.domain << std::dec << colCmd;
187 cout << setw(TAG_W) << "-" << colCmd;
188 PrintStats(dStats.stats);
189 cout << endl;
190 uint16_t k = 0;
191 if (dStats.tStats == nullptr) {
192 continue;
193 }
194 vector<TagStatsRsp> vt; // sort tag list
195 SortTagList(vt, dStats.tStats, dStats.tagNum);
196 for (k = 0; k < dStats.tagNum; k++) {
197 TagStatsRsp &tStats = vt[k];
198 cout << setw(LOGTYPE_W) << LogType2Str(ldStats.type) << colCmd;
199 cout << std::hex << "0x" << setw(DOMAIN_W) << dStats.domain << std::dec << colCmd;
200 cout << setw(TAG_W) << tStats.tag << colCmd;
201 PrintStats(tStats.stats);
202 cout << endl;
203 }
204 }
205 }
206 }
207
GetProcessName(const ProcStatsRsp & pStats)208 static string GetProcessName(const ProcStatsRsp &pStats)
209 {
210 /* hap process is forked from /system/bin/appspawn, sa process is started by /system/bin/sa_main
211 the name will be changed after process forking, hilogd holds the original name always,
212 here we need reconfirm it */
213 string name = GetNameByPid(pStats.pid);
214 if (name == "") {
215 name = pStats.name;
216 }
217 return name.substr(0, PNAME_W - 1);
218 }
219
HiLogShowProcInfo(const std::string & logType,uint32_t pid,const std::string & processName,const std::string & tag)220 static inline void HiLogShowProcInfo(const std::string& logType, uint32_t pid, const std::string& processName,
221 const std::string& tag)
222 {
223 cout << setw(LOGTYPE_W) << logType << colCmd;
224 cout << setw(PID_W) << pid << colCmd;
225 cout << setw(PNAME_W) << processName << colCmd;
226 cout << setw(TAG_W) << tag << colCmd;
227 }
228
HilogShowProcStatsInfo(const StatsQueryRsp & rsp)229 static void HilogShowProcStatsInfo(const StatsQueryRsp& rsp)
230 {
231 cout << "Pid Table:" << endl;
232 PrintPidTitle();
233 PrintStatsTitile();
234 cout << endl;
235 uint16_t i = 0;
236 if (rsp.pStats == nullptr) {
237 return;
238 }
239 vector<ProcStatsRsp> vp; // sort process list
240 SortProcList(vp, rsp.pStats, rsp.procNum);
241 for (i = 0; i < rsp.procNum; i++) {
242 ProcStatsRsp &pStats = vp[i];
243 string name = GetProcessName(pStats);
244 HiLogShowProcInfo("-", pStats.pid, name, "-");
245 PrintStats(pStats.stats);
246 cout << endl;
247 uint16_t j = 0;
248 if (pStats.lStats == nullptr) {
249 continue;
250 }
251 for (j = 0; j < pStats.typeNum; j++) {
252 LogTypeStatsRsp &lStats = pStats.lStats[j];
253 if (GetTotalLines(lStats.stats) == 0) {
254 continue;
255 }
256 HiLogShowProcInfo(LogType2Str(lStats.type), pStats.pid, name, "-");
257 PrintStats(lStats.stats);
258 cout << endl;
259 }
260 if (pStats.tStats == nullptr) {
261 continue;
262 }
263 vector<TagStatsRsp> vt; // sort tag list
264 SortTagList(vt, pStats.tStats, pStats.tagNum);
265 for (j = 0; j < pStats.tagNum; j++) {
266 TagStatsRsp &tStats = vt[j];
267 HiLogShowProcInfo("-", pStats.pid, name, std::string(tStats.tag));
268 PrintStats(tStats.stats);
269 cout << endl;
270 }
271 }
272 }
273
HilogShowLogStatsInfo(const StatsQueryRsp & rsp)274 void HilogShowLogStatsInfo(const StatsQueryRsp& rsp)
275 {
276 cout << std::left;
277 cout << "Log statistic report (Duration: " << DurationStr(rsp.durationSec, rsp.durationNsec);
278 cout << ", From: " << TimeStr(rsp.tsBeginSec, rsp.tsBeginNsec) << "):" << endl;
279 uint32_t lines = 0;
280 uint64_t lens = 0;
281 for (int i = 0; i < LevelNum; i++) {
282 lines += rsp.totalLines[i];
283 lens += rsp.totalLens[i];
284 }
285 if (lines == 0) {
286 return;
287 }
288 cout << "Total lines: " << lines << ", length: " << Size2Str(lens) << endl;
289 static const int PERCENT = 100;
290 for (int i = 0; i < LevelNum; i++) {
291 string level = LogLevel2Str(static_cast<uint16_t>(i + LevelBase));
292 cout << level << " lines: " << rsp.totalLines[i];
293 cout << "(" << setprecision(FLOAT_PRECSION) << (static_cast<float>(rsp.totalLines[i] * PERCENT) / lines) <<
294 "%)";
295 cout << ", length: " << Size2Str(rsp.totalLens[i]);
296 cout << "(" << setprecision(FLOAT_PRECSION) << (static_cast<float>(rsp.totalLens[i] * PERCENT) / lens) <<
297 "%)";
298 cout<< endl;
299 }
300 cout << setw(STATS_W) << setfill('-') << "-" << endl;
301 HilogShowDomainStatsInfo(rsp);
302 cout << setw(STATS_W) << setfill('-') << "-" << endl;
303 HilogShowProcStatsInfo(rsp);
304 }
305 } // namespace HiviewDFX
306 } // namespace OHOS