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