1 /*
2 * Copyright (c) 2021-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
16 #include "sys_event_store.h"
17
18 #include <cstdio>
19 #include <memory>
20
21 #include "event.h"
22 #include "event_export_engine.h"
23 #include "file_util.h"
24 #include "focused_event_util.h"
25 #include "hiview_global.h"
26 #include "hiview_logger.h"
27 #include "hiview_platform.h"
28 #include "running_status_logger.h"
29 #include "parameter_ex.h"
30 #include "plugin_factory.h"
31 #include "string_util.h"
32 #include "sys_event.h"
33 #include "sys_event_dao.h"
34 #include "sys_event_db_mgr.h"
35 #include "sys_event_sequence_mgr.h"
36 #include "time_util.h"
37
38 namespace OHOS {
39 namespace HiviewDFX {
40 namespace {
41 REGISTER(SysEventStore);
42 DEFINE_LOG_TAG("HiView-SysEventStore");
43 const std::string PROP_LAST_BACKUP = "persist.hiviewdfx.priv.sysevent.backup_time";
44 constexpr int TWO_HOURS_OFFSET = -2;
45 constexpr size_t EVENT_STORE_INFO_DEFAULT_CNT = 1;
46 constexpr char STORE_PERIOD_CNT_ITEM_CONCATE[] = " ";
47 constexpr size_t STORE_PERIOD_INFO_ITEM_CNT = 2;
48 constexpr size_t PERIOD_FILE_WROTE_STEP = 100;
49
LogStorePeriodInfo(std::shared_ptr<StorePeriodInfo> info)50 void LogStorePeriodInfo(std::shared_ptr<StorePeriodInfo> info)
51 {
52 std::string logInfo;
53 // append period
54 logInfo.append("period=[").append(info->timeStamp).append("]; ");
55 // append num of the event which has been stored;
56 logInfo.append("stored_event_num=[").append(std::to_string(info->storedCnt)).append("]");
57 RunningStatusLogger::GetInstance().LogEventCountStatisticInfo(logInfo);
58 }
59 }
60
SysEventStore()61 SysEventStore::SysEventStore() : hasLoaded_(false)
62 {
63 sysEventDbMgr_ = std::make_unique<SysEventDbMgr>();
64 }
65
OnLoad()66 void SysEventStore::OnLoad()
67 {
68 HIVIEW_LOGI("sys event service load");
69 sysEventDbMgr_->StartCheckStoreTask(this->workLoop_);
70
71 lastBackupTime_ = Parameter::GetString(PROP_LAST_BACKUP, "");
72 // pack id must be initialized as soon as event store plugin has been loaded
73 EventExportEngine::InitPackId();
74 hasLoaded_ = true;
75
76 periodFileOpt_ = std::make_unique<PeriodInfoFileOperator>(GetHiviewContext(), "event_store_period_count");
77 periodFileOpt_->ReadPeriodInfoFromFile(STORE_PERIOD_INFO_ITEM_CNT,
78 [this] (const std::vector<std::string>& infoDetails) {
79 uint64_t storeCnt = 0;
80 StringUtil::ConvertStringTo(infoDetails[1], storeCnt); // 1 is the index of store count
81 periodInfoList_.emplace_back(std::make_shared<StorePeriodInfo>(infoDetails[0], storeCnt));
82 });
83 }
84
OnUnload()85 void SysEventStore::OnUnload()
86 {
87 HIVIEW_LOGI("sys event service unload");
88 EventExportEngine::GetInstance().Stop();
89 }
90
IsNeedBackup(const std::string & dateStr)91 bool SysEventStore::IsNeedBackup(const std::string& dateStr)
92 {
93 if (lastBackupTime_ == dateStr) {
94 return false;
95 }
96 if (lastBackupTime_.empty()) {
97 // first time boot, no need to backup
98 lastBackupTime_ = dateStr;
99 Parameter::SetProperty(PROP_LAST_BACKUP, dateStr);
100 HIVIEW_LOGI("first time boot, record backup time: %{public}s.", dateStr.c_str());
101 return false;
102 }
103 return true;
104 }
105
Convert2SysEvent(std::shared_ptr<Event> & event)106 std::shared_ptr<SysEvent> SysEventStore::Convert2SysEvent(std::shared_ptr<Event>& event)
107 {
108 if (event == nullptr) {
109 HIVIEW_LOGE("event is null");
110 return nullptr;
111 }
112 if (event->messageType_ != Event::MessageType::SYS_EVENT) {
113 HIVIEW_LOGE("receive out of sys event type");
114 return nullptr;
115 }
116 std::shared_ptr<SysEvent> sysEvent = Event::DownCastTo<SysEvent>(event);
117 if (sysEvent == nullptr) {
118 HIVIEW_LOGE("sysevent is null");
119 }
120 return sysEvent;
121 }
122
OnEvent(std::shared_ptr<Event> & event)123 bool SysEventStore::OnEvent(std::shared_ptr<Event>& event)
124 {
125 if (!hasLoaded_) {
126 HIVIEW_LOGE("SysEventService not ready");
127 return false;
128 }
129 // start event export engine only once time
130 std::call_once(exportEngineStartFlag_, [] () {
131 EventExportEngine::GetInstance().Start();
132 });
133
134 std::shared_ptr<SysEvent> sysEvent = Convert2SysEvent(event);
135 if (sysEvent != nullptr && sysEvent->preserve_) {
136 // add seq to sys event and save it to local file
137 int64_t eventSeq = EventStore::SysEventSequenceManager::GetInstance().GetSequence();
138 sysEvent->SetEventSeq(eventSeq);
139 sysEvent->SetEventValue("period_seq_", sysEvent->GetValue("period_seq_"));
140 if (FocusedEventUtil::IsFocusedEvent(sysEvent->domain_, sysEvent->eventName_)) {
141 HIVIEW_LOGI("event[%{public}s|%{public}s|%{public}" PRId64 "] is valid.",
142 sysEvent->domain_.c_str(), sysEvent->eventName_.c_str(), eventSeq);
143 }
144 EventStore::SysEventSequenceManager::GetInstance().SetSequence(++eventSeq);
145 sysEventDbMgr_->SaveToStore(sysEvent);
146
147 if (!Parameter::IsOversea()) {
148 std::string dateStr(TimeUtil::TimestampFormatToDate(TimeUtil::GetSeconds(), "%Y%m%d"));
149 if (IsNeedBackup(dateStr)) {
150 EventStore::SysEventDao::Backup();
151 lastBackupTime_ = dateStr;
152 Parameter::SetProperty(PROP_LAST_BACKUP, dateStr);
153 }
154 }
155 StatisticStorePeriodInfo(sysEvent);
156 }
157 return true;
158 }
159
StatisticStorePeriodInfo(const std::shared_ptr<SysEvent> event)160 void SysEventStore::StatisticStorePeriodInfo(const std::shared_ptr<SysEvent> event)
161 {
162 if (!Parameter::IsBetaVersion()) {
163 return;
164 }
165 auto eventPeriodTimeStamp = event->GetEventPeriodSeqInfo().timeStamp;
166 HIVIEW_LOGD("current formatted hour is %{public}s", eventPeriodTimeStamp.c_str());
167 if (eventPeriodTimeStamp.empty()) {
168 HIVIEW_LOGW("time stamp of current event period sequence is empty");
169 return;
170 }
171 std::shared_ptr<StorePeriodInfo> recentPeriodInfo = nullptr;
172 for (auto iter = periodInfoList_.crbegin(); iter != periodInfoList_.crend(); ++iter) {
173 auto storeInfoItem = *iter;
174 if (storeInfoItem->timeStamp == eventPeriodTimeStamp) {
175 recentPeriodInfo = storeInfoItem;
176 break;
177 }
178 }
179 if (recentPeriodInfo != nullptr) {
180 ++(recentPeriodInfo->storedCnt);
181 RecordStorePeriodInfo();
182 return;
183 }
184
185 time_t baseTimeStamp = TimeUtil::StrToTimeStamp(eventPeriodTimeStamp, "%Y%m%d%H");
186 auto twoHourAgoTs = TimeUtil::TimestampFormatToDate(baseTimeStamp + TWO_HOURS_OFFSET * TimeUtil::SECONDS_PER_HOUR,
187 "%Y%m%d%H");
188 // clear and log historical info
189 while (!periodInfoList_.empty()) {
190 auto infoItem = periodInfoList_.front();
191 if (infoItem->timeStamp <= twoHourAgoTs || infoItem->timeStamp > eventPeriodTimeStamp) {
192 LogStorePeriodInfo(infoItem);
193 periodInfoList_.pop_front();
194 } else {
195 break;
196 }
197 }
198 recentPeriodInfo = std::make_shared<StorePeriodInfo>(eventPeriodTimeStamp, EVENT_STORE_INFO_DEFAULT_CNT);
199 periodInfoList_.emplace_back(recentPeriodInfo);
200 RecordStorePeriodInfo();
201 }
202
RecordStorePeriodInfo()203 void SysEventStore::RecordStorePeriodInfo()
204 {
205 periodFileOpt_->WritePeriodInfoToFile([this] () {
206 std::string periodInfoContent;
207 for (const auto& periodInfo : periodInfoList_) {
208 periodInfoContent.append(periodInfo->timeStamp).append(STORE_PERIOD_CNT_ITEM_CONCATE);
209 periodInfoContent.append(std::to_string(periodInfo->storedCnt)).append("\n");
210 }
211 return periodInfoContent;
212 });
213 }
214 } // namespace HiviewDFX
215 } // namespace OHOS
216