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