1 /*
2 * Copyright (c) 2024 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 "hiappevent_util.h"
16
17 #include <cinttypes>
18 #include <utility>
19
20 #include "app_event.h"
21 #include "app_event_processor_mgr.h"
22 #include "ffrt.h"
23 #include "hidebug_util.h"
24 #include "hilog/log.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN 0xD002D0A
31 #undef LOG_TAG
32 #define LOG_TAG "HIAPPEVENT_UTIL"
33
34 int64_t ApiRecordReporter::processId_ = -1;
35
InitProcessor()36 void ApiRecordReporter::InitProcessor()
37 {
38 ffrt::submit([] {
39 using namespace HiAppEvent;
40 ReportConfig config;
41 config.name = "ha_app_event";
42 config.configName = "SDK_OCG";
43 processId_ = AppEventProcessorMgr::AddProcessor(config);
44 if (processId_ < 0) {
45 HILOG_ERROR(LOG_CORE, "failed to init processor and ret: %{public}" PRId64, processId_);
46 }
47 }, {}, {});
48 }
49
GetInstance()50 SingleRecordReporter& SingleRecordReporter::GetInstance()
51 {
52 static SingleRecordReporter singleRecordReporter;
53 return singleRecordReporter;
54 }
55
ReportRecord(const std::string & apiName,int errorCode,int64_t beginTime,int64_t endTime)56 void SingleRecordReporter::ReportRecord(const std::string& apiName, int errorCode, int64_t beginTime, int64_t endTime)
57 {
58 if (processId_ < 0) {
59 return;
60 }
61 auto task = [apiName, errorCode, beginTime, endTime] {
62 HiAppEvent::Event event("api_diagnostic", "api_exec_end", HiAppEvent::BEHAVIOR);
63 event.AddParam("trans_id", std::string("transId_") + std::to_string(beginTime));
64 event.AddParam("api_name", apiName);
65 event.AddParam("sdk_name", std::string("PerformanceAnalysisKit"));
66 event.AddParam("begin_time", beginTime);
67 event.AddParam("end_time", endTime);
68 event.AddParam("result", errorCode ? 1 : 0);
69 event.AddParam("error_code", errorCode);
70 Write(event);
71 };
72 ffrt::submit(task, {}, {});
73 }
74
MultipleRecordReporter(uint32_t timeout,uint32_t limitValue)75 MultipleRecordReporter::MultipleRecordReporter(uint32_t timeout, uint32_t limitValue) : timeout_(timeout),
76 limitValue_(limitValue) {}
77
ReportRecord(const std::string & apiName,int errorCode,int64_t beginTime,int64_t endTime)78 void MultipleRecordReporter::ReportRecord(const std::string& apiName, int errorCode, int64_t beginTime, int64_t endTime)
79 {
80 if (processId_ < 0) {
81 return;
82 }
83 std::unique_lock<std::mutex> lock(mutex_);
84 records_.emplace_back(errorCode);
85 const int64_t costTime = endTime - beginTime;
86 maxCostTime_ = std::max(maxCostTime_, costTime);
87 minCostTime_ = std::min(minCostTime_, costTime);
88 totalCostTime_ += costTime;
89 constexpr int64_t secondToNanosecond = 1 * 1000 * 1000 * 1000;
90 if (records_.size() >= limitValue_ ||
91 lastReportTime_ + timeout_ * secondToNanosecond < GetElapsedNanoSecondsSinceBoot()) {
92 UploadRecordData(apiName);
93 lastReportTime_ = GetElapsedNanoSecondsSinceBoot();
94 records_.assign({});
95 minCostTime_ = std::numeric_limits<int64_t>::max();
96 maxCostTime_ = std::numeric_limits<int64_t>::min();
97 totalCostTime_ = 0;
98 }
99 }
100
UploadRecordData(const std::string & apiName) const101 void MultipleRecordReporter::UploadRecordData(const std::string& apiName) const
102 {
103 auto maxCostTime = maxCostTime_;
104 auto minCostTime = minCostTime_;
105 auto totalCostTime = totalCostTime_;
106 auto task = [apiName, records = std::move(records_), maxCostTime, minCostTime, totalCostTime] {
107 HiAppEvent::Event event("api_diagnostic", "api_called_stat_cnt", HiAppEvent::BEHAVIOR);
108 event.AddParam("api_name", apiName);
109 event.AddParam("sdk_name", std::string("PerformanceAnalysisKit"));
110 event.AddParam("call_times", static_cast<int32_t>(records.size()));
111 event.AddParam("error_code_num", records);
112 int32_t successTime = 0;
113 for (const auto& errCode : records) {
114 if (errCode == 0) {
115 successTime++;
116 }
117 }
118 event.AddParam("success_times", successTime);
119 event.AddParam("max_cost_time", maxCostTime);
120 event.AddParam("min_cost_time", minCostTime);
121 event.AddParam("total_cost_time", totalCostTime);
122 Write(event);
123 };
124 ffrt::submit(task, {}, {});
125 }
126
ApiInvokeRecorder(std::string apiName,ApiRecordReporter & reporter)127 ApiInvokeRecorder::ApiInvokeRecorder(std::string apiName, ApiRecordReporter& reporter) : apiName_(std::move(apiName)),
128 beginTime_(GetElapsedNanoSecondsSinceBoot()), reporter_(reporter) {}
129
~ApiInvokeRecorder()130 ApiInvokeRecorder::~ApiInvokeRecorder()
131 {
132 if (beginTime_ < 0) {
133 return;
134 }
135 const int64_t costTime = GetElapsedNanoSecondsSinceBoot() - beginTime_;
136 if (costTime < 0) {
137 return;
138 }
139 int64_t realEndTime = GetRealNanoSecondsTimestamp();
140 int64_t realBeginTime = realEndTime - costTime;
141 if (realBeginTime < 0 || realEndTime < 0) {
142 return;
143 }
144 constexpr int milliSecondsToNanoseconds = 1000 * 1000;
145 reporter_.ReportRecord(apiName_, errorCode_,
146 realBeginTime / milliSecondsToNanoseconds, realEndTime / milliSecondsToNanoseconds);
147 }
148
SetErrorCode(int errorCode)149 void ApiInvokeRecorder::SetErrorCode(int errorCode)
150 {
151 errorCode_ = errorCode;
152 }
153 }
154 }