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 if (dbMgr_->IsUnrecordedModule(config->moduleName)) { // first time to export event for current module
146 auto upgradeParam = config->sysUpgradeParam;
147 if (!upgradeParam.name.empty() &&
148 SettingObserverManager::GetInstance()->GetStringValue(upgradeParam.name) == upgradeParam.enabledVal) {
149 HIVIEW_LOGI("reset enabled sequence to 0 for moudle %{public}s", config->moduleName.c_str());
150 dbMgr_->HandleExportSwitchChanged(config->moduleName, 0);
151 }
152 }
153 HIVIEW_LOGI("succeed to regist setting db observer for module %{public}s", config->moduleName.c_str());
154 return regRet;
155 }
156
InitAndRunTask(std::shared_ptr<ExportConfig> config)157 void EventExportEngine::InitAndRunTask(std::shared_ptr<ExportConfig> config)
158 {
159 // reg setting db observer
160 auto regRet = RegistSettingObserver(config);
161 if (!regRet) {
162 return;
163 }
164 // init tasks of current config then run them
165 auto expireTask = std::make_shared<EventExpireTask>(config, dbMgr_);
166 auto exportTask = std::make_shared<EventExportTask>(config, dbMgr_);
167 while (isTaskRunning_) {
168 expireTask->Run();
169 exportTask->Run();
170 // sleep for a task cycle
171 ffrt::this_task::sleep_for(exportTask->GetExecutingCycle());
172 }
173 }
174
HandleExportSwitchOn(const std::string & moduleName)175 void EventExportEngine::HandleExportSwitchOn(const std::string& moduleName)
176 {
177 int64_t enabledSeq = dbMgr_->GetExportEnabledSeq(moduleName);
178 if (enabledSeq == 0) {
179 // expport enabled sequence has been reset to 0, no need to update
180 return;
181 }
182 auto curEventSeq = EventStore::SysEventSequenceManager::GetInstance().GetSequence();
183 HIVIEW_LOGI("update enabled seq:%{public}" PRId64 " for moudle %{public}s", curEventSeq, moduleName.c_str());
184 dbMgr_->HandleExportSwitchChanged(moduleName, curEventSeq);
185 }
186
HandleExportSwitchOff(const std::string & moduleName)187 void EventExportEngine::HandleExportSwitchOff(const std::string& moduleName)
188 {
189 dbMgr_->HandleExportSwitchChanged(moduleName, INVALID_SEQ_VAL);
190 }
191 } // HiviewDFX
192 } // OHOS