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