• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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