1 /*
2 * Copyright (c) 2022 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 #include <thread>
16 #include <algorithm>
17
18 #include <log_utils.h>
19 #include <properties.h>
20
21 #include "log_stats.h"
22
23 namespace OHOS {
24 namespace HiviewDFX {
25 using namespace std;
26
LogStats()27 LogStats::LogStats()
28 {
29 Reset();
30 enable = IsStatsEnable();
31 tagEnable = IsTagStatsEnable();
32 }
~LogStats()33 LogStats::~LogStats() {}
34
idxLvl(uint16_t lvl)35 static inline int idxLvl(uint16_t lvl)
36 {
37 return static_cast<int>(lvl) - LevelBase;
38 }
39
UpdateStats(StatsEntry & entry,const StatsInfo & info)40 static void UpdateStats(StatsEntry &entry, const StatsInfo &info)
41 {
42 LogTimeStamp ts_mono(info.mono_sec, info.tv_nsec);
43 static LogTimeStamp ts_audit_period(1, 0); // Audit period : one second
44 ts_mono -= entry.monoTimeLast;
45 if (ts_mono > ts_audit_period) {
46 entry.monoTimeLast -= entry.monoTimeAuditStart;
47 float secs = entry.monoTimeLast.FloatSecs();
48 if (secs < 1.0f) {
49 secs = 1.0f;
50 }
51 float freq = entry.tmpLines / secs;
52 if (freq > entry.freqMax) {
53 entry.freqMax = freq;
54 entry.realTimeFreqMax = entry.realTimeLast;
55 }
56 entry.tmpLines = 0;
57 float throughput = entry.tmpLen / secs;
58 if (throughput > entry.throughputMax) {
59 entry.throughputMax = throughput;
60 entry.realTimeThroughputMax = entry.realTimeLast;
61 }
62 entry.tmpLen = 0;
63 entry.monoTimeAuditStart.SetTimeStamp(info.mono_sec, info.tv_nsec);
64 }
65
66 int lvl = idxLvl(info.level);
67 entry.lines[lvl]++;
68 entry.len[lvl] += info.len;
69 entry.dropped += info.dropped;
70 entry.tmpLines++;
71 entry.tmpLen += info.len;
72 entry.monoTimeLast.SetTimeStamp(info.mono_sec, info.tv_nsec);
73 entry.realTimeLast.SetTimeStamp(info.tv_sec, info.tv_nsec);
74 }
75
ResetStatsEntry(StatsEntry & entry)76 static void ResetStatsEntry(StatsEntry &entry)
77 {
78 entry.dropped = 0;
79 entry.tmpLines = 0;
80 entry.freqMax = 0;
81 entry.realTimeFreqMax.SetTimeStamp(0, 0);
82 entry.tmpLen = 0;
83 entry.throughputMax = 0;
84 entry.realTimeThroughputMax.SetTimeStamp(0, 0);
85 entry.monoTimeLast.SetTimeStamp(0, 0);
86 entry.monoTimeAuditStart.SetTimeStamp(0, 0);
87 for (uint32_t &i : entry.lines) {
88 i = 0;
89 }
90 for (uint64_t &i : entry.len) {
91 i = 0;
92 }
93 }
94
StatsInfo2NewStatsEntry(const StatsInfo & info,StatsEntry & entry)95 static void StatsInfo2NewStatsEntry(const StatsInfo &info, StatsEntry &entry)
96 {
97 entry.dropped = info.dropped;
98 entry.tmpLines = 1;
99 entry.freqMax = 0;
100 entry.realTimeFreqMax.SetTimeStamp(info.tv_sec, info.tv_nsec);
101 entry.tmpLen = info.len;
102 entry.throughputMax = 0;
103 entry.realTimeThroughputMax.SetTimeStamp(info.tv_sec, info.tv_nsec);
104 entry.realTimeLast.SetTimeStamp(info.tv_sec, info.tv_nsec);
105 entry.monoTimeLast.SetTimeStamp(info.mono_sec, info.tv_nsec);
106 entry.monoTimeAuditStart.SetTimeStamp(info.mono_sec, info.tv_nsec);
107 for (uint32_t &i : entry.lines) {
108 i = 0;
109 }
110 for (uint64_t &i : entry.len) {
111 i = 0;
112 }
113 int lvl = idxLvl(info.level);
114 entry.lines[lvl] = 1;
115 entry.len[lvl] = info.len;
116 }
117
UpdateTagTable(TagTable & tt,const StatsInfo & info)118 void LogStats::UpdateTagTable(TagTable& tt, const StatsInfo &info)
119 {
120 if (!tagEnable) {
121 return;
122 }
123 auto itt = tt.find(info.tag);
124 if (itt != tt.end()) {
125 UpdateStats(itt->second, info);
126 } else {
127 TagStatsEntry entry;
128 StatsInfo2NewStatsEntry(info, entry);
129 (void)tt.emplace(info.tag, entry);
130 }
131 }
132
UpdateDomainTable(const StatsInfo & info)133 void LogStats::UpdateDomainTable(const StatsInfo &info)
134 {
135 DomainTable& t = domainStats[info.type];
136 auto it = t.find(info.domain);
137 if (it != t.end()) {
138 UpdateStats(it->second.stats, info);
139 } else {
140 DomainStatsEntry entry;
141 StatsInfo2NewStatsEntry(info, entry.stats);
142 auto result = t.emplace(info.domain, entry);
143 if (!result.second) {
144 cerr << "Add entry to DomainTable error" << endl;
145 return;
146 }
147 it = result.first;
148 }
149 UpdateTagTable(it->second.tagStats, info);
150 }
151
UpdatePidTable(const StatsInfo & info)152 void LogStats::UpdatePidTable(const StatsInfo &info)
153 {
154 PidTable& t = pidStats;
155 auto it = t.find(info.pid);
156 if (it != t.end()) {
157 UpdateStats(it->second.statsAll, info);
158 UpdateStats(it->second.stats[info.type], info);
159 } else {
160 PidStatsEntry entry;
161 StatsInfo2NewStatsEntry(info, entry.statsAll);
162 for (StatsEntry &e : entry.stats) {
163 ResetStatsEntry(e);
164 }
165 entry.stats[info.type] = entry.statsAll;
166 entry.name = GetNameByPid(info.pid);
167 auto result = t.emplace(info.pid, entry);
168 if (!result.second) {
169 cerr << "Add entry to PidTable error" << endl;
170 return;
171 }
172 it = result.first;
173 }
174 UpdateTagTable(it->second.tagStats, info);
175 }
176
Count(const StatsInfo & info)177 void LogStats::Count(const StatsInfo &info)
178 {
179 if (enable) {
180 std::scoped_lock lk(lock);
181 int index = idxLvl(info.level);
182 totalLines[index]++;
183 totalLens[index] += info.len;
184 UpdateDomainTable(info);
185 UpdatePidTable(info);
186 }
187 }
188
Reset()189 void LogStats::Reset()
190 {
191 std::scoped_lock lk(lock);
192 for (auto &t : domainStats) {
193 t.clear();
194 }
195 pidStats.clear();
196 tsBegin = LogTimeStamp(CLOCK_REALTIME);
197 monoBegin = LogTimeStamp(CLOCK_MONOTONIC);
198 for (int i = 0; i < LevelNum; i++) {
199 totalLines[i] = 0;
200 totalLens[i] = 0;
201 }
202 }
203
GetDomainTable() const204 const LogTypeDomainTable& LogStats::GetDomainTable() const
205 {
206 return domainStats;
207 }
208
GetPidTable() const209 const PidTable& LogStats::GetPidTable() const
210 {
211 return pidStats;
212 }
213
GetBeginTs() const214 const LogTimeStamp& LogStats::GetBeginTs() const
215 {
216 return tsBegin;
217 }
218
GetBeginMono() const219 const LogTimeStamp& LogStats::GetBeginMono() const
220 {
221 return monoBegin;
222 }
223
GetTotalLines(uint32_t (& in_lines)[LevelNum]) const224 void LogStats::GetTotalLines(uint32_t (&in_lines)[LevelNum]) const
225 {
226 std::copy(totalLines, totalLines + LevelNum, in_lines);
227 }
228
GetTotalLens(uint64_t (& in_lens)[LevelNum]) const229 void LogStats::GetTotalLens(uint64_t (&in_lens)[LevelNum]) const
230 {
231 std::copy(totalLens, totalLens + LevelNum, in_lens);
232 }
233
IsEnable() const234 bool LogStats::IsEnable() const
235 {
236 return enable;
237 }
238
IsTagEnable() const239 bool LogStats::IsTagEnable() const
240 {
241 return tagEnable;
242 }
243
GetLock()244 std::unique_lock<std::mutex> LogStats::GetLock()
245 {
246 std::unique_lock<std::mutex> lk(lock);
247 return lk;
248 }
249
Print()250 void LogStats::Print()
251 {
252 cout << "Domain Table:" << endl;
253 int i = 0;
254 for (auto &t : domainStats) {
255 i++;
256 if (t.size() == 0) {
257 continue;
258 }
259 cout << " Log type:" << (i - 1) << endl;
260 for (auto &it : t) {
261 cout << " Domain: 0x" << std::hex << it.first << std::dec << endl;
262 cout << " ";
263 it.second.stats.Print();
264 for (auto &itt : it.second.tagStats) {
265 cout << " Tag: " << itt.first << endl;
266 cout << " ";
267 itt.second.Print();
268 }
269 }
270 }
271 cout << "Pid Table:" << endl;
272 for (auto &t : pidStats) {
273 cout << " Proc: " << t.second.name << "(" << t.first << ")" << endl;
274 cout << " ";
275 t.second.statsAll.Print();
276 int i = 0;
277 for (auto &s : t.second.stats) {
278 i++;
279 if (s.GetTotalLines() == 0) {
280 continue;
281 }
282 cout << " Log Type: " << (i - 1) << endl;
283 cout << " ";
284 s.Print();
285 }
286 for (auto &itt : t.second.tagStats) {
287 cout << " Tag: " << itt.first << endl;
288 cout << " ";
289 itt.second.Print();
290 }
291 }
292 }
293 } // namespace HiviewDFX
294 } // namespace OHOS