• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_json_parser.h"
17 
18 #include <algorithm>
19 #include <cctype>
20 #include <cinttypes>
21 #include <fstream>
22 #include <map>
23 #include <cstdlib>
24 
25 #include "file_util.h"
26 #include "flat_json_parser.h"
27 #include "hiview_global.h"
28 #include "logger.h"
29 #include "parameter.h"
30 #include "sys_event_service_adapter.h"
31 
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace {
35 constexpr uint64_t PRIME = 0x100000001B3ull;
36 constexpr uint64_t BASIS = 0xCBF29CE484222325ull;
37 constexpr int INVALID_EVENT_TYPE = 0;
38 constexpr char BASE[] = "__BASE";
39 constexpr char LEVEL[] = "level";
40 constexpr char TAG[] = "tag";
41 constexpr char TYPE[] = "type";
42 constexpr char PRESERVE[] = "preserve";
43 constexpr char TEST_TYPE_PARAM_KEY[] = "persist.sys.hiview.testtype";
44 constexpr char TEST_TYPE_KEY[] = "test_type_";
45 constexpr char SEQ_PERSISTS_FILE_NAME[] = "event_sequence";
46 const std::map<std::string, uint8_t> EVENT_TYPE_MAP = {
47     {"FAULT", 1}, {"STATISTIC", 2}, {"SECURITY", 3}, {"BEHAVIOR", 4}
48 };
49 
GenerateHash(const std::string & info)50 uint64_t GenerateHash(const std::string& info)
51 {
52     uint64_t ret {BASIS};
53     const char* p = info.c_str();
54     size_t infoLen = info.size();
55     size_t infoLenLimit = 256;
56     size_t hashLen = (infoLen < infoLenLimit) ? infoLen : infoLenLimit;
57     size_t i = 0;
58     while (i < hashLen) {
59         ret ^= *(p + i);
60         ret *= PRIME;
61         i++;
62     }
63     return ret;
64 }
65 
GetConfiguredTestType(const std::string & configuredType)66 std::string GetConfiguredTestType(const std::string& configuredType)
67 {
68     std::string defaultType {""};
69     size_t maxLen = 12;
70     if (configuredType.empty() || configuredType.length() > maxLen ||
71         any_of(configuredType.cbegin(), configuredType.cend(), [] (char c) {
72             return !isalnum(c);
73         })) {
74         return defaultType;
75     }
76     return configuredType;
77 }
78 
79 static std::string testTypeConfigured;
ParameterWatchCallback(const char * key,const char * value,void * context)80 void ParameterWatchCallback(const char* key, const char* value, void* context)
81 {
82     testTypeConfigured = GetConfiguredTestType(value);
83 }
84 
ReadSysEventDefFromFile(const std::string & path,Json::Value & hiSysEventDef)85 bool ReadSysEventDefFromFile(const std::string& path, Json::Value& hiSysEventDef)
86 {
87     std::ifstream fin(path, std::ifstream::binary);
88     Json::CharReaderBuilder jsonRBuilder;
89     Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
90     JSONCPP_STRING errs;
91     return parseFromStream(jsonRBuilder, fin, &hiSysEventDef, &errs);
92 }
93 }
94 
95 DEFINE_LOG_TAG("Event-JsonParser");
96 
IsDuplicateEvent(const uint64_t sysEventId)97 bool DuplicateIdFilter::IsDuplicateEvent(const uint64_t sysEventId)
98 {
99     for (auto iter = sysEventIds.begin(); iter != sysEventIds.end(); iter++) {
100         if (*iter == sysEventId) {
101             return true;
102         }
103     }
104     FILTER_SIZE_TYPE maxSize { 5 }; // size of queue limit to 5
105     if (sysEventIds.size() >= maxSize) {
106         sysEventIds.pop_front();
107     }
108     sysEventIds.emplace_back(sysEventId);
109     return false;
110 }
111 
EventJsonParser(std::vector<std::string> & paths)112 EventJsonParser::EventJsonParser(std::vector<std::string>& paths)
113 {
114     Json::Value hiSysEventDef;
115     for (auto path : paths) {
116         if (!ReadSysEventDefFromFile(path, hiSysEventDef)) {
117             HIVIEW_LOGE("parse json file failed, please check the style of json file: %{public}s", path.c_str());
118         }
119         ParseHiSysEventDef(hiSysEventDef);
120     }
121     WatchParameterAndReadLatestSeq();
122 }
123 
WatchParameterAndReadLatestSeq()124 void EventJsonParser::WatchParameterAndReadLatestSeq()
125 {
126     if (WatchParameter(TEST_TYPE_PARAM_KEY, ParameterWatchCallback, nullptr) != 0) {
127         HIVIEW_LOGW("failed to watch the change of parameter %{public}s", TEST_TYPE_PARAM_KEY);
128     }
129     ReadSeqFromFile(curSeq_);
130 }
131 
GetTagByDomainAndName(const std::string & domain,const std::string & name) const132 std::string EventJsonParser::GetTagByDomainAndName(const std::string& domain, const std::string& name) const
133 {
134     return GetDefinedBaseInfoByDomainName(domain, name).tag;
135 }
136 
GetTypeByDomainAndName(const std::string & domain,const std::string & name) const137 int EventJsonParser::GetTypeByDomainAndName(const std::string& domain, const std::string& name) const
138 {
139     return GetDefinedBaseInfoByDomainName(domain, name).type;
140 }
141 
GetPreserveByDomainAndName(const std::string & domain,const std::string & name) const142 bool EventJsonParser::GetPreserveByDomainAndName(const std::string& domain, const std::string& name) const
143 {
144     return GetDefinedBaseInfoByDomainName(domain, name).preserve;
145 }
146 
HandleEventJson(const std::shared_ptr<SysEvent> & event)147 bool EventJsonParser::HandleEventJson(const std::shared_ptr<SysEvent>& event)
148 {
149     if (!CheckEventValidity(event)) {
150         HIVIEW_LOGI("invalid event or event with empty domain or empty name.");
151         return false;
152     }
153 
154     auto baseInfo = GetDefinedBaseInfoByDomainName(event->domain_, event->eventName_);
155     if (baseInfo.type == INVALID_EVENT_TYPE) {
156         HIVIEW_LOGI("type defined for event[%{public}s|%{public}s|%{public}" PRIu64 "] is invalid.",
157             event->domain_.c_str(), event->eventName_.c_str(), event->GetEventUintValue("time_"));
158         return false;
159     }
160     if (!CheckBaseInfoValidity(baseInfo, event)) {
161         HIVIEW_LOGI("failed to verify the base info of event[%{public}s|%{public}s|%{public}" PRIu64 "].",
162             event->domain_.c_str(), event->eventName_.c_str(), event->GetEventUintValue("time_"));
163         return false;
164     }
165 
166     auto curSysEventId = GenerateHash(event->AsJsonStr());
167     if (filter_.IsDuplicateEvent(curSysEventId)) {
168         HIVIEW_LOGI(
169             "ignore duplicate event[%{public}s|%{public}s|%{public}" PRIu64 "].", event->domain_.c_str(),
170             event->eventName_.c_str(), event->GetEventUintValue("time_"));
171         return false; // ignore duplicate sys event
172     }
173 
174     AppendExtensiveInfo(event, curSysEventId);
175     WriteSeqToFile(++curSeq_);
176 
177     return true;
178 }
179 
AppendExtensiveInfo(std::shared_ptr<SysEvent> event,const uint64_t sysEventId) const180 void EventJsonParser::AppendExtensiveInfo(std::shared_ptr<SysEvent> event, const uint64_t sysEventId) const
181 {
182     if (event == nullptr) {
183         return;
184     }
185 
186     // hash code need to add
187     event->SetId(sysEventId);
188 
189     // FreezeDetector needs to add
190     event->SetEventValue(EventStore::EventCol::INFO, "");
191 
192     // add testtype configured as system property named persist.sys.hiview.testtype
193     if (!testTypeConfigured.empty()) {
194         event->SetEventValue(TEST_TYPE_KEY, testTypeConfigured);
195     }
196 
197     // add seq to sys event and then persist it into local file
198     event->SetEventSeq(curSeq_);
199 }
200 
CheckBaseInfoValidity(const BaseInfo & baseInfo,std::shared_ptr<SysEvent> event) const201 bool EventJsonParser::CheckBaseInfoValidity(const BaseInfo& baseInfo, std::shared_ptr<SysEvent> event) const
202 {
203     if (!CheckTypeValidity(baseInfo, event)) {
204         return false;
205     }
206     if (!baseInfo.level.empty()) {
207         event->SetLevel(baseInfo.level);
208     }
209     if (!baseInfo.tag.empty()) {
210         event->SetTag(baseInfo.tag);
211     }
212     return true;
213 }
214 
CheckEventValidity(std::shared_ptr<SysEvent> event) const215 bool EventJsonParser::CheckEventValidity(std::shared_ptr<SysEvent> event) const
216 {
217     if (event == nullptr) {
218         return false;
219     }
220     return !(event->domain_.empty()) && !(event->eventName_.empty());
221 }
222 
CheckTypeValidity(const BaseInfo & baseInfo,std::shared_ptr<SysEvent> event) const223 bool EventJsonParser::CheckTypeValidity(const BaseInfo& baseInfo, std::shared_ptr<SysEvent> event) const
224 {
225     if (event == nullptr) {
226         return false;
227     }
228     HIVIEW_LOGD("base info type is %{public}d, event type is %{public}d", baseInfo.type, event->GetEventType());
229     return event->GetEventType() == baseInfo.type;
230 }
231 
GetDefinedBaseInfoByDomainName(const std::string & domain,const std::string & name) const232 BaseInfo EventJsonParser::GetDefinedBaseInfoByDomainName(const std::string& domain,
233     const std::string& name) const
234 {
235     BaseInfo baseInfo = {
236         .type = INVALID_EVENT_TYPE,
237         .level = "",
238         .tag = "",
239         .preserve = true
240     };
241     auto domainIter = hiSysEventDef_.find(domain);
242     if (domainIter == hiSysEventDef_.end()) {
243         HIVIEW_LOGD("domain named %{public}s is not defined.", domain.c_str());
244         return baseInfo;
245     }
246     auto domainNames = hiSysEventDef_.at(domain);
247     auto nameIter = domainNames.find(name);
248     if (nameIter == domainNames.end()) {
249         HIVIEW_LOGD("%{public}s is not defined in domain named %{public}s.",
250             name.c_str(), domain.c_str());
251         return baseInfo;
252     }
253     return nameIter->second;
254 }
255 
HasIntMember(const Json::Value & jsonObj,const std::string & name) const256 bool EventJsonParser::HasIntMember(const Json::Value& jsonObj, const std::string& name) const
257 {
258     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isInt();
259 }
260 
HasStringMember(const Json::Value & jsonObj,const std::string & name) const261 bool EventJsonParser::HasStringMember(const Json::Value& jsonObj, const std::string& name) const
262 {
263     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isString();
264 }
265 
HasBoolMember(const Json::Value & jsonObj,const std::string & name) const266 bool EventJsonParser::HasBoolMember(const Json::Value& jsonObj, const std::string& name) const
267 {
268     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isBool();
269 }
270 
InitEventInfoMapRef(const Json::Value & eventJson,JSON_VALUE_LOOP_HANDLER handler) const271 void EventJsonParser::InitEventInfoMapRef(const Json::Value& eventJson, JSON_VALUE_LOOP_HANDLER handler) const
272 {
273     if (!eventJson.isObject()) {
274         return;
275     }
276     auto attrList = eventJson.getMemberNames();
277     for (auto it = attrList.cbegin(); it != attrList.cend(); it++) {
278         std::string key = *it;
279         if (key.empty()) {
280             continue;
281         }
282         if (handler != nullptr) {
283             handler(key, eventJson[key]);
284         }
285     }
286 }
287 
ParseBaseConfig(const Json::Value & eventNameJson) const288 BaseInfo EventJsonParser::ParseBaseConfig(const Json::Value& eventNameJson) const
289 {
290     BaseInfo baseInfo = {
291         .type = INVALID_EVENT_TYPE,
292         .level = "",
293         .tag = "",
294         .preserve = true
295     };
296     if (!eventNameJson.isObject() || !eventNameJson[BASE].isObject()) {
297         HIVIEW_LOGD("__BASE definition is invalid.");
298         return baseInfo;
299     }
300     Json::Value baseJsonInfo = eventNameJson[BASE];
301     if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, TYPE)) {
302         HIVIEW_LOGD("type is not defined in __BASE.");
303         return baseInfo;
304     }
305     std::string typeDes = baseJsonInfo[TYPE].asString();
306     if (EVENT_TYPE_MAP.find(typeDes) == EVENT_TYPE_MAP.end()) {
307         HIVIEW_LOGD("type is defined as %{public}s, but a valid type must be FAULT, STATISTIC, SECURITY, or BEHAVIOR",
308             typeDes.c_str());
309         return baseInfo;
310     }
311     baseInfo.type = EVENT_TYPE_MAP.at(typeDes);
312     if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, LEVEL)) {
313         HIVIEW_LOGD("level is not defined in __BASE.");
314         return baseInfo;
315     }
316     baseInfo.level = baseJsonInfo[LEVEL].asString();
317     if (baseJsonInfo.isObject() && HasStringMember(baseJsonInfo, TAG)) {
318         baseInfo.tag = baseJsonInfo[TAG].asString();
319     }
320     if (baseJsonInfo.isObject() && HasBoolMember(baseJsonInfo, PRESERVE)) {
321         baseInfo.preserve = baseJsonInfo[PRESERVE].asBool();
322         return baseInfo;
323     }
324     return baseInfo;
325 }
326 
ParseHiSysEventDef(const Json::Value & hiSysEventDef)327 void EventJsonParser::ParseHiSysEventDef(const Json::Value& hiSysEventDef)
328 {
329     InitEventInfoMapRef(hiSysEventDef, [this] (const std::string& key, const Json::Value& value) {
330        hiSysEventDef_[key] = ParseNameConfig(value);
331     });
332 }
333 
ParseNameConfig(const Json::Value & domainJson) const334 NAME_INFO_MAP EventJsonParser::ParseNameConfig(const Json::Value& domainJson) const
335 {
336     NAME_INFO_MAP allNames;
337     if (!domainJson.isObject()) {
338         return allNames;
339     }
340     InitEventInfoMapRef(domainJson, [this, &allNames] (const std::string& key, const Json::Value& value) {
341         allNames[key] = ParseBaseConfig(value);
342     });
343     return allNames;
344 }
345 
GetSequenceFile() const346 std::string EventJsonParser::GetSequenceFile() const
347 {
348     std::string workPath = HiviewGlobal::GetInstance()->GetHiViewDirectory(
349         HiviewContext::DirectoryType::WORK_DIRECTORY);
350     if (workPath.back() != '/') {
351         workPath = workPath + "/";
352     }
353     return workPath + "sys_event_db/" + SEQ_PERSISTS_FILE_NAME;
354 }
355 
ReadSeqFromFile(int64_t & seq)356 void EventJsonParser::ReadSeqFromFile(int64_t& seq)
357 {
358     std::string content;
359     std::string seqFile = GetSequenceFile();
360     if (!FileUtil::LoadStringFromFile(seqFile, content) && !content.empty()) {
361         HIVIEW_LOGE("failed to read sequence value from %{public}s.", seqFile.c_str());
362         return;
363     }
364     seq = static_cast<int64_t>(strtoll(content.c_str(), nullptr, 0));
365     HIVIEW_LOGI("read max sequence from local file successful, value is %{public}" PRId64 ".", seq);
366     SysEventServiceAdapter::UpdateEventSeq(seq);
367 }
368 
WriteSeqToFile(int64_t seq) const369 void EventJsonParser::WriteSeqToFile(int64_t seq) const
370 {
371     std::string seqFile = GetSequenceFile();
372     std::string content = std::to_string(seq);
373     if (!SaveStringToFile(seqFile, content)) {
374         HIVIEW_LOGE("failed to write sequence %{public}s to %{public}s.", content.c_str(), seqFile.c_str());
375     }
376     SysEventServiceAdapter::UpdateEventSeq(seq);
377 }
378 
SaveStringToFile(const std::string & filePath,const std::string & content) const379 bool EventJsonParser::SaveStringToFile(const std::string& filePath, const std::string& content) const
380 {
381     std::ofstream file;
382     file.open(filePath.c_str(), std::ios::in | std::ios::out);
383     if (!file.is_open()) {
384         file.open(filePath.c_str(), std::ios::out);
385         if (!file.is_open()) {
386             return false;
387         }
388     }
389     file.seekp(0);
390     file.write(content.c_str(), content.length() + 1);
391     bool ret = true;
392     if (file.fail()) {
393         ret = false;
394     }
395     file.close();
396     return ret;
397 }
398 } // namespace HiviewDFX
399 } // namespace OHOS
400