• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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