• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 "daily_controller.h"
16 
17 #include <cmath>
18 
19 #include "hiview_config_util.h"
20 #include "hiview_logger.h"
21 #include "time_util.h"
22 
23 namespace OHOS {
24 namespace HiviewDFX {
25 DEFINE_LOG_TAG("DailyController");
26 namespace {
27 constexpr int32_t COUNT_OF_INIT = 1;
28 }
29 
DailyController(const std::string & workPath,const std::string & configPath)30 DailyController::DailyController(const std::string& workPath, const std::string& configPath)
31 {
32     dbHelper_ = std::make_unique<DailyDbHelper>(workPath);
33     config_ = std::make_unique<DailyConfig>(configPath);
34 }
35 
CheckThreshold(std::shared_ptr<SysEvent> event)36 bool DailyController::CheckThreshold(std::shared_ptr<SysEvent> event)
37 {
38     if (event == nullptr) {
39         HIVIEW_LOGW("event is null");
40         return false;
41     }
42 
43     // try to update cache to db and report db before checking
44     int64_t nowTime = TimeUtil::GetSeconds();
45     TryToUpdateCacheToDb(nowTime);
46     TryToReportDb(nowTime);
47 
48     // check the threshold of event
49     auto cacheKey = std::make_pair(event->domain_, event->eventName_);
50     int32_t threshold = GetThreshold(cacheKey, event->eventType_);
51     int32_t count = GetCount(cacheKey) + 1;
52 
53     // update cache and db after checking
54     UpdateCacheAndDb(cacheKey, threshold, count);
55     return config_->IsValid() ? (count <= threshold) : true;
56 }
57 
TryToUpdateCacheToDb(int64_t nowTime)58 void DailyController::TryToUpdateCacheToDb(int64_t nowTime)
59 {
60     if (CheckTimeOfCache(nowTime) || CheckSizeOfCache()) {
61         UpdateCacheToDb();
62     }
63 }
64 
CheckTimeOfCache(int64_t nowTime)65 bool DailyController::CheckTimeOfCache(int64_t nowTime)
66 {
67     static int64_t lastUpdateTime = 0;
68     if (lastUpdateTime == 0) {
69         lastUpdateTime = TimeUtil::GetSeconds();
70         return false;
71     }
72 
73     constexpr int64_t updateInterval = 600; // 10min
74     if (std::abs(nowTime - lastUpdateTime) <= updateInterval) {
75         return false;
76     }
77     lastUpdateTime = nowTime;
78     return true;
79 }
80 
CheckSizeOfCache()81 bool DailyController::CheckSizeOfCache()
82 {
83     constexpr size_t maxSizeOfCache = 1000;
84     return cache_.size() > maxSizeOfCache;
85 }
86 
UpdateCacheToDb()87 void DailyController::UpdateCacheToDb()
88 {
89     HIVIEW_LOGI("start to update cache to db, size=%{public}zu", cache_.size());
90     for (const auto& [key, value] : cache_) {
91         // means that the record has been inserted and does not need to be updated
92         if (value.count == COUNT_OF_INIT) {
93             continue;
94         }
95 
96         DailyDbHelper::EventInfo eventInfo = {
97             .domain = key.first,
98             .name = key.second,
99             .count = value.count,
100             .exceedTime = value.exceedTime,
101         };
102         if (dbHelper_->UpdateEventInfo(eventInfo) < 0) {
103             HIVIEW_LOGW("failed to update, domain=%{public}s, name=%{public}s",
104                 key.first.c_str(), key.second.c_str());
105         }
106     }
107     cache_.clear();
108 }
109 
TryToReportDb(int64_t nowTime)110 void DailyController::TryToReportDb(int64_t nowTime)
111 {
112     if (dbHelper_->NeedReport(nowTime)) {
113         UpdateCacheToDb();
114         dbHelper_->Report();
115     }
116 }
117 
GetThreshold(const CacheKey & cachekey,int32_t type)118 int32_t DailyController::GetThreshold(const CacheKey& cachekey, int32_t type)
119 {
120     if (cache_.find(cachekey) != cache_.end()) {
121         return cache_[cachekey].threshold;
122     }
123     int32_t threshold = config_->GetThreshold(cachekey.first, cachekey.second, type);
124     if (threshold < 0) {
125         HIVIEW_LOGW("failed to get threshold from config, threshold=%{public}d", threshold);
126         return 0;
127     }
128     return threshold;
129 }
130 
GetCount(const CacheKey & cachekey)131 int32_t DailyController::GetCount(const CacheKey& cachekey)
132 {
133     if (cache_.find(cachekey) != cache_.end()) {
134         return cache_[cachekey].count;
135     }
136 
137     DailyDbHelper::EventInfo eventInfo = {
138         .domain = cachekey.first,
139         .name = cachekey.second,
140     };
141     if (dbHelper_->QueryEventInfo(eventInfo) < 0) {
142         HIVIEW_LOGW("failed to query event info from db, count=%{public}d", eventInfo.count);
143         return 0;
144     }
145     return eventInfo.count;
146 }
147 
UpdateCacheAndDb(const CacheKey & cachekey,int32_t threshold,int32_t count)148 void DailyController::UpdateCacheAndDb(const CacheKey& cachekey, int32_t threshold, int32_t count)
149 {
150     // check the first time the event crosses the threshold
151     int64_t exceedTime = 0;
152     if (count == (threshold + 1)) {
153         exceedTime = TimeUtil::GetSeconds();
154         HIVIEW_LOGI("event first exceeds threshold=%{public}d, domain=%{public}s, name=%{public}s",
155             threshold, cachekey.first.c_str(), cachekey.second.c_str());
156     }
157 
158     UpdateCache(cachekey, threshold, count, exceedTime);
159     UpdateDb(cachekey, count, exceedTime);
160 }
161 
UpdateCache(const CacheKey & cachekey,int32_t threshold,int32_t count,int64_t exceedTime)162 void DailyController::UpdateCache(const CacheKey& cachekey, int32_t threshold, int32_t count, int64_t exceedTime)
163 {
164     if (cache_.find(cachekey) == cache_.end()) {
165         cache_[cachekey] = {
166             .threshold = threshold,
167             .count = count,
168             .exceedTime = exceedTime,
169         };
170         return;
171     }
172 
173     cache_[cachekey].count = count;
174     if (exceedTime != 0) {
175         cache_[cachekey].exceedTime = exceedTime;
176     }
177 }
178 
UpdateDb(const CacheKey & cachekey,int32_t count,int64_t exceedTime)179 void DailyController::UpdateDb(const CacheKey& cachekey, int32_t count, int64_t exceedTime)
180 {
181     // the record does not exist in the db, need to init the record
182     if (count == COUNT_OF_INIT) {
183         DailyDbHelper::EventInfo eventInfo = {
184             .domain = cachekey.first,
185             .name = cachekey.second,
186             .count = count,
187             .exceedTime = exceedTime,
188         };
189         if (dbHelper_->InsertEventInfo(eventInfo) < 0) {
190             HIVIEW_LOGW("failed to insert, domain=%{public}s, name=%{public}s",
191                 eventInfo.domain.c_str(), eventInfo.name.c_str());
192         }
193     }
194 }
195 
OnConfigUpdate(const std::string & configPath)196 void DailyController::OnConfigUpdate(const std::string& configPath)
197 {
198     UpdateCacheToDb();
199     config_ = std::make_unique<DailyConfig>(configPath);
200 }
201 } // namespace HiviewDFX
202 } // namespace OHOS
203