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
16 #include "event_export_engine.h"
17
18 #include <chrono>
19
20 #include "event_expire_task.h"
21 #include "event_export_task.h"
22 #include "ffrt.h"
23 #include "file_util.h"
24 #include "hiview_global.h"
25 #include "hiview_logger.h"
26 #include "setting_observer_manager.h"
27 #include "sys_event_sequence_mgr.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 DEFINE_LOG_TAG("HiView-EventExportEngine");
32 namespace {
33 constexpr char SYS_EVENT_EXPORT_DIR_NAME[] = "sys_event_export";
34 constexpr int REGISTER_RETRY_CNT = 100;
35 constexpr int REGISTER_LOOP_DURATION = 6;
GetExportDir(HiviewContext::DirectoryType type)36 std::string GetExportDir(HiviewContext::DirectoryType type)
37 {
38 auto& context = HiviewGlobal::GetInstance();
39 if (context == nullptr) {
40 HIVIEW_LOGW("faield to get export directory");
41 return "";
42 }
43 std::string configDir = context->GetHiViewDirectory(type);
44 return FileUtil::IncludeTrailingPathDelimiter(configDir.append(SYS_EVENT_EXPORT_DIR_NAME));
45 }
46 }
47
GetInstance()48 EventExportEngine& EventExportEngine::GetInstance()
49 {
50 static EventExportEngine instance;
51 return instance;
52 }
53
EventExportEngine()54 EventExportEngine::EventExportEngine()
55 {
56 }
57
~EventExportEngine()58 EventExportEngine::~EventExportEngine()
59 {
60 for (auto& config : configs_) {
61 SettingObserverManager::GetInstance()->UnregisterObserver(config->exportSwitchParam.name);
62 }
63 }
64
Start()65 void EventExportEngine::Start()
66 {
67 std::lock_guard<std::mutex> lock(mgrMutex_);
68 if (isTaskRunning_) {
69 HIVIEW_LOGW("tasks have been started.");
70 return;
71 }
72 isTaskRunning_ = true;
73 auto initTaskHandle = ffrt::submit_h([this] () {
74 Init();
75 }, {}, {}, ffrt::task_attr().name("dft_export_init").qos(ffrt::qos_default));
76 ffrt::submit([this] () {
77 InitAndRunTasks();
78 }, { initTaskHandle }, {}, ffrt::task_attr().name("dft_export_start").qos(ffrt::qos_default));
79 }
80
Stop()81 void EventExportEngine::Stop()
82 {
83 std::lock_guard<std::mutex> lock(mgrMutex_);
84 if (!isTaskRunning_) {
85 HIVIEW_LOGW("tasks have been stopped");
86 return;
87 }
88 isTaskRunning_ = false;
89 HIVIEW_LOGE("succeed to stop all tasks");
90 }
91
Init()92 void EventExportEngine::Init()
93 {
94 // init ExportConfigManager
95 std::string configFileStoreDir = GetExportDir(HiviewContext::DirectoryType::CONFIG_DIRECTORY);
96 HIVIEW_LOGI("directory for export config file to store: %{public}s", configFileStoreDir.c_str());
97 ExportConfigManager configMgr(configFileStoreDir);
98
99 // init ExportDbManager
100 std::string dbStoreDir = GetExportDir(HiviewContext::DirectoryType::WORK_DIRECTORY);
101 HIVIEW_LOGI("directory for export db to store: %{public}s", dbStoreDir.c_str());
102 dbMgr_ = std::make_shared<ExportDbManager>(dbStoreDir);
103
104 // build tasks for all modules
105 configMgr.GetExportConfigs(configs_);
106 HIVIEW_LOGD("count of configuration: %{public}zu", configs_.size());
107 }
108
InitAndRunTasks()109 void EventExportEngine::InitAndRunTasks()
110 {
111 HIVIEW_LOGI("total count of module is %{public}zu", configs_.size());
112 for (const auto& config : configs_) {
113 auto task = std::bind(&EventExportEngine::InitAndRunTask, this, config);
114 ffrt::submit(task, {}, {}, ffrt::task_attr().name("dft_event_export").qos(ffrt::qos_default));
115 }
116 }
117
RegistSettingObserver(std::shared_ptr<ExportConfig> config)118 bool EventExportEngine::RegistSettingObserver(std::shared_ptr<ExportConfig> config)
119 {
120 SettingObserver::ObserverCallback callback =
121 [this, &config] (const std::string& paramKey) {
122 std::string val = SettingObserverManager::GetInstance()->GetStringValue(paramKey);
123 HIVIEW_LOGI("value of param key[%{public}s] is %{public}s", paramKey.c_str(), val.c_str());
124 if (val == config->exportSwitchParam.enabledVal) {
125 HandleExportSwitchOn(config->moduleName);
126 } else {
127 HandleExportSwitchOff(config->moduleName);
128 }
129 };
130 bool regRet = false;
131 int retryCount = REGISTER_RETRY_CNT;
132 while (!regRet && retryCount > 0) {
133 regRet = SettingObserverManager::GetInstance()->RegisterObserver(config->exportSwitchParam.name,
134 callback);
135 if (regRet) {
136 break;
137 }
138 retryCount--;
139 ffrt::this_task::sleep_for(std::chrono::seconds(REGISTER_LOOP_DURATION));
140 }
141 if (!regRet) {
142 HIVIEW_LOGW("failed to regist setting db observer for module %{public}s", config->moduleName.c_str());
143 return regRet;
144 }
145 InitModuleExportInfo(config);
146 HIVIEW_LOGI("succeed to regist setting db observer for module %{public}s", config->moduleName.c_str());
147 return regRet;
148 }
149
InitModuleExportInfo(std::shared_ptr<ExportConfig> config)150 void EventExportEngine::InitModuleExportInfo(std::shared_ptr<ExportConfig> config)
151 {
152 int64_t exportEnabledSeq = dbMgr_->GetExportEnabledSeq(config->moduleName);
153 bool isExportSwitchOff = (SettingObserverManager::GetInstance()->GetStringValue(config->exportSwitchParam.name) !=
154 config->exportSwitchParam.enabledVal);
155 if (isExportSwitchOff) {
156 HIVIEW_LOGI("export switch for module %{public}s is off", config->moduleName.c_str());
157 if (exportEnabledSeq != INVALID_SEQ_VAL) { // handle setting parameter listening error
158 exportEnabledSeq = INVALID_SEQ_VAL;
159 dbMgr_->HandleExportSwitchChanged(config->moduleName, exportEnabledSeq);
160 }
161 return;
162 }
163 HIVIEW_LOGI("export switch for module %{public}s is on", config->moduleName.c_str());
164 bool needUpdateRecord = false;
165 if (exportEnabledSeq == INVALID_SEQ_VAL) { // handle setting parameter listening error
166 exportEnabledSeq = EventStore::SysEventSequenceManager::GetInstance().GetSequence();
167 needUpdateRecord = true;
168 }
169 if (dbMgr_->IsUnrecordedModule(config->moduleName)) { // first time to export event for current module
170 auto upgradeParam = config->sysUpgradeParam;
171 if (!upgradeParam.name.empty() &&
172 SettingObserverManager::GetInstance()->GetStringValue(upgradeParam.name) == upgradeParam.enabledVal) {
173 exportEnabledSeq = 0;
174 needUpdateRecord = true;
175 }
176 }
177 if (needUpdateRecord) {
178 dbMgr_->HandleExportSwitchChanged(config->moduleName, exportEnabledSeq);
179 }
180 }
181
InitAndRunTask(std::shared_ptr<ExportConfig> config)182 void EventExportEngine::InitAndRunTask(std::shared_ptr<ExportConfig> config)
183 {
184 // reg setting db observer
185 auto regRet = RegistSettingObserver(config);
186 if (!regRet) {
187 return;
188 }
189 // init tasks of current config then run them
190 auto expireTask = std::make_shared<EventExpireTask>(config, dbMgr_);
191 auto exportTask = std::make_shared<EventExportTask>(config, dbMgr_);
192 while (isTaskRunning_) {
193 expireTask->Run();
194 exportTask->Run();
195 // sleep for a task cycle
196 ffrt::this_task::sleep_for(exportTask->GetExecutingCycle());
197 }
198 }
199
HandleExportSwitchOn(const std::string & moduleName)200 void EventExportEngine::HandleExportSwitchOn(const std::string& moduleName)
201 {
202 auto curEventSeq = EventStore::SysEventSequenceManager::GetInstance().GetSequence();
203 HIVIEW_LOGI("update enabled seq:%{public}" PRId64 " for moudle %{public}s", curEventSeq, moduleName.c_str());
204 dbMgr_->HandleExportSwitchChanged(moduleName, curEventSeq);
205 }
206
HandleExportSwitchOff(const std::string & moduleName)207 void EventExportEngine::HandleExportSwitchOff(const std::string& moduleName)
208 {
209 dbMgr_->HandleExportSwitchChanged(moduleName, INVALID_SEQ_VAL);
210 }
211 } // HiviewDFX
212 } // OHOS