• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "HiViewAdapter"
17 
18 #include "hiview_adapter.h"
19 #include <thread>
20 #include <unistd.h>
21 #include "log_print.h"
22 
23 namespace OHOS {
24 namespace DistributedDataDfx {
25 using namespace DistributedKv;
26 namespace {
27 // fault key
28 constexpr const char *FAULT_TYPE = "FAULT_TYPE";
29 constexpr const char *MODULE_NAME = "MODULE_NAME";
30 constexpr const char *INTERFACE_NAME = "INTERFACE_NAME";
31 constexpr const char *ERROR_TYPE = "ERROR_TYPE";
32 constexpr const char *SYNC_ERROR_INFO = "SYNC_ERROR_INFO";
33 // Database statistic
34 constexpr const char *USER_ID = "ANONYMOUS_UID";
35 constexpr const char *APP_ID = "APP_ID";
36 constexpr const char *STORE_ID = "STORE_ID";
37 constexpr const char *DB_SIZE = "DB_SIZE";
38 // interface visit statistic
39 constexpr const char *TIMES = "TIMES";
40 constexpr const char *DEVICE_ID = "ANONYMOUS_DID";
41 constexpr const char *SEND_SIZE = "SEND_SIZE";
42 constexpr const char *RECEIVED_SIZE = "RECEIVED_SIZE";
43 constexpr const char *AVERAGE_TIMES = "AVERAGE_TIME";
44 constexpr const char *WORST_TIMES = "WORST_TIME";
45 constexpr const char *INTERFACES = "INTERFACES";
46 constexpr const char *TAG = "TAG";
47 constexpr const char *POWERSTATS = "PowerStats";
48 // behaviour key
49 constexpr const char *BEHAVIOUR_INFO = "BEHAVIOUR_INFO";
50 
51 const std::map<int, std::string> EVENT_COVERT_TABLE = {
52     { DfxCodeConstant::SERVICE_FAULT, "SERVICE_FAULT" },
53     { DfxCodeConstant::RUNTIME_FAULT, "RUNTIME_FAULT" },
54     { DfxCodeConstant::DATABASE_FAULT, "DATABASE_FAULT" },
55     { DfxCodeConstant::COMMUNICATION_FAULT, "COMMUNICATION_FAULT" },
56     { DfxCodeConstant::DATABASE_STATISTIC, "DATABASE_STATISTIC}" },
57     { DfxCodeConstant::VISIT_STATISTIC, "VISIT_STATISTIC" },
58     { DfxCodeConstant::TRAFFIC_STATISTIC, "VISIT_STATISTIC" },
59     { DfxCodeConstant::DATABASE_PERFORMANCE_STATISTIC, "DATABASE_PERFORMANCE_STATISTIC" },
60     { DfxCodeConstant::API_PERFORMANCE_STATISTIC, "API_PERFORMANCE_STATISTIC" },
61     { DfxCodeConstant::API_PERFORMANCE_INTERFACE, "API_PERFORMANCE_STATISTIC" },
62     { DfxCodeConstant::DATABASE_SYNC_FAILED, "DATABASE_SYNC_FAILED" },
63     { DfxCodeConstant::DATABASE_CORRUPTED_FAILED, "DATABASE_CORRUPTED_FAILED" },
64     { DfxCodeConstant::DATABASE_REKEY_FAILED, "DATABASE_REKEY_FAILED" },
65     { DfxCodeConstant::DATABASE_BEHAVIOUR, "DATABASE_BEHAVIOUR" },
66 };
67 }
68 using OHOS::HiviewDFX::HiSysEvent;
69 std::shared_ptr<KvStoreThreadPool> HiViewAdapter::pool_ = KvStoreThreadPool::GetPool(POOL_SIZE, "HiView", true);
70 
71 std::mutex HiViewAdapter::visitMutex_;
72 std::map<std::string, StatisticWrap<VisitStat>> HiViewAdapter::visitStat_;
73 
74 std::mutex HiViewAdapter::trafficMutex_;
75 std::map<std::string, StatisticWrap<TrafficStat>> HiViewAdapter::trafficStat_;
76 
77 std::mutex HiViewAdapter::dbMutex_;
78 std::map<std::string, StatisticWrap<DbStat>> HiViewAdapter::dbStat_;
79 
80 std::mutex HiViewAdapter::apiPerformanceMutex_;
81 std::map<std::string, StatisticWrap<ApiPerformanceStat>> HiViewAdapter::apiPerformanceStat_;
82 
83 bool HiViewAdapter::running_ = false;
84 TaskScheduler HiViewAdapter::scheduler_ {"HiView"};
85 std::mutex HiViewAdapter::runMutex_;
86 
ReportFault(int dfxCode,const FaultMsg & msg)87 void HiViewAdapter::ReportFault(int dfxCode, const FaultMsg &msg)
88 {
89     if (pool_ == nullptr) {
90         return;
91     }
92     KvStoreTask task([dfxCode, msg]() {
93         HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
94             CoverEventID(dfxCode),
95             HiSysEvent::EventType::FAULT,
96             FAULT_TYPE, static_cast<int>(msg.faultType),
97             MODULE_NAME, msg.moduleName,
98             INTERFACE_NAME, msg.interfaceName,
99             ERROR_TYPE, static_cast<int>(msg.errorType));
100     });
101     pool_->AddTask(std::move(task));
102 }
103 
ReportDBFault(int dfxCode,const DBFaultMsg & msg)104 void HiViewAdapter::ReportDBFault(int dfxCode, const DBFaultMsg &msg)
105 {
106     if (pool_ == nullptr) {
107         return;
108     }
109     KvStoreTask task([dfxCode, msg]() {
110         HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
111             CoverEventID(dfxCode),
112             HiSysEvent::EventType::FAULT,
113             APP_ID, msg.appId,
114             STORE_ID, msg.storeId,
115             MODULE_NAME, msg.moduleName,
116             ERROR_TYPE, static_cast<int>(msg.errorType));
117     });
118     pool_->AddTask(std::move(task));
119 }
120 
121 
ReportCommFault(int dfxCode,const CommFaultMsg & msg)122 void HiViewAdapter::ReportCommFault(int dfxCode, const CommFaultMsg &msg)
123 {
124     if (pool_ == nullptr) {
125         return;
126     }
127     KvStoreTask task([dfxCode, msg]() {
128         std::string message;
129         for (size_t i = 0; i < msg.deviceId.size(); i++) {
130             message.append("No: ").append(std::to_string(i))
131             .append(" sync to device: ").append(msg.deviceId[i])
132             .append(" has error, errCode:").append(std::to_string(msg.errorCode[i])).append(". ");
133         }
134         HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
135             CoverEventID(dfxCode),
136             HiSysEvent::EventType::FAULT,
137             USER_ID, msg.userId,
138             APP_ID, msg.appId,
139             STORE_ID, msg.storeId,
140             SYNC_ERROR_INFO, message);
141     });
142     pool_->AddTask(std::move(task));
143 }
144 
ReportBehaviour(int dfxCode,const BehaviourMsg & msg)145 void HiViewAdapter::ReportBehaviour(int dfxCode, const BehaviourMsg &msg)
146 {
147     if (pool_ == nullptr) {
148         return;
149     }
150     KvStoreTask task([dfxCode, msg]() {
151         std::string message;
152         message.append("Behaviour type : ").append(std::to_string(static_cast<int>(msg.behaviourType)))
153             .append(" behaviour info : ").append(msg.extensionInfo);
154         HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
155             CoverEventID(dfxCode),
156             HiSysEvent::EventType::BEHAVIOR,
157             USER_ID, msg.userId,
158             APP_ID, msg.appId,
159             STORE_ID, msg.storeId,
160             BEHAVIOUR_INFO, message);
161     });
162     pool_->AddTask(std::move(task));
163 }
164 
ReportDatabaseStatistic(int dfxCode,const DbStat & stat)165 void HiViewAdapter::ReportDatabaseStatistic(int dfxCode, const DbStat &stat)
166 {
167     if (pool_ == nullptr) {
168         return;
169     }
170     KvStoreTask task([dfxCode, stat]() {
171         std::lock_guard<std::mutex> lock(dbMutex_);
172         if (!dbStat_.count(stat.GetKey())) {
173             dbStat_.insert({stat.GetKey(), {stat, 0, dfxCode}});
174         }
175     });
176     pool_->AddTask(std::move(task));
177     StartTimerThread();
178 }
179 
ReportDbSize(const StatisticWrap<DbStat> & stat)180 void HiViewAdapter::ReportDbSize(const StatisticWrap<DbStat> &stat)
181 {
182     uint64_t dbSize;
183     if (!stat.val.delegate->GetKvStoreDiskSize(stat.val.storeId, dbSize)) {
184         return;
185     }
186 
187     ValueHash vh;
188     std::string userId;
189     if (!vh.CalcValueHash(stat.val.userId, userId)) {
190         return;
191     }
192 
193     HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
194         CoverEventID(stat.code),
195         HiSysEvent::EventType::STATISTIC,
196         USER_ID, userId, APP_ID, stat.val.appId, STORE_ID, stat.val.storeId, DB_SIZE, dbSize);
197 }
198 
InvokeDbSize()199 void HiViewAdapter::InvokeDbSize()
200 {
201     std::lock_guard<std::mutex> lock(dbMutex_);
202     for (auto const &kv : dbStat_) {
203         if (kv.second.val.delegate == nullptr) {
204             continue;
205         }
206         // device coordinate for single version database
207         if (!kv.second.val.storeId.empty()) {
208             ReportDbSize(kv.second);
209             continue;
210         }
211         // below codes for multiple version database
212         std::vector<StoreInfo> storeInfos;
213         kv.second.val.delegate->GetKvStoreKeys(storeInfos);
214         if (storeInfos.empty()) {
215             continue;
216         }
217         for (auto const &storeInfo : storeInfos) {
218             ReportDbSize({{storeInfo.userId, storeInfo.appId, storeInfo.storeId, 0,
219                 kv.second.val.delegate}, 0, kv.second.code});
220         }
221     }
222     dbStat_.clear();
223 }
224 
ReportTrafficStatistic(int dfxCode,const TrafficStat & stat)225 void HiViewAdapter::ReportTrafficStatistic(int dfxCode, const TrafficStat &stat)
226 {
227     if (pool_ == nullptr) {
228         return;
229     }
230     KvStoreTask task([dfxCode, stat]() {
231         std::lock_guard<std::mutex> lock(trafficMutex_);
232         auto it = trafficStat_.find(stat.GetKey());
233         if (it != trafficStat_.end()) {
234             it->second.val.receivedSize += stat.receivedSize;
235             it->second.val.sendSize += stat.sendSize;
236         } else {
237             trafficStat_.insert({stat.GetKey(), {stat, 0, dfxCode}});
238         }
239     });
240     pool_->AddTask(std::move(task));
241     StartTimerThread();
242 }
243 
InvokeTraffic()244 void HiViewAdapter::InvokeTraffic()
245 {
246     std::lock_guard<std::mutex> lock(trafficMutex_);
247     ValueHash vh;
248     for (auto const &kv : trafficStat_) {
249         std::string deviceId;
250         if (!vh.CalcValueHash(kv.second.val.deviceId, deviceId)) {
251             continue;
252         }
253 
254         HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
255             CoverEventID(kv.second.code),
256             HiSysEvent::EventType::STATISTIC,
257             TAG, POWERSTATS,
258             APP_ID, kv.second.val.appId,
259             DEVICE_ID, deviceId,
260             SEND_SIZE, kv.second.val.sendSize,
261             RECEIVED_SIZE, kv.second.val.receivedSize);
262     }
263     trafficStat_.clear();
264 }
265 
ReportVisitStatistic(int dfxCode,const VisitStat & stat)266 void HiViewAdapter::ReportVisitStatistic(int dfxCode, const VisitStat &stat)
267 {
268     if (pool_ == nullptr) {
269         return;
270     }
271     KvStoreTask task([dfxCode, stat]() {
272         std::lock_guard<std::mutex> lock(visitMutex_);
273         auto it = visitStat_.find(stat.GetKey());
274         if (it == visitStat_.end()) {
275             visitStat_.insert({stat.GetKey(), {stat, 1, dfxCode}});
276         } else {
277             it->second.times++;
278         }
279     });
280     pool_->AddTask(std::move(task));
281     StartTimerThread();
282 }
283 
InvokeVisit()284 void HiViewAdapter::InvokeVisit()
285 {
286     std::lock_guard<std::mutex> lock(visitMutex_);
287     for (auto const &kv : visitStat_) {
288         HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
289             CoverEventID(kv.second.code),
290             HiSysEvent::EventType::STATISTIC,
291             TAG, POWERSTATS,
292             APP_ID, kv.second.val.appId,
293             INTERFACE_NAME, kv.second.val.interfaceName,
294             TIMES, kv.second.times);
295     }
296     visitStat_.clear();
297 }
298 
ReportApiPerformanceStatistic(int dfxCode,const ApiPerformanceStat & stat)299 void HiViewAdapter::ReportApiPerformanceStatistic(int dfxCode, const ApiPerformanceStat &stat)
300 {
301     if (pool_ == nullptr) {
302         return;
303     }
304     KvStoreTask task([dfxCode, stat]() {
305         std::lock_guard<std::mutex> lock(apiPerformanceMutex_);
306         auto it = apiPerformanceStat_.find(stat.GetKey());
307         if (it == apiPerformanceStat_.end()) {
308             apiPerformanceStat_.insert({stat.GetKey(), {stat, 1, dfxCode}}); // the init value of times is 1
309         } else {
310             it->second.times++;
311             it->second.val.costTime = stat.costTime;
312             if (it->second.times > 0) {
313                 it->second.val.averageTime =
314                     (it->second.val.averageTime * static_cast<uint64_t>(it->second.times - 1) + stat.costTime)
315                     / it->second.times;
316             }
317             if (stat.costTime > it->second.val.worstTime) {
318                 it->second.val.worstTime = stat.costTime;
319             }
320         }
321     });
322     pool_->AddTask(std::move(task));
323     StartTimerThread();
324 }
325 
InvokeApiPerformance()326 void HiViewAdapter::InvokeApiPerformance()
327 {
328     std::string message;
329     message.append("[");
330     std::lock_guard<std::mutex> lock(apiPerformanceMutex_);
331     for (auto const &kv : apiPerformanceStat_) {
332         message.append("{\"CODE\":\"").append(std::to_string(kv.second.code)).append("\",")
333         .append("\"").append(INTERFACE_NAME).append("\":\"").append(kv.second.val.interfaceName).append("\",")
334         .append("\"").append(TIMES).append("\":").append(std::to_string(kv.second.times)).append(",")
335         .append("\"").append(AVERAGE_TIMES).append("\":").append(std::to_string(kv.second.val.averageTime)).append(",")
336         .append("\"").append(WORST_TIMES).append("\":").append(std::to_string(kv.second.val.worstTime)).append("}");
337     }
338     message.append("]");
339     HiSysEvent::Write(HiSysEvent::Domain::DISTRIBUTED_DATAMGR,
340         CoverEventID(DfxCodeConstant::API_PERFORMANCE_STATISTIC),
341         HiSysEvent::EventType::STATISTIC,
342         INTERFACES, message);
343     apiPerformanceStat_.clear();
344     ZLOGI("DdsTrace interface: clean");
345 }
346 
StartTimerThread()347 void HiViewAdapter::StartTimerThread()
348 {
349     if (running_) {
350         return;
351     }
352     std::lock_guard<std::mutex> lock(runMutex_);
353     if (running_) {
354         return;
355     }
356     running_ = true;
357     std::chrono::duration<int> delay(0);
358     std::chrono::duration<int> internal(WAIT_TIME);
359     auto fun = []() {
360         time_t current = time(nullptr);
361         tm localTime = { 0 };
362         tm *result = localtime_r(&current, &localTime);
363         if ((result != nullptr) && (localTime.tm_hour == DAILY_REPORT_TIME)) {
364             InvokeDbSize();
365             InvokeApiPerformance();
366         }
367         InvokeTraffic();
368         InvokeVisit();
369     };
370     scheduler_.Every(delay, internal, fun);
371 }
372 
CoverEventID(int dfxCode)373 std::string HiViewAdapter::CoverEventID(int dfxCode)
374 {
375     std::string sysEventID = "";
376     auto operatorIter = EVENT_COVERT_TABLE.find(dfxCode);
377     if (operatorIter != EVENT_COVERT_TABLE.end()) {
378         sysEventID = operatorIter->second;
379     }
380     return sysEventID;
381 }
382 } // namespace DistributedDataDfx
383 } // namespace OHOS
384