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(¤t, &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