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
16 #include "report.h"
17
18 #include <algorithm>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include <sstream>
23 #include <sys/inotify.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "ability_manager_client.h"
28 #include "element_name.h"
29 #include "exception_manager.h"
30 #include "filter_category.h"
31 #include "format_csv.h"
32 #include "format_json.h"
33 #include "statistics_ability.h"
34 #include "statistics_componment.h"
35 #include "statistics_event.h"
36 #include "statistics_exception.h"
37 #include "string_ex.h"
38 #include "wukong_define.h"
39 #include "wukong_util.h"
40
41 namespace OHOS {
42 namespace WuKong {
43 namespace {
44 const uint32_t SEGMENT_STATISTICS_LENGTH = 10;
45 std::string crashDir = "/data/log/faultlog/faultlogger/";
ListenCrashDir()46 void ListenCrashDir()
47 {
48 int fd;
49 int wd;
50 ssize_t readLenght;
51 char buf[BUFSIZ];
52 char* bufPtr = nullptr;
53 struct inotify_event *event;
54 fd = inotify_init();
55 INFO_LOG("init notify");
56 if (fd < 0) {
57 return;
58 }
59 wd = inotify_add_watch(fd, "/data/log/faultlog/faultlogger/", IN_CLOSE_WRITE);
60 INFO_LOG("add_watch");
61 if (wd < 0) {
62 ERROR_LOG("inotify_add_watch /data/log/faultlog/faultlogger/ failed");
63 return;
64 }
65 buf[sizeof(buf) - 1] = 0;
66 std::string destDir = Report::GetInstance()->GetReportExceptionDir();
67 while ((readLenght = read(fd, buf, sizeof(buf) - 1)) > 0) {
68 uint32_t len = static_cast<uint32_t>(readLenght);
69 uint32_t nread = 0;
70 while (len > 0) {
71 bufPtr = &buf[nread];
72 void* middleType = static_cast<void *>(bufPtr);
73 event = static_cast<struct inotify_event *>(middleType);
74 if ((event->mask & IN_CLOSE_WRITE) && (event->len > 0)) {
75 DEBUG_LOG_STR("event->mask{%x}", event->mask);
76 std::string targetFile(event->name);
77 WuKongUtil::GetInstance()->CopyFile(targetFile, crashDir, destDir);
78 DEBUG_LOG_STR("%s --- IN_CLOSE_WRITE\n", event->name);
79 Report::GetInstance()->ExceptionRecord(targetFile);
80 }
81 nread = nread + sizeof(struct inotify_event) + event->len;
82 len = len - sizeof(struct inotify_event) - event->len;
83 }
84 }
85 INFO_LOG("exit thread");
86 return;
87 }
88
StartCrashDirListen()89 void StartCrashDirListen()
90 {
91 std::thread listenerThread(&ListenCrashDir);
92 INFO_LOG("create listener thread");
93 listenerThread.detach();
94 INFO_LOG("thread detach");
95 }
96 } // namespace
97 using namespace OHOS::AAFwk;
Report()98 Report::Report()
99 {
100 EnvInit();
101 DataSetInit();
102 }
103
EnvInit()104 void Report::EnvInit()
105 {
106 const std::string DEFAULT_DIR = "/data/local/tmp/wukong/report/";
107 startRunTime_ = WuKongUtil::GetInstance()->GetStartRunTime();
108 // Get a screenshot within the previous timestamp of the current timestamp
109 DIR *dirp = nullptr;
110 dirp = opendir(DEFAULT_DIR.c_str());
111 std::string maxValue = "";
112 std::string targetTimeDir;
113 // setting filename
114 currentTestDir_ = WuKongUtil::GetInstance()->GetCurrentTestDir();
115 INFO_LOG_STR("Report currentTestDir: (%s)", currentTestDir_.c_str());
116 // setting filename
117 reportCsvFileName_ = currentTestDir_ + "wukong_report.csv";
118 reportJsonFileName_ = currentTestDir_ + "data.js";
119 reportFocusInputFileName_ = currentTestDir_ + "focus_report";
120
121 INFO_LOG_STR("Report CSV: (%s)", reportCsvFileName_.c_str());
122 INFO_LOG_STR("Report JSON: (%s)", reportJsonFileName_.c_str());
123
124 reportExceptionDir_ = currentTestDir_ + "exception/";
125 INFO_LOG_STR("Report exception dir: (%s)", reportExceptionDir_.c_str());
126 int dirExist = access(reportExceptionDir_.c_str(), F_OK);
127 if (dirExist != 0) {
128 int dirStatus = mkdir((reportExceptionDir_).c_str(), 0777);
129 if (dirStatus == -1) {
130 ERROR_LOG("exception dir create fail");
131 }
132 }
133 StartCrashDirListen();
134 // register crash catcher
135 ExceptionManager::GetInstance()->StartCatching();
136 if (dirp == nullptr) {
137 ERROR_LOG_STR("dir{%s} opendir error", DEFAULT_DIR.c_str());
138 return;
139 }
140 while (dirp != nullptr) {
141 struct dirent *dp;
142 if ((dp = readdir(dirp)) == NULL) {
143 break;
144 }
145 std::string currentStringName(dp->d_name);
146 if (currentStringName != startRunTime_) {
147 if (currentStringName > maxValue) {
148 maxValue = currentStringName;
149 targetTimeDir = currentStringName;
150 }
151 }
152 }
153 (void)closedir(dirp);
154 // Delete the screenshot under the timestamp
155 std::string targetDir_ = DEFAULT_DIR + targetTimeDir +"/screenshot/";
156 WuKongUtil::GetInstance()->DeleteFile(targetDir_);
157 }
158
DataSetInit()159 void Report::DataSetInit()
160 {
161 std::shared_ptr<Filter> categoryFilter = std::make_shared<FilterCategory>();
162 eventDataSet_->SetFilterStragety(categoryFilter);
163 eventDataSet_->SetFilterType("event");
164 std::shared_ptr<Statistics> eventSatistics = std::make_shared<StatisticsEvent>();
165 eventDataSet_->SetStatisticsStragety(eventSatistics);
166
167 // set componment filter,statistics,format
168 componmentDataSet_->SetFilterStragety(categoryFilter);
169 componmentDataSet_->SetFilterType("componment");
170 std::shared_ptr<Statistics> componmentSatistics = std::make_shared<StatisticsComponment>();
171 componmentDataSet_->SetStatisticsStragety(componmentSatistics);
172
173 // set ability filter,statistics,format
174 abilityDataSet_->SetFilterStragety(categoryFilter);
175 abilityDataSet_->SetFilterType("abilityName");
176 std::shared_ptr<Statistics> abilitySatistics = std::make_shared<StatisticsAbility>();
177 abilityDataSet_->SetStatisticsStragety(abilitySatistics);
178
179 // set exception filter,statistics,format
180 exceptionDataSet_->SetFilterStragety(categoryFilter);
181 exceptionDataSet_->SetFilterType("exception");
182 std::shared_ptr<Statistics> exceptionSatistics = std::make_shared<StatisticsException>();
183 exceptionDataSet_->SetStatisticsStragety(exceptionSatistics);
184 }
185
SyncInputInfo(std::shared_ptr<InputedMsgObject> inputedMsgObject)186 void Report::SyncInputInfo(std::shared_ptr<InputedMsgObject> inputedMsgObject)
187 {
188 TRACK_LOG_STD();
189 std::shared_ptr<AbilityManagerClient> abilityManagerClient = AbilityManagerClient::GetInstance();
190 OHOS::AppExecFwk::ElementName elementName = abilityManagerClient->GetTopAbility();
191 std::map<std::string, std::string> data;
192 data["bundleName"] = elementName.GetBundleName();
193 data["abilityName"] = elementName.GetAbilityName();
194 DEBUG_LOG_STR("bundleName{%s} abilityName{%s} ", data["bundleName"].c_str(), data["abilityName"].c_str());
195 SplitInputMode(inputedMsgObject, data);
196
197 // first appswitch abandon
198 std::map<std::string, std::string>::iterator it = data.find("event");
199 if (it != data.end() && (data["event"] == "appswitch") && (isFirstAppSwitch_ == false)) {
200 DEBUG_LOG("first appswitch abandon");
201 isFirstAppSwitch_ = true;
202 return;
203 }
204 // record app used to control data display
205 std::vector<std::string>::iterator bundleIter = std::find(bundles_.begin(), bundles_.end(), data["bundleName"]);
206 if (bundleIter == bundles_.end()) {
207 DEBUG_LOG_STR("push apps item{%s}", data["bundleName"].c_str());
208 bundles_.push_back(data["bundleName"]);
209 }
210 // send `k => v` to filter
211 eventDataSet_->FilterData(data);
212 componmentDataSet_->FilterData(data);
213 abilityDataSet_->FilterData(data);
214 taskCount_++;
215 DEBUG_LOG_STR("taskCount{%d}", taskCount_);
216 if (is_focus_) {
217 GroupFocusDataAndRecord(inputedMsgObject, data);
218 }
219 // statistics and storage every 10 data
220 if ((taskCount_ % SEGMENT_STATISTICS_LENGTH) == 0) {
221 HilogFileRecord();
222 SegmentedWriteCSV();
223 SegmentedWriteJson();
224 if (is_focus_) {
225 SegmentedWriteForFocusInput();
226 }
227 }
228 TRACK_LOG_END();
229 }
230
SplitInputMode(std::shared_ptr<InputedMsgObject> & inputedMsgObject,std::map<std::string,std::string> & data)231 void Report::SplitInputMode(std::shared_ptr<InputedMsgObject> &inputedMsgObject,
232 std::map<std::string, std::string> &data)
233 {
234 inputedMode inputMode = inputedMsgObject->GetInputedMode();
235 switch (inputMode) {
236 case multimodeInput: {
237 auto inputMutlMsgPtr = std::static_pointer_cast<MultimodeInputMsg>(inputedMsgObject);
238 data["event"] = inputMutlMsgPtr->GetInputType();
239 DEBUG_LOG_STR("eventType{%s}", data["event"].c_str());
240 break;
241 }
242
243 case componmentInput: {
244 auto inputCompMsgPtr = std::static_pointer_cast<ComponmentInputMsg>(inputedMsgObject);
245 ComponmentInfoArrange(data["bundleName"], inputCompMsgPtr, data);
246 DEBUG_LOG("componmentType map");
247 break;
248 }
249 default:
250 break;
251 }
252 }
253
GroupFocusDataAndRecord(std::shared_ptr<InputedMsgObject> & inputedMsgObject,std::map<std::string,std::string> & data)254 void Report::GroupFocusDataAndRecord(std::shared_ptr<InputedMsgObject> &inputedMsgObject,
255 std::map<std::string, std::string> &data)
256 {
257 TRACK_LOG_STD();
258 inputedMode inputMode = inputedMsgObject->GetInputedMode();
259 if (inputMode != componmentInput) {
260 return;
261 }
262 auto inputCompMsgPtr = std::static_pointer_cast<ComponmentInputMsg>(inputedMsgObject);
263 std::string item = "";
264 time_t currentTime = time(0);
265 std::string timeStr = "";
266 if (currentTime > 0) {
267 timeStr = std::to_string(currentTime);
268 }
269 item += std::to_string(taskCount_) + ",";
270 item += timeStr + ",";
271 item += data["abilityName"] + ",";
272 item += inputCompMsgPtr->pagePath_ + ",";
273 item += inputCompMsgPtr->componmentType_ + ",";
274 item += std::to_string(inputCompMsgPtr->startX_) + ",";
275 item += std::to_string(inputCompMsgPtr->startY_) + ",";
276 item += std::to_string(inputCompMsgPtr->endX_) + ",";
277 item += std::to_string(inputCompMsgPtr->endY_) + ",";
278 item += inputCompMsgPtr->content_ + ",";
279 item += std::to_string(inputCompMsgPtr->pssTotal_);
280 focus_input_vec_.push_back(item);
281 TRACK_LOG_END();
282 }
283
~Report()284 Report::~Report()
285 {
286 }
287
SegmentedWriteCSV()288 void Report::SegmentedWriteCSV()
289 {
290 TRACK_LOG_STD();
291 // csv report format
292 if (reportCsvFileName_.empty()) {
293 return;
294 }
295 std::shared_ptr<FormatCSV> formatCSV = std::make_shared<FormatCSV>();
296 eventDataSet_->SetFormatStragety(formatCSV);
297 componmentDataSet_->SetFormatStragety(formatCSV);
298 abilityDataSet_->SetFormatStragety(formatCSV);
299 exceptionDataSet_->SetFormatStragety(formatCSV);
300 std::stringstream modules;
301 modules << "module, Base Info" << std::endl;
302 modules << "name, base" << std::endl;
303 modules << "detail, info" << std::endl;
304 modules << "name, base, detail, info" << std::endl;
305 modules << "task status, success" << std::endl;
306 modules << "task time , " << time(0) - startTime_ << std::endl;
307 if (!seed_.empty()) {
308 modules << "seed , " << seed_ << std::endl;
309 }
310 modules << "task count , " << taskCount_ << std::endl;
311 DEBUG_LOG("start event statistics");
312 eventDataSet_->StatisticsData();
313 DEBUG_LOG("end event statistics");
314 DEBUG_LOG("start componment statistics");
315 componmentDataSet_->StatisticsData();
316 DEBUG_LOG("end componment statistics");
317 std::string moduleInput;
318 modules << "module, Input Message Statistics" << std::endl;
319 modules << "name, all";
320 // show all app and detail
321 for (auto bundleIter : bundles_) {
322 modules << ", " << bundleIter;
323 }
324 modules << std::endl;
325 modules << "detail, event, componment" << std::endl;
326 eventDataSet_->FormatData("all", moduleInput);
327 componmentDataSet_->FormatData("all", moduleInput);
328 // loop app show name-type statistics content
329 for (auto bundleIter : bundles_) {
330 eventDataSet_->FormatData(bundleIter, moduleInput);
331 componmentDataSet_->FormatData(bundleIter, moduleInput);
332 }
333 modules << moduleInput;
334 modules << "module, ability Statistics" << std::endl;
335 modules << "name, all" << std::endl;
336 modules << "detail, ability" << std::endl;
337 moduleInput = "";
338 abilityDataSet_->StatisticsData();
339 abilityDataSet_->FormatData("all", moduleInput);
340 modules << moduleInput;
341
342 std::unique_lock<std::mutex> locker(crashMtx_);
343 modules << "module, Exception Message Statistics" << std::endl;
344 modules << "name, exception" << std::endl;
345 modules << "detail, statistics" << std::endl;
346 moduleInput = "";
347 exceptionDataSet_->StatisticsData();
348 exceptionDataSet_->FormatData("exception", moduleInput);
349 modules << moduleInput;
350 locker.unlock();
351 std::string csvContent = modules.str();
352 std::fstream csvFileStream(reportCsvFileName_, std::ios::out | std::ios::trunc);
353 csvFileStream << csvContent << std::endl;
354 csvFileStream.close();
355 TRACK_LOG_END();
356 }
357
SegmentedWriteJson()358 void Report::SegmentedWriteJson()
359 {
360 TRACK_LOG_STD();
361 DEBUG_LOG("SegmentedWriteJson start");
362 // csv report format
363 if (reportCsvFileName_.empty()) {
364 return;
365 }
366 std::shared_ptr<FormatJSON> formatJSON = std::make_shared<FormatJSON>();
367 eventDataSet_->SetFormatStragety(formatJSON);
368 componmentDataSet_->SetFormatStragety(formatJSON);
369 abilityDataSet_->SetFormatStragety(formatJSON);
370 exceptionDataSet_->SetFormatStragety(formatJSON);
371 std::stringstream modules;
372 std::string moduleInput;
373 modules << "var reportJson = {" << std::endl;
374 modules << "base: [" << std::endl;
375 modules << "{ item: \"task status\", detail: \" success \"}," << std::endl;
376 modules << "{ item: \"task time\", detail: \" " << time(0) - startTime_ << "s\"}," << std::endl;
377 modules << "{ item: \"task count\", detail: \" " << taskCount_ << "\"}," << std::endl;
378 if (!seed_.empty()) {
379 modules << "{ item: \"seed\", detail: \" " << seed_ << "\"}," << std::endl;
380 }
381 modules << "]," << std::endl;
382 modules << "detailApps:{" << std::endl;
383 modules << "names:[ \"all\"";
384 // show all app and detail
385 for (auto bundleIter : bundles_) {
386 modules << ", \"" << bundleIter << " \"";
387 }
388 modules << "]," << std::endl;
389 modules << "details: [" << std::endl;
390 modules << "{" << std::endl;
391 modules << "eventStatistics:" << std::endl;
392 eventDataSet_->FormatData("all", moduleInput);
393 modules << moduleInput;
394 modules << "controlStatistics:";
395 componmentDataSet_->FormatData("all", moduleInput);
396 modules << moduleInput;
397 modules << "},";
398 // loop app show name-type statistics content
399 for (auto bundleIter : bundles_) {
400 modules << "{" << std::endl;
401 modules << "eventStatistics:";
402 eventDataSet_->FormatData(bundleIter, moduleInput);
403 modules << moduleInput;
404 modules << "controlStatistics:";
405 componmentDataSet_->FormatData(bundleIter, moduleInput);
406 modules << moduleInput;
407 modules << "},";
408 }
409 modules << "]" << std::endl;
410 modules << "}," << std::endl;
411 modules << "abilityStatistics:";
412 abilityDataSet_->FormatData("all", moduleInput);
413 modules << moduleInput;
414 modules << "detailException: {" << std::endl;
415 modules << "names: [\"exception statistics\", \"cpp crash statistics\", \"js crash statistics\"]," << std::endl;
416 modules << "details: [" << std::endl;
417 modules << "{" << std::endl;
418 modules << "exception_statistics: {" << std::endl;
419 modules << "header: [\"Type\", \"Times\", \"Proportion\"]," << std::endl;
420 modules << "content: " << std::endl;
421 exceptionDataSet_->FormatData("exception", moduleInput);
422 modules << moduleInput;
423 modules << "}," << std::endl;
424 modules << "}," << std::endl;
425 modules << "]" << std::endl;
426 modules << "}," << std::endl;
427 unsigned int index = 0;
428 modules << "screens:[" << std::endl;
429 for (auto srceen : screenPaths_) {
430 modules << "{index:\"" << index << "\","
431 << "path:\"" << srceen << "\"}," << std::endl;
432 index++;
433 }
434 modules << "]," << std::endl;
435 modules << "};" << std::endl;
436 std::string jsonContent = modules.str();
437 std::fstream jsonFileStream(reportJsonFileName_, std::ios::out | std::ios::trunc);
438 jsonFileStream << jsonContent << std::endl;
439 jsonFileStream.close();
440 DEBUG_LOG("SegmentedWriteJson end");
441 TRACK_LOG_END();
442 }
443
SegmentedWriteForFocusInput()444 void Report::SegmentedWriteForFocusInput()
445 {
446 TRACK_LOG_STD();
447 DEBUG_LOG("SegmentedWriteForFocusInput start");
448 // csv report format
449 if (reportFocusInputFileName_.empty()) {
450 return;
451 }
452
453 std::stringstream modules;
454 for (size_t i = 0; i < focus_input_vec_.size(); ++i) {
455 modules << focus_input_vec_[i];
456 if (i < focus_input_vec_.size() - 1) {
457 modules << std::endl;
458 }
459 }
460 focus_input_vec_.clear();
461 std::string jsonContent = modules.str();
462 std::fstream jsonFileStream(reportFocusInputFileName_, std::ios::app);
463 jsonFileStream << jsonContent << std::endl;
464 jsonFileStream.close();
465 DEBUG_LOG("SegmentedWriteForFocusInput end");
466 TRACK_LOG_END();
467 }
468
HilogFileRecord()469 void Report::HilogFileRecord()
470 {
471 struct dirent *dp;
472 DIR *dirpHilog = nullptr;
473 std::shared_ptr<WuKongUtil> utilPtr = WuKongUtil::GetInstance();
474 dirpHilog = opendir(hilogDirs_.c_str());
475 if (dirpHilog == nullptr) {
476 ERROR_LOG_STR("dir{%s} opendir error", hilogDirs_.c_str());
477 return;
478 }
479 while ((dp = readdir(dirpHilog)) != NULL) {
480 std::string targetFile(dp->d_name);
481 if ((strcmp(dp->d_name, ".") != 0) && (strcmp(dp->d_name, "..") != 0)) {
482 std::vector<std::string>::iterator iterDir = find(hilogFiles_.begin(), hilogFiles_.end(), targetFile);
483 if (iterDir == hilogFiles_.end()) {
484 DEBUG_LOG("hilog copy action");
485 utilPtr->CopyFile(targetFile, hilogDirs_, reportExceptionDir_);
486 hilogFiles_.push_back(targetFile);
487 }
488 }
489 }
490 if (dirpHilog != nullptr) {
491 (void)closedir(dirpHilog);
492 }
493 }
494
ExceptionRecord(const std::string & exceptionFilename)495 void Report::ExceptionRecord(const std::string &exceptionFilename)
496 {
497 std::unique_lock<std::mutex> locker(crashMtx_);
498 std::map<std::string, std::string> data;
499 std::string exceptionType;
500 if (exceptionFilename.find("cppcrash") != std::string::npos) {
501 exceptionType = "cppcrash";
502 }
503
504 if (exceptionFilename.find("appfreeze") != std::string::npos) {
505 exceptionType = "appfreeze";
506 }
507
508 if (exceptionFilename.find("jscrash") != std::string::npos) {
509 exceptionType = "jscrash";
510 }
511
512 if (exceptionFilename.find("serviceblock") != std::string::npos) {
513 exceptionType = "serviceblock";
514 }
515
516 data["exception"] = exceptionType;
517 exceptionDataSet_->FilterData(data);
518 }
519
Finish()520 void Report::Finish()
521 {
522 SegmentedWriteCSV();
523 SegmentedWriteJson();
524 if (is_focus_) {
525 SegmentedWriteForFocusInput();
526 }
527 ExceptionManager::GetInstance()->StopCatching();
528 }
529
SetSeed(std::string seed)530 void Report::SetSeed(std::string seed)
531 {
532 seed_ = seed;
533 }
534
ComponmentInfoArrange(const std::string & bundle,std::shared_ptr<ComponmentInputMsg> inputCompMsgPtr,std::map<std::string,std::string> & data)535 void Report::ComponmentInfoArrange(const std::string &bundle, std::shared_ptr<ComponmentInputMsg> inputCompMsgPtr,
536 std::map<std::string, std::string> &data)
537 {
538 std::map<std::string, componmentRecord>::iterator bundleComponmentRecordIter;
539 componmentRecord componmentRecord;
540 bundleComponmentRecordIter = bundleComponmentRecord_.find(bundle);
541 if (bundleComponmentRecordIter != bundleComponmentRecord_.end()) {
542 componmentRecord = bundleComponmentRecordIter->second;
543 }
544 componmentRecord.pageIdComponments[inputCompMsgPtr->pageId_] = inputCompMsgPtr->pageComponments;
545 std::map<std::string, uint32_t>::iterator componmentTypeCountIter;
546 uint32_t componmentTypeInputedCount = 0;
547 uint32_t componmentTypeTotal = 0;
548 componmentTypeCountIter = componmentRecord.componmentTypeCount.find(inputCompMsgPtr->componmentType_);
549 if (componmentTypeCountIter != componmentRecord.componmentTypeCount.end()) {
550 componmentTypeInputedCount = componmentTypeCountIter->second;
551 }
552 componmentTypeInputedCount++;
553
554 for (auto pageIdComponmentsIter : componmentRecord.pageIdComponments) {
555 for (auto componmentVectorIter : pageIdComponmentsIter.second) {
556 if (componmentVectorIter.compare(inputCompMsgPtr->componmentType_) == 0) {
557 componmentTypeTotal++;
558 }
559 }
560 }
561 if (componmentTypeInputedCount > componmentTypeTotal) {
562 componmentTypeInputedCount = componmentTypeTotal;
563 }
564
565 componmentRecord.componmentTypeCount[inputCompMsgPtr->componmentType_] = componmentTypeInputedCount;
566 data["componment"] = inputCompMsgPtr->componmentType_;
567 data["inputedTimes"] = std::to_string(componmentTypeInputedCount);
568 data["componmentTotals"] = std::to_string(componmentTypeTotal);
569 DEBUG_LOG_STR("componmentType{%s} inputedTimes{%s} componmentTotals{%s}", data["componment"].c_str(),
570 data["inputedTimes"].c_str(), data["componmentTotals"].c_str());
571 bundleComponmentRecord_[bundle] = componmentRecord;
572 }
573
RecordScreenPath(const std::string & screenPath)574 void Report::RecordScreenPath(const std::string &screenPath)
575 {
576 TRACK_LOG_STD();
577 screenPaths_.push_back(screenPath);
578 TRACK_LOG_END();
579 }
580
GetReportExceptionDir()581 std::string Report::GetReportExceptionDir()
582 {
583 return reportExceptionDir_;
584 }
585 } // namespace WuKong
586 } // namespace OHOS