• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "sysevent_source.h"
17 
18 #include <functional>
19 #include <memory>
20 
21 #include "daily_controller.h"
22 #include "decoded/decoded_event.h"
23 #include "defines.h"
24 #include "file_util.h"
25 #include "focused_event_util.h"
26 #include "hiview_logger.h"
27 #include "hiview_platform.h"
28 #include "param_const_common.h"
29 #include "parameter.h"
30 #include "parameter_ex.h"
31 #include "plugin_factory.h"
32 #include "raw_data_base_def.h"
33 #include "running_status_logger.h"
34 #include "string_util.h"
35 #include "sys_event.h"
36 #include "sys_event_dao.h"
37 #include "sys_event_service_adapter.h"
38 #include "time_util.h"
39 
40 namespace OHOS {
41 namespace HiviewDFX {
42 REGISTER(SysEventSource);
43 namespace {
44 DEFINE_LOG_TAG("HiView-SysEventSource");
45 constexpr char TEST_TYPE_PARAM_KEY[] = "hiviewdfx.hiview.testtype";
46 constexpr char TEST_TYPE_KEY[] = "test_type_";
47 constexpr char SOURCE_PERIOD_CNT_ITEM_CONCATE[] = " ";
48 constexpr size_t SOURCE_PERIOD_INFO_ITEM_CNT = 3;
49 constexpr size_t PERIOD_FILE_WROTE_STEP = 100;
50 
GenerateHash(std::shared_ptr<SysEvent> event)51 uint64_t GenerateHash(std::shared_ptr<SysEvent> event)
52 {
53     if (event == nullptr) {
54         return 0;
55     }
56     constexpr size_t infoLenLimit = 256;
57     size_t infoLen = event->rawData_->GetDataLength();
58     size_t hashLen = (infoLen < infoLenLimit) ? infoLen : infoLenLimit;
59     const uint8_t* p = event->rawData_->GetData();
60     uint64_t ret { 0xCBF29CE484222325ULL }; // basis value
61     size_t i = 0;
62     while (i < hashLen) {
63         ret ^= *(p + i);
64         ret *= 0x100000001B3ULL; // prime value
65         i++;
66     }
67     return ret;
68 }
69 
ParameterWatchCallback(const char * key,const char * value,void * context)70 void ParameterWatchCallback(const char* key, const char* value, void* context)
71 {
72     if (context == nullptr) {
73         HIVIEW_LOGE("context is null");
74         return;
75     }
76     auto eventSourcePlugin = reinterpret_cast<SysEventSource*>(context);
77     if (eventSourcePlugin == nullptr) {
78         HIVIEW_LOGE("eventsource plugin is null");
79         return;
80     }
81     size_t testTypeStrMaxLen = 256;
82     std::string testTypeStr(value);
83     if (testTypeStr.size() > testTypeStrMaxLen) {
84         HIVIEW_LOGE("length of the test type string set exceeds the limit");
85         return;
86     }
87     HIVIEW_LOGI("test_type is set to be \"%{public}s\"", testTypeStr.c_str());
88     eventSourcePlugin->UpdateTestType(testTypeStr);
89 }
90 
LogEventDelayedInfo(bool & isLastEventDelayed,bool isCurEventDelayed,uint64_t happenTime,uint64_t createTime)91 void LogEventDelayedInfo(bool& isLastEventDelayed, bool isCurEventDelayed, uint64_t happenTime,
92     uint64_t createTime)
93 {
94     if (isLastEventDelayed == isCurEventDelayed) {
95         return;
96     }
97     // reset delay info of the last event by delay info of current event
98     isLastEventDelayed = isCurEventDelayed;
99     std::string info { "event delay " };
100     if (isCurEventDelayed) {
101         info.append("start;");
102     } else {
103         info.append("end;");
104     }
105     info.append("happen_time=[").append(std::to_string(happenTime)).append("]; ");
106     info.append("create_time=[").append(std::to_string(createTime)).append("]");
107     RunningStatusLogger::GetInstance().LogEventRunningLogInfo(info);
108 }
109 
CheckIfEventDelayed(bool & isLastEventDelayed,std::shared_ptr<SysEvent> event)110 void CheckIfEventDelayed(bool& isLastEventDelayed, std::shared_ptr<SysEvent> event)
111 {
112     uint64_t happenTime = event->happenTime_;
113     uint64_t createTime = event->createTime_ / 1000; // 1000: us->ms
114     if (createTime < happenTime) { // for the time jump scene
115         LogEventDelayedInfo(isLastEventDelayed, false, happenTime, createTime);
116         return;
117     }
118     constexpr uint64_t delayDetectLimit = 5 * 1000; // 5s
119     if (uint64_t delayTime = createTime - happenTime; delayTime > delayDetectLimit) {
120         HIVIEW_LOGI("event[%{public}s|%{public}s|%{public}" PRIu64 "] delayed by %{public}" PRIu64 "ms",
121             event->domain_.c_str(), event->eventName_.c_str(), happenTime, delayTime);
122         LogEventDelayedInfo(isLastEventDelayed, true, happenTime, createTime);
123         return;
124     }
125     LogEventDelayedInfo(isLastEventDelayed, false, happenTime, createTime);
126 }
127 
LogSourcePeriodInfo(std::shared_ptr<SourcePeriodInfo> info)128 void LogSourcePeriodInfo(std::shared_ptr<SourcePeriodInfo> info)
129 {
130     if (info == nullptr) {
131         HIVIEW_LOGE("info is null");
132         return;
133     }
134     std::string logInfo;
135     // append period
136     logInfo.append("period=[").append(info->timeStamp).append("]; ");
137     // append num of the event which is need to be stored;
138     logInfo.append("need_store_event_num=[").append(std::to_string(info->preserveCnt)).append("]; ");
139     // append num of the event which is need to be exported;
140     logInfo.append("need_export_event_num=[").append(std::to_string(info->exportCnt)).append("]");
141     RunningStatusLogger::GetInstance().LogEventCountStatisticInfo(logInfo);
142 }
143 }
144 
HandlerEvent(std::shared_ptr<EventRaw::RawData> rawData)145 void SysEventReceiver::HandlerEvent(std::shared_ptr<EventRaw::RawData> rawData)
146 {
147     if (rawData == nullptr || rawData->GetData() == nullptr) {
148         HIVIEW_LOGW("raw data of sys event is null");
149         return;
150     }
151     std::shared_ptr<PipelineEvent> event = std::make_shared<SysEvent>("SysEventSource",
152         static_cast<PipelineEventProducer*>(&eventSource), rawData);
153     if (eventSource.CheckEvent(event)) {
154         eventSource.PublishPipelineEvent(event);
155     }
156 }
157 
OnLoad()158 void SysEventSource::OnLoad()
159 {
160     HIVIEW_LOGI("SysEventSource load ");
161     std::shared_ptr<EventLoop> looper = GetHiviewContext()->GetSharedWorkLoop();
162     platformMonitor_.StartMonitor(looper);
163 
164     sysEventStat_ = std::make_unique<SysEventStat>();
165     InitController();
166 
167     // start sys event service
168     SysEventServiceAdapter::StartService(this);
169     SysEventServiceAdapter::SetWorkLoop(looper);
170 
171     // watch parameter
172     if (WatchParameter(TEST_TYPE_PARAM_KEY, ParameterWatchCallback, this) != 0) {
173         HIVIEW_LOGW("failed to watch the change of parameter %{public}s", TEST_TYPE_PARAM_KEY);
174     }
175 
176     periodFileOpt_ = std::make_unique<PeriodInfoFileOperator>(GetHiviewContext(), "event_source_period_count");
177     periodFileOpt_->ReadPeriodInfoFromFile(SOURCE_PERIOD_INFO_ITEM_CNT,
178         [this] (const std::vector<std::string>& infoDetails) {
179             uint64_t preserveCnt = 0;
180             StringUtil::ConvertStringTo(infoDetails[1], preserveCnt); // 1 is the index of preserve count
181             uint64_t exportCnt = 0;
182             StringUtil::ConvertStringTo(infoDetails[2], exportCnt); // 2 is the index of export count
183             periodInfoList_.emplace_back(std::make_shared<SourcePeriodInfo>(infoDetails[0], preserveCnt,
184                 exportCnt));
185         });
186 }
187 
InitController()188 void SysEventSource::InitController()
189 {
190     auto context = GetHiviewContext();
191     if (context == nullptr) {
192         HIVIEW_LOGW("context is null");
193         return;
194     }
195 
196     std::string workPath = context->GetHiViewDirectory(HiviewContext::DirectoryType::WORK_DIRECTORY);
197     std::string configPath = context->GetHiViewDirectory(HiviewContext::DirectoryType::CONFIG_DIRECTORY);
198     const std::string configFileName = "event_threshold.json";
199     controller_ = std::make_unique<DailyController>(workPath, configPath.append(configFileName));
200 }
201 
OnUnload()202 void SysEventSource::OnUnload()
203 {
204     eventServer_.Stop();
205     HIVIEW_LOGI("SysEventSource unload");
206 }
207 
StartEventSource()208 void SysEventSource::StartEventSource()
209 {
210     HIVIEW_LOGI("SysEventSource start");
211     EventJsonParser::GetInstance()->ReadDefFile();
212     std::shared_ptr<EventReceiver> sysEventReceiver = std::make_shared<SysEventReceiver>(*this);
213     eventServer_.AddReceiver(sysEventReceiver);
214     eventServer_.Start();
215 }
216 
Recycle(PipelineEvent * event)217 void SysEventSource::Recycle(PipelineEvent *event)
218 {
219     platformMonitor_.CollectCostTime(event);
220 }
221 
PauseDispatch(std::weak_ptr<Plugin> plugin)222 void SysEventSource::PauseDispatch(std::weak_ptr<Plugin> plugin)
223 {
224     auto requester = plugin.lock();
225     if (requester != nullptr) {
226         HIVIEW_LOGI("process pause dispatch event from plugin:%s.\n", requester->GetName().c_str());
227     }
228 }
229 
PublishPipelineEvent(std::shared_ptr<PipelineEvent> event)230 bool SysEventSource::PublishPipelineEvent(std::shared_ptr<PipelineEvent> event)
231 {
232     platformMonitor_.CollectEvent(event);
233     platformMonitor_.Breaking();
234     auto context = GetHiviewContext();
235     HiviewPlatform* hiviewPlatform = static_cast<HiviewPlatform*>(context);
236     if (hiviewPlatform == nullptr) {
237         HIVIEW_LOGW("hiviewPlatform is null");
238         return false;
239     }
240     auto const &pipelineRules = hiviewPlatform->GetPipelineConfigMap();
241     auto const &pipelineMap = hiviewPlatform->GetPipelineMap();
242     for (auto it = pipelineRules.begin(); it != pipelineRules.end(); it++) {
243         std::string pipelineName = it->first;
244         auto dispathRule = it->second;
245         if (dispathRule->FindEvent(event->domain_, event->eventName_)) {
246             pipelineMap.at(pipelineName)->ProcessEvent(event);
247             return true;
248         }
249     }
250     pipelineMap.at("SysEventPipeline")->ProcessEvent(event);
251     return true;
252 }
253 
CheckEvent(std::shared_ptr<Event> event)254 bool SysEventSource::CheckEvent(std::shared_ptr<Event> event)
255 {
256     if (isConfigUpdated_) {
257         EventJsonParser::GetInstance()->OnConfigUpdate();
258         isConfigUpdated_.store(false);
259     }
260     std::shared_ptr<SysEvent> sysEvent = Convert2SysEvent(event);
261     if (sysEvent == nullptr) {
262         HIVIEW_LOGE("event or event parser is null.");
263         sysEventStat_->AccumulateEvent(false);
264         return false;
265     }
266     CheckIfEventDelayed(isLastEventDelayed_, sysEvent);
267     if (controller_ != nullptr && !controller_->CheckThreshold(sysEvent)) {
268         sysEventStat_->AccumulateEvent(false);
269         return false;
270     }
271     if (!IsValidSysEvent(sysEvent)) {
272         sysEventStat_->AccumulateEvent(sysEvent->domain_, sysEvent->eventName_, false);
273         return false;
274     }
275     if (FocusedEventUtil::IsFocusedEvent(sysEvent->domain_, sysEvent->eventName_)) {
276         HIVIEW_LOGI("event[%{public}s|%{public}s|%{public}" PRIu64 "] is valid.",
277             sysEvent->domain_.c_str(), sysEvent->eventName_.c_str(), event->happenTime_);
278     } else {
279         HIVIEW_LOGD("event[%{public}s|%{public}s|%{public}" PRIu64 "] is valid.",
280             sysEvent->domain_.c_str(), sysEvent->eventName_.c_str(), event->happenTime_);
281     }
282     StatisticSourcePeriodInfo(sysEvent);
283     sysEventStat_->AccumulateEvent();
284     return true;
285 }
286 
Convert2SysEvent(std::shared_ptr<Event> & event)287 std::shared_ptr<SysEvent> SysEventSource::Convert2SysEvent(std::shared_ptr<Event>& event)
288 {
289     if (event == nullptr) {
290         HIVIEW_LOGE("event is null");
291         return nullptr;
292     }
293     if (event->messageType_ != Event::MessageType::SYS_EVENT) {
294         HIVIEW_LOGE("receive out of sys event type");
295         return nullptr;
296     }
297     return Event::DownCastTo<SysEvent>(event);
298 }
299 
ShowUsage(int fd,const std::vector<std::string> & cmds)300 static void ShowUsage(int fd, const std::vector<std::string>& cmds)
301 {
302     dprintf(fd, "invalid cmd:");
303     for (auto it = cmds.begin(); it != cmds.end(); it++) {
304         dprintf(fd, "%s ", it->c_str());
305     }
306     dprintf(fd, "\n");
307     dprintf(fd, "usage: SysEventService [sum|detail|invalid|clear]\n");
308 }
309 
Dump(int fd,const std::vector<std::string> & cmds)310 void SysEventSource::Dump(int fd, const std::vector<std::string>& cmds)
311 {
312     if (cmds.size() >= 2) { // 2: args from the second item
313         std::string arg1 = cmds[1];
314         if (arg1 == "sum") {
315             sysEventStat_->StatSummary(fd);
316         } else if (arg1 == "detail") {
317             sysEventStat_->StatDetail(fd);
318         } else if (arg1 == "invalid") {
319             sysEventStat_->StatInvalidDetail(fd);
320         } else if (arg1 == "clear") {
321             sysEventStat_->Clear(fd);
322         } else {
323             ShowUsage(fd, cmds);
324         }
325     } else {
326         sysEventStat_->StatSummary(fd);
327     }
328 }
329 
OnConfigUpdate(const std::string & localCfgPath,const std::string & cloudCfgPath)330 void SysEventSource::OnConfigUpdate(const std::string& localCfgPath, const std::string& cloudCfgPath)
331 {
332     this->isConfigUpdated_.store(true);
333 }
334 
IsValidSysEvent(const std::shared_ptr<SysEvent> event)335 bool SysEventSource::IsValidSysEvent(const std::shared_ptr<SysEvent> event)
336 {
337     if (event->domain_.empty() || event->eventName_.empty()) {
338         HIVIEW_LOGW("domain=%{public}s or name=%{public}s is empty.",
339             event->domain_.c_str(), event->eventName_.c_str());
340         return false;
341     }
342     auto baseInfo = EventJsonParser::GetInstance()->GetDefinedBaseInfoByDomainName(event->domain_, event->eventName_);
343     if (baseInfo.keyConfig.type == INVALID_EVENT_TYPE) {
344         HIVIEW_LOGW("type defined for event[%{public}s|%{public}s|%{public}" PRIu64 "] invalid, or privacy dismatch.",
345             event->domain_.c_str(), event->eventName_.c_str(), event->happenTime_);
346         return false;
347     }
348     if (event->GetEventType() != baseInfo.keyConfig.type) {
349         HIVIEW_LOGW("type=%{public}d of event[%{public}s|%{public}s|%{public}" PRIu64 "] is invalid.",
350             event->GetEventType(), event->domain_.c_str(), event->eventName_.c_str(), event->happenTime_);
351         return false;
352     }
353     // append id
354     auto eventId = GenerateHash(event);
355     if (IsDuplicateEvent(eventId)) {
356         HIVIEW_LOGW("ignore duplicate event[%{public}s|%{public}s|%{public}" PRIu64 "].",
357             event->domain_.c_str(), event->eventName_.c_str(), eventId);
358         return false;
359     }
360     DecorateSysEvent(event, baseInfo, eventId);
361     return true;
362 }
363 
UpdateTestType(const std::string & testType)364 void SysEventSource::UpdateTestType(const std::string& testType)
365 {
366     testType_ = testType;
367 }
368 
DecorateSysEvent(const std::shared_ptr<SysEvent> event,const BaseInfo & baseInfo,uint64_t id)369 void SysEventSource::DecorateSysEvent(const std::shared_ptr<SysEvent> event, const BaseInfo& baseInfo, uint64_t id)
370 {
371     if (!baseInfo.level.empty()) {
372         event->SetLevel(baseInfo.level);
373     }
374     if (!baseInfo.tag.empty()) {
375         event->SetTag(baseInfo.tag);
376     }
377     event->SetPrivacy(baseInfo.keyConfig.privacy);
378     if (!testType_.empty()) {
379         event->SetEventValue(TEST_TYPE_KEY, testType_);
380     }
381     event->preserve_ = baseInfo.keyConfig.preserve;
382     event->collect_ = baseInfo.keyConfig.collect;
383     // add hashcode id
384     event->SetId(id);
385     event->SetInvalidParams(baseInfo.disallowParams);
386 }
387 
IsDuplicateEvent(const uint64_t eventId)388 bool SysEventSource::IsDuplicateEvent(const uint64_t eventId)
389 {
390     for (auto iter = eventIdList_.rbegin(); iter != eventIdList_.rend(); ++iter) {
391         if (*iter == eventId) {
392             return true;
393         }
394     }
395     std::list<uint64_t>::size_type maxSize { 25 }; // size of queue limit to 25
396     if (eventIdList_.size() >= maxSize) {
397         eventIdList_.pop_front();
398     }
399     eventIdList_.emplace_back(eventId);
400     return false;
401 }
402 
GetEventExportConfigFilePath()403 std::string SysEventSource::GetEventExportConfigFilePath()
404 {
405     auto context = GetHiviewContext();
406     if (context == nullptr) {
407         HIVIEW_LOGW("context is null");
408         return "";
409     }
410     std::string configPath = context->GetHiViewDirectory(HiviewContext::DirectoryType::CONFIG_DIRECTORY);
411     return configPath.append("hiviewx_events.json");
412 }
413 
StatisticSourcePeriodInfo(const std::shared_ptr<SysEvent> event)414 void SysEventSource::StatisticSourcePeriodInfo(const std::shared_ptr<SysEvent> event)
415 {
416     if (!Parameter::IsBetaVersion()) {
417         return;
418     }
419     auto curTimeStamp = TimeUtil::TimestampFormatToDate(TimeUtil::GetSeconds(), "%Y%m%d%H");
420     std::shared_ptr<SourcePeriodInfo> recentPeriodInfo = nullptr;
421     if (!periodInfoList_.empty()) {
422         recentPeriodInfo = periodInfoList_.back();
423     }
424     EventPeriodSeqInfo eventPeriodSeqInfo;
425     eventPeriodSeqInfo.timeStamp = curTimeStamp;
426     if (recentPeriodInfo != nullptr && recentPeriodInfo->timeStamp == curTimeStamp) {
427         periodSeq_++;
428         eventPeriodSeqInfo.periodSeq = periodSeq_;
429         if (event->collect_) {
430             ++(recentPeriodInfo->exportCnt);
431             eventPeriodSeqInfo.isNeedExport = true;
432         }
433         if (event->preserve_) {
434             ++(recentPeriodInfo->preserveCnt);
435         }
436         event->SetEventPeriodSeqInfo(eventPeriodSeqInfo);
437         RecordSourcePeriodInfo();
438         return;
439     }
440 
441     // clear and log historical info
442     while (!periodInfoList_.empty()) {
443         auto infoItem = periodInfoList_.front();
444         LogSourcePeriodInfo(infoItem);
445         periodInfoList_.pop_front();
446     }
447 
448     periodSeq_ = DEFAULT_PERIOD_SEQ;
449     eventPeriodSeqInfo.isNeedExport = event->collect_;
450     eventPeriodSeqInfo.periodSeq = periodSeq_;
451     event->SetEventPeriodSeqInfo(eventPeriodSeqInfo);
452     recentPeriodInfo = std::make_shared<SourcePeriodInfo>(curTimeStamp, static_cast<uint64_t>(event->preserve_),
453         static_cast<uint64_t>(event->collect_));
454     periodInfoList_.emplace_back(recentPeriodInfo);
455     RecordSourcePeriodInfo();
456 }
457 
RecordSourcePeriodInfo()458 void SysEventSource::RecordSourcePeriodInfo()
459 {
460     periodFileOpt_->WritePeriodInfoToFile([this] () {
461         std::string periodInfoContent;
462         for (const auto& periodInfo : periodInfoList_) {
463             if (periodInfo == nullptr) {
464                 HIVIEW_LOGE("event source info item is null");
465                 continue;
466             }
467             periodInfoContent.append(periodInfo->timeStamp).append(SOURCE_PERIOD_CNT_ITEM_CONCATE);
468             periodInfoContent.append(std::to_string(periodInfo->preserveCnt)).append(SOURCE_PERIOD_CNT_ITEM_CONCATE);
469             periodInfoContent.append(std::to_string(periodInfo->exportCnt)).append("\n");
470         }
471         return periodInfoContent;
472     });
473 }
474 } // namespace HiviewDFX
475 } // namespace OHOS
476