• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 (event == nullptr) {
150         HIVIEW_LOGD("sysevent is null.");
151         return false;
152     }
153 
154     if (!CheckEventValidity(event)) {
155         HIVIEW_LOGD("domain_ or name_ not found in the event json string.");
156         return false;
157     }
158 
159     auto baseInfo = GetDefinedBaseInfoByDomainName(event->domain_, event->eventName_);
160     if (baseInfo.type == INVALID_EVENT_TYPE) {
161         HIVIEW_LOGD("type defined for domain: %{public}s, name: %{public}s is invalid.",
162             event->domain_.c_str(), event->eventName_.c_str());
163         return false;
164     }
165     if (!CheckBaseInfoValidity(baseInfo, event)) {
166         HIVIEW_LOGD("failed to verify the base info of the event.");
167         return false;
168     }
169 
170     auto curSysEventId = GenerateHash(event->AsJsonStr());
171     if (filter_.IsDuplicateEvent(curSysEventId)) {
172         HIVIEW_LOGD("duplicate sys event, ignore it directly.");
173         return false; // ignore duplicate sys event
174     }
175 
176     AppendExtensiveInfo(event, curSysEventId);
177     WriteSeqToFile(++curSeq_);
178 
179     return true;
180 }
181 
AppendExtensiveInfo(std::shared_ptr<SysEvent> event,const uint64_t sysEventId) const182 void EventJsonParser::AppendExtensiveInfo(std::shared_ptr<SysEvent> event, const uint64_t sysEventId) const
183 {
184     if (event == nullptr) {
185         return;
186     }
187 
188     // hash code need to add
189     event->SetId(sysEventId);
190 
191     // FreezeDetector needs to add
192     event->SetEventValue(EventStore::EventCol::INFO, "");
193 
194     // add testtype configured as system property named persist.sys.hiview.testtype
195     if (!testTypeConfigured.empty()) {
196         event->SetEventValue(TEST_TYPE_KEY, testTypeConfigured);
197     }
198 
199     // add seq to sys event and then persist it into local file
200     event->SetEventSeq(curSeq_);
201 }
202 
CheckBaseInfoValidity(const BaseInfo & baseInfo,std::shared_ptr<SysEvent> event) const203 bool EventJsonParser::CheckBaseInfoValidity(const BaseInfo& baseInfo, std::shared_ptr<SysEvent> event) const
204 {
205     if (!CheckTypeValidity(baseInfo, event)) {
206         return false;
207     }
208     if (!baseInfo.level.empty()) {
209         event->SetLevel(baseInfo.level);
210     }
211     if (!baseInfo.tag.empty()) {
212         event->SetTag(baseInfo.tag);
213     }
214     return true;
215 }
216 
CheckEventValidity(std::shared_ptr<SysEvent> event) const217 bool EventJsonParser::CheckEventValidity(std::shared_ptr<SysEvent> event) const
218 {
219     if (event == nullptr) {
220         return false;
221     }
222     return !(event->domain_.empty()) && !(event->eventName_.empty());
223 }
224 
CheckTypeValidity(const BaseInfo & baseInfo,std::shared_ptr<SysEvent> event) const225 bool EventJsonParser::CheckTypeValidity(const BaseInfo& baseInfo, std::shared_ptr<SysEvent> event) const
226 {
227     if (event == nullptr) {
228         return false;
229     }
230     HIVIEW_LOGD("base info type is %{public}d, event type is %{public}d", baseInfo.type, event->GetEventType());
231     return event->GetEventType() == baseInfo.type;
232 }
233 
GetDefinedBaseInfoByDomainName(const std::string & domain,const std::string & name) const234 BaseInfo EventJsonParser::GetDefinedBaseInfoByDomainName(const std::string& domain,
235     const std::string& name) const
236 {
237     BaseInfo baseInfo = {
238         .type = INVALID_EVENT_TYPE,
239         .level = "",
240         .tag = "",
241         .preserve = true
242     };
243     auto domainIter = hiSysEventDef_.find(domain);
244     if (domainIter == hiSysEventDef_.end()) {
245         HIVIEW_LOGD("domain named %{public}s is not defined.", domain.c_str());
246         return baseInfo;
247     }
248     auto domainNames = hiSysEventDef_.at(domain);
249     auto nameIter = domainNames.find(name);
250     if (nameIter == domainNames.end()) {
251         HIVIEW_LOGD("%{public}s is not defined in domain named %{public}s.",
252             name.c_str(), domain.c_str());
253         return baseInfo;
254     }
255     return nameIter->second;
256 }
257 
HasIntMember(const Json::Value & jsonObj,const std::string & name) const258 bool EventJsonParser::HasIntMember(const Json::Value& jsonObj, const std::string& name) const
259 {
260     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isInt();
261 }
262 
HasStringMember(const Json::Value & jsonObj,const std::string & name) const263 bool EventJsonParser::HasStringMember(const Json::Value& jsonObj, const std::string& name) const
264 {
265     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isString();
266 }
267 
HasBoolMember(const Json::Value & jsonObj,const std::string & name) const268 bool EventJsonParser::HasBoolMember(const Json::Value& jsonObj, const std::string& name) const
269 {
270     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isBool();
271 }
272 
InitEventInfoMapRef(const Json::Value & eventJson,JSON_VALUE_LOOP_HANDLER handler) const273 void EventJsonParser::InitEventInfoMapRef(const Json::Value& eventJson, JSON_VALUE_LOOP_HANDLER handler) const
274 {
275     if (!eventJson.isObject()) {
276         return;
277     }
278     auto attrList = eventJson.getMemberNames();
279     for (auto it = attrList.cbegin(); it != attrList.cend(); it++) {
280         std::string key = *it;
281         if (key.empty()) {
282             continue;
283         }
284         if (handler != nullptr) {
285             handler(key, eventJson[key]);
286         }
287     }
288 }
289 
ParseBaseConfig(const Json::Value & eventNameJson) const290 BaseInfo EventJsonParser::ParseBaseConfig(const Json::Value& eventNameJson) const
291 {
292     BaseInfo baseInfo = {
293         .type = INVALID_EVENT_TYPE,
294         .level = "",
295         .tag = "",
296         .preserve = true
297     };
298     if (!eventNameJson.isObject() || !eventNameJson[BASE].isObject()) {
299         HIVIEW_LOGD("__BASE definition is invalid.");
300         return baseInfo;
301     }
302     Json::Value baseJsonInfo = eventNameJson[BASE];
303     if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, TYPE)) {
304         HIVIEW_LOGD("type is not defined in __BASE.");
305         return baseInfo;
306     }
307     std::string typeDes = baseJsonInfo[TYPE].asString();
308     if (EVENT_TYPE_MAP.find(typeDes) == EVENT_TYPE_MAP.end()) {
309         HIVIEW_LOGD("type is defined as %{public}s, but a valid type must be FAULT, STATISTIC, SECURITY, or BEHAVIOR",
310             typeDes.c_str());
311         return baseInfo;
312     }
313     baseInfo.type = EVENT_TYPE_MAP.at(typeDes);
314     if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, LEVEL)) {
315         HIVIEW_LOGD("level is not defined in __BASE.");
316         return baseInfo;
317     }
318     baseInfo.level = baseJsonInfo[LEVEL].asString();
319     if (baseJsonInfo.isObject() && HasStringMember(baseJsonInfo, TAG)) {
320         baseInfo.tag = baseJsonInfo[TAG].asString();
321     }
322     if (baseJsonInfo.isObject() && HasBoolMember(baseJsonInfo, PRESERVE)) {
323         baseInfo.preserve = baseJsonInfo[PRESERVE].asBool();
324         return baseInfo;
325     }
326     return baseInfo;
327 }
328 
ParseHiSysEventDef(const Json::Value & hiSysEventDef)329 void EventJsonParser::ParseHiSysEventDef(const Json::Value& hiSysEventDef)
330 {
331     InitEventInfoMapRef(hiSysEventDef, [this] (const std::string& key, const Json::Value& value) {
332        hiSysEventDef_[key] = ParseNameConfig(value);
333     });
334 }
335 
ParseNameConfig(const Json::Value & domainJson) const336 NAME_INFO_MAP EventJsonParser::ParseNameConfig(const Json::Value& domainJson) const
337 {
338     NAME_INFO_MAP allNames;
339     if (!domainJson.isObject()) {
340         return allNames;
341     }
342     InitEventInfoMapRef(domainJson, [this, &allNames] (const std::string& key, const Json::Value& value) {
343         allNames[key] = ParseBaseConfig(value);
344     });
345     return allNames;
346 }
347 
GetSequenceFile() const348 std::string EventJsonParser::GetSequenceFile() const
349 {
350     std::string workPath = HiviewGlobal::GetInstance()->GetHiViewDirectory(
351         HiviewContext::DirectoryType::WORK_DIRECTORY);
352     if (workPath.back() != '/') {
353         workPath = workPath + "/";
354     }
355     return workPath + "sys_event_db/" + SEQ_PERSISTS_FILE_NAME;
356 }
357 
ReadSeqFromFile(int64_t & seq)358 void EventJsonParser::ReadSeqFromFile(int64_t& seq)
359 {
360     std::string content;
361     std::string seqFile = GetSequenceFile();
362     if (!FileUtil::LoadStringFromFile(seqFile, content) && !content.empty()) {
363         HIVIEW_LOGE("failed to read sequence value from %{public}s.", seqFile.c_str());
364         return;
365     }
366     seq = static_cast<int64_t>(strtoll(content.c_str(), nullptr, 0));
367     HIVIEW_LOGI("read max sequence from local file successful, value is %{public}" PRId64 ".", seq);
368     SysEventServiceAdapter::UpdateEventSeq(seq);
369 }
370 
WriteSeqToFile(int64_t seq) const371 void EventJsonParser::WriteSeqToFile(int64_t seq) const
372 {
373     std::string seqFile = GetSequenceFile();
374     std::string content = std::to_string(seq);
375     if (!FileUtil::SaveStringToFile(seqFile, content, true)) {
376         HIVIEW_LOGE("failed to write sequence %{public}s to %{public}s.", content.c_str(), seqFile.c_str());
377     }
378     SysEventServiceAdapter::UpdateEventSeq(seq);
379 }
380 } // namespace HiviewDFX
381 } // namespace OHOS
382