1 /*
2 * Copyright (c) 2023-2025 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 <charconv>
16 #include <sys/stat.h>
17 #include <set>
18
19 #include "app_caller_event.h"
20 #include "app_event_task_storage.h"
21 #include "file_util.h"
22 #include "hiview_logger.h"
23 #include "time_util.h"
24 #include "trace_common.h"
25 #include "trace_flow_controller.h"
26 #include "trace_db_callback.h"
27
28 using namespace OHOS::HiviewDFX;
29
30 namespace OHOS {
31 namespace HiviewDFX {
32 namespace {
33 DEFINE_LOG_TAG("TraceFlowController");
34 constexpr int32_t DB_VERSION = 6;
35 constexpr char DB_NAME[] = "trace_flow_control.db";
36 constexpr int32_t HITRACE_CACHE_DURATION_LIMIT_DAILY_TOTAL = 10 * 60; // 10 minutes
37 const std::set<std::string> DB_CALLER {
38 CallerName::XPERF, CallerName::XPOWER, CallerName::RELIABILITY, CallerName::HIVIEW
39 };
40 }
41
InitTraceDb(const std::string & dbPath)42 void TraceFlowController::InitTraceDb(const std::string& dbPath)
43 {
44 NativeRdb::RdbStoreConfig config(dbPath + DB_NAME);
45 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
46 TraceDbStoreCallback callback;
47 auto ret = NativeRdb::E_OK;
48 dbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, DB_VERSION, callback, ret);
49 if (ret != NativeRdb::E_OK) {
50 HIVIEW_LOGE("failed to init db store, db store path=%{public}s", dbPath.c_str());
51 dbStore_ = nullptr;
52 return;
53 }
54 }
55
InitTraceStorage(const std::string & caller,const std::string & configPath)56 void TraceFlowController::InitTraceStorage(const std::string& caller, const std::string& configPath)
57 {
58 if (dbStore_ == nullptr) {
59 HIVIEW_LOGE("dbStore fail init");
60 return;
61 }
62 if (DB_CALLER.find(caller) != DB_CALLER.end()) {
63 HIVIEW_LOGD("is db caller, init TraceStorage");
64 traceStorage_ = std::make_shared<TraceStorage>(dbStore_, caller, configPath);
65 }
66 if (caller == ClientName::APP) {
67 appTaskStore_ = std::make_shared<AppEventTaskStorage>(dbStore_);
68 }
69 if (caller == BusinessName::BEHAVIOR) {
70 behaviorTaskStore_ = std::make_shared<TraceBehaviorStorage>(dbStore_);
71 }
72 if (caller == BusinessName::TELEMETRY) {
73 teleMetryStorage_ = std::make_shared<TeleMetryStorage>(dbStore_);
74 }
75 }
76
TraceFlowController(const std::string & caller,const std::string & dbPath,const std::string & configPath)77 TraceFlowController::TraceFlowController(const std::string& caller, const std::string& dbPath,
78 const std::string& configPath)
79 {
80 InitTraceDb(dbPath);
81 InitTraceStorage(caller, configPath);
82 }
83
GetRemainingTraceSize()84 int64_t TraceFlowController::GetRemainingTraceSize()
85 {
86 if (traceStorage_ == nullptr) {
87 return 0;
88 }
89 return traceStorage_->GetRemainingTraceSize();
90 }
91
StoreDb(int64_t traceSize)92 void TraceFlowController::StoreDb(int64_t traceSize)
93 {
94 if (traceStorage_ == nullptr) {
95 return;
96 }
97 traceStorage_->StoreDb(traceSize);
98 }
99
IsOverLimit()100 bool TraceFlowController::IsOverLimit()
101 {
102 if (traceStorage_ == nullptr) {
103 return true;
104 }
105 return traceStorage_->IsOverLimit();
106 }
107
DecreaseDynamicThreshold()108 void TraceFlowController::DecreaseDynamicThreshold()
109 {
110 if (traceStorage_ == nullptr) {
111 return;
112 }
113 traceStorage_->DecreaseDynamicThreshold();
114 }
115
HasCallOnceToday(int32_t uid,uint64_t happenTime)116 bool TraceFlowController::HasCallOnceToday(int32_t uid, uint64_t happenTime)
117 {
118 if (appTaskStore_ == nullptr) {
119 return true;
120 }
121 uint64_t happenTimeInSecond = happenTime / TimeUtil::SEC_TO_MILLISEC;
122 std::string date = TimeUtil::TimestampFormatToDate(happenTimeInSecond, "%Y%m%d");
123
124 AppEventTask appEventTask;
125 appEventTask.id_ = 0;
126 int32_t dateNum = 0;
127 auto result = std::from_chars(date.c_str(), date.c_str() + date.size(), dateNum);
128 if (result.ec != std::errc()) {
129 HIVIEW_LOGW("convert error, dateStr: %{public}s", date.c_str());
130 return true;
131 }
132 HIVIEW_LOGD("Query appEventTask where uid:%{public}d, dateNum:%{public}d", uid, dateNum);
133 appTaskStore_->GetAppEventTask(uid, dateNum, appEventTask);
134 return appEventTask.id_ > 0;
135 }
136
RecordCaller(std::shared_ptr<AppCallerEvent> appEvent)137 bool TraceFlowController::RecordCaller(std::shared_ptr<AppCallerEvent> appEvent)
138 {
139 if (appTaskStore_ == nullptr) {
140 return false;
141 }
142 uint64_t happenTimeInSecond = appEvent->happenTime_ / TimeUtil::SEC_TO_MILLISEC;
143 std::string date = TimeUtil::TimestampFormatToDate(happenTimeInSecond, "%Y%m%d");
144 int64_t dateNum = 0;
145 auto result = std::from_chars(date.c_str(), date.c_str() + date.size(), dateNum);
146 if (result.ec != std::errc()) {
147 HIVIEW_LOGW("convert error, dateStr: %{public}s", date.c_str());
148 return false;
149 }
150 AppEventTask appEventTask;
151 appEventTask.taskDate_ = dateNum;
152 appEventTask.taskType_ = APP_EVENT_TASK_TYPE_JANK_EVENT;
153 appEventTask.uid_ = appEvent->uid_;
154 appEventTask.pid_ = appEvent->pid_;
155 appEventTask.bundleName_ = appEvent->bundleName_;
156 appEventTask.bundleVersion_ = appEvent->bundleVersion_;
157 appEventTask.startTime_ = appEvent->taskBeginTime_;
158 appEventTask.finishTime_ = appEvent->taskEndTime_;
159 appEventTask.resourePath_ = appEvent->externalLog_;
160 appEventTask.resourceSize_ = static_cast<int32_t>(FileUtil::GetFileSize(appEventTask.resourePath_));
161 appEventTask.state_ = APP_EVENT_TASK_STATE_FINISH;
162 return appTaskStore_->InsertAppEventTask(appEventTask);
163 }
164
CleanOldAppTrace(int32_t dateNum)165 void TraceFlowController::CleanOldAppTrace(int32_t dateNum)
166 {
167 if (appTaskStore_ == nullptr) {
168 return;
169 }
170 appTaskStore_->RemoveAppEventTask(dateNum);
171 }
172
UseCacheTimeQuota(int32_t interval)173 CacheFlow TraceFlowController::UseCacheTimeQuota(int32_t interval)
174 {
175 if (behaviorTaskStore_ == nullptr) {
176 return CacheFlow::EXIT;
177 }
178 BehaviorRecord record;
179 record.behaviorId = CACHE_LOW_MEM;
180 record.dateNum = TimeUtil::TimestampFormatToDate(TimeUtil::GetSeconds(), "%Y%m%d");
181 if (!behaviorTaskStore_->GetRecord(record) && !behaviorTaskStore_->InsertRecord(record)) {
182 HIVIEW_LOGE("failed to get and insert record, close task");
183 return CacheFlow::EXIT;
184 }
185 HIVIEW_LOGD("get used quota:%{public}d", record.usedQuota);
186 if (record.usedQuota >= HITRACE_CACHE_DURATION_LIMIT_DAILY_TOTAL) {
187 HIVIEW_LOGW("usedQuota exceeds daily limit. usedQuota:%{public}d", record.usedQuota);
188 return CacheFlow::OVER_FLOW;
189 }
190 record.usedQuota += interval;
191 behaviorTaskStore_->UpdateRecord(record);
192 return CacheFlow::SUCCESS;
193 }
194
InitTelemetryData(const std::string & telemetryId,int64_t & runningTime,const std::map<std::string,int64_t> & flowControlQuotas)195 TelemetryRet TraceFlowController::InitTelemetryData(const std::string &telemetryId, int64_t &runningTime,
196 const std::map<std::string, int64_t>& flowControlQuotas)
197 {
198 if (teleMetryStorage_ == nullptr) {
199 HIVIEW_LOGE("failed to init teleMetryStorage");
200 return TelemetryRet::EXIT;
201 }
202 return teleMetryStorage_->InitTelemetryControl(telemetryId, runningTime, flowControlQuotas);
203 }
204
NeedTelemetryDump(const std::string & module)205 TelemetryRet TraceFlowController::NeedTelemetryDump(const std::string &module)
206 {
207 if (teleMetryStorage_ == nullptr) {
208 HIVIEW_LOGE("failed to init teleMetryStorage, close task");
209 return TelemetryRet::EXIT;
210 }
211 return teleMetryStorage_->NeedTelemetryDump(module);
212 }
213
TelemetryStore(const std::string & module,int64_t zipTraceSize)214 void TraceFlowController::TelemetryStore(const std::string &module, int64_t zipTraceSize)
215 {
216 if (teleMetryStorage_ == nullptr) {
217 HIVIEW_LOGE("failed to init teleMetryStorage, close task");
218 return;
219 }
220 return teleMetryStorage_->TelemetryStore(module, zipTraceSize);
221 }
222
ClearTelemetryData()223 void TraceFlowController::ClearTelemetryData()
224 {
225 if (teleMetryStorage_ == nullptr) {
226 HIVIEW_LOGE("failed to init teleMetryStorage, return");
227 return;
228 }
229 return teleMetryStorage_->ClearTelemetryData();
230 }
231
QueryRunningTime(int64_t & runningTime)232 bool TraceFlowController::QueryRunningTime(int64_t &runningTime)
233 {
234 if (teleMetryStorage_ == nullptr) {
235 HIVIEW_LOGE("failed to QueryTraceOnTime, return");
236 return false;
237 }
238 return teleMetryStorage_->QueryRunningTime(runningTime);
239 }
240
UpdateRunningTime(int64_t runningTime)241 bool TraceFlowController::UpdateRunningTime(int64_t runningTime)
242 {
243 if (teleMetryStorage_ == nullptr) {
244 HIVIEW_LOGE("failed to UpdateTraceOnTime, return");
245 return false;
246 }
247 return teleMetryStorage_->UpdateRunningTime(runningTime);
248 }
249 } // HiViewDFX
250 } // OHOS
251