1 /*
2 * Copyright (c) 2022 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 "hisysevent_json_decorator.h"
17
18 #include <algorithm>
19 #include <fstream>
20 #include <sstream>
21
22 #include "hilog/log.h"
23 #include "hisysevent.h"
24 #include "json_flatten_parser.h"
25
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN 0xD002D08
28
29 #undef LOG_TAG
30 #define LOG_TAG "HISYSEVENT_JSON_DECORATOR"
31
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace {
35 constexpr char ARRY_SIZE[] = "arrsize";
36 constexpr char DECORATE_PREFIX[] = "\033[31m";
37 constexpr char DECORATE_SUFFIX[] = "\033[0m";
38 constexpr char HISYSEVENT_YAML_DEF_JSON_PATH[] = "/data/system/hiview/unzip_configs/sys_event_def/hisysevent.def";
39 constexpr char LEVEL[] = "level";
40 constexpr char LEVEL_[] = "level_";
41 constexpr char TYPE[] = "type";
42 constexpr int BASE_INDEX = 0;
43 constexpr int DOMAIN_INDEX = 1;
44 constexpr int NAME_INDEX = 2;
45 const char* INNER_BUILD_KEYS[] = {
46 "__BASE", "domain_", "name_", "type_", "level_", "tag_",
47 "time_", "tz_", "pid_", "tid_", "uid_", "traceid_", "log_",
48 "id_", "spanid_", "pspanid_", "trace_flag_", "info_", "seq_" };
49 const std::string VALID_LEVELS[] = { "CRITICAL", "MINOR" };
50 const std::map<std::string, int> EVENT_TYPE_MAP = {{"FAULT", 1}, {"STATISTIC", 2}, {"SECURITY", 3}, {"BEHAVIOR", 4} };
51 }
52
HiSysEventJsonDecorator()53 HiSysEventJsonDecorator::HiSysEventJsonDecorator()
54 {
55 std::ifstream fin(HISYSEVENT_YAML_DEF_JSON_PATH, std::ifstream::binary);
56 #ifdef JSONCPP_VERSION_STRING
57 Json::CharReaderBuilder jsonRBuilder;
58 Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
59 JSONCPP_STRING errs;
60 if (!parseFromStream(jsonRBuilder, fin, &jsonRoot_, &errs)) {
61 #else
62 Json::Reader reader(Json::Features::strictMode());
63 if (!reader.parse(fin, jsonRoot_)) {
64 #endif
65 HILOG_ERROR(LOG_CORE, "parse json file failed, please check the style of json file: %{public}s.",
66 HISYSEVENT_YAML_DEF_JSON_PATH);
67 } else {
68 isJsonRootValid_ = true;
69 }
70 }
71
72 bool HiSysEventJsonDecorator::CheckAttrDecorationNeed(const Json::Value& eventJson, const std::string& key,
73 const Json::Value& standard)
74 {
75 auto ret = CheckAttrValidity(eventJson, key, standard);
76 decoratedMarks_[key] = ret;
77 return ret != Validity::KV_BOTH_VALID;
78 }
79
80 Validity HiSysEventJsonDecorator::CheckAttrValidity(const Json::Value& eventJson, const std::string& key,
81 const Json::Value& standard)
82 {
83 if (!standard.isMember(key)) {
84 return Validity::KEY_INVALID;
85 }
86 bool ret = false;
87 if (standard[key].isMember(ARRY_SIZE)) {
88 if (!eventJson[key].isArray() || eventJson[key].size() > standard[key][ARRY_SIZE].asUInt()) {
89 return Validity::VALUE_INVALID;
90 }
91 ret = JudgeDataType(standard[key][TYPE].asString(), eventJson[key][0]);
92 return ret ? Validity::KV_BOTH_VALID : Validity::VALUE_INVALID;
93 }
94 ret = JudgeDataType(standard[key][TYPE].asString(), eventJson[key]);
95 return ret ? Validity::KV_BOTH_VALID : Validity::VALUE_INVALID;
96 }
97
98 Validity HiSysEventJsonDecorator::CheckLevelValidity(const Json::Value& baseInfo)
99 {
100 if (!baseInfo.isMember(LEVEL)) {
101 HILOG_ERROR(LOG_CORE, "level not defined in __BASE");
102 return Validity::KEY_INVALID;
103 }
104 std::string levelDes = baseInfo[LEVEL].asString();
105 if (std::any_of(std::begin(VALID_LEVELS), std::end(VALID_LEVELS), [&levelDes] (auto& level) {
106 return level == levelDes;
107 })) {
108 return Validity::KV_BOTH_VALID;
109 }
110 return Validity::VALUE_INVALID;
111 }
112
113 bool HiSysEventJsonDecorator::CheckEventDecorationNeed(const Json::Value& eventJson,
114 BaseInfoHandler baseJsonInfoHandler, ExtensiveInfoHander extensiveJsonInfoHandler)
115 {
116 if (!isJsonRootValid_ || !jsonRoot_.isObject() || !eventJson.isObject()) {
117 return true;
118 }
119 std::string domain = eventJson[INNER_BUILD_KEYS[DOMAIN_INDEX]].asString();
120 std::string name = eventJson[INNER_BUILD_KEYS[NAME_INDEX]].asString();
121 if (!jsonRoot_.isMember(domain)) {
122 return true;
123 }
124 Json::Value definedDomain = jsonRoot_[domain];
125 if (!definedDomain.isObject() || !definedDomain.isMember(name)) {
126 return true;
127 }
128 Json::Value definedName = definedDomain[name];
129 if (!definedName.isObject()) {
130 return true;
131 }
132 auto baseInfoNeed = false;
133 if (definedName.isMember(INNER_BUILD_KEYS[BASE_INDEX])) {
134 baseInfoNeed = baseJsonInfoHandler(definedName[INNER_BUILD_KEYS[BASE_INDEX]]);
135 }
136 auto extensiveInfoNeed = extensiveJsonInfoHandler(eventJson, definedName);
137 return baseInfoNeed || extensiveInfoNeed;
138 }
139
140 std::string HiSysEventJsonDecorator::Decorate(Validity validity, std::string& key, std::string& value)
141 {
142 std::stringstream ss;
143 switch (validity) {
144 case Validity::KEY_INVALID:
145 ss << "\"" << DECORATE_PREFIX << key << DECORATE_SUFFIX << "\":" << value;
146 break;
147 case Validity::VALUE_INVALID:
148 ss << "\"" << key << "\":" << DECORATE_PREFIX << value << DECORATE_SUFFIX;
149 break;
150 case Validity::KV_BOTH_VALID:
151 ss << "\"" << key << "\":" << value;
152 break;
153 default:
154 break;
155 }
156 std::string ret = ss.str();
157 ss.clear();
158 return ret;
159 }
160
161 std::string HiSysEventJsonDecorator::DecorateEventJsonStr(const HiSysEventRecord& record)
162 {
163 std::string origin = record.AsJson();
164 decoratedMarks_.clear(); // reset marked keys.
165 if (!isJsonRootValid_) {
166 HILOG_ERROR(LOG_CORE, "root json value is not valid, failed to decorate.");
167 return origin;
168 }
169 Json::Value eventJson;
170 #ifdef JSONCPP_VERSION_STRING
171 Json::CharReaderBuilder jsonRBuilder;
172 Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
173 std::unique_ptr<Json::CharReader> const reader(jsonRBuilder.newCharReader());
174 JSONCPP_STRING errs;
175 if (!reader->parse(origin.data(), origin.data() + origin.size(), &eventJson, &errs)) {
176 #else
177 Json::Reader reader(Json::Features::strictMode());
178 if (!reader.parse(origin, eventJson)) {
179 #endif
180 HILOG_ERROR(LOG_CORE, "parse json file failed, please check the style of json file: %{public}s.",
181 origin.c_str());
182 return origin;
183 }
184 auto needDecorate = CheckEventDecorationNeed(eventJson,
185 [this] (const Json::Value& definedBase) {
186 auto levelValidity = this->CheckLevelValidity(definedBase);
187 decoratedMarks_[LEVEL_] = levelValidity;
188 return levelValidity != Validity::KV_BOTH_VALID;
189 }, [this] (const Json::Value& eventJson, const Json::Value& definedName) {
190 auto attrList = eventJson.getMemberNames();
191 bool ret = false;
192 for (auto it = attrList.cbegin(); it != attrList.cend(); it++) {
193 std::string key = *it;
194 if (std::find_if(std::cbegin(INNER_BUILD_KEYS), std::cend(INNER_BUILD_KEYS),
195 [&ret, &eventJson, &key, &definedName] (const char* ele) {
196 return (key.compare(ele) == 0);
197 }) == std::cend(INNER_BUILD_KEYS)) {
198 ret = this->CheckAttrDecorationNeed(eventJson, key, definedName) || ret;
199 }
200 }
201 return ret;
202 });
203 if (!needDecorate) {
204 HILOG_DEBUG(LOG_CORE, "no need to decorate this event json string.");
205 return origin;
206 }
207 HILOG_DEBUG(LOG_CORE, "all invalid key or value will be high-lighted with red color.");
208 return DecorateJsonStr(origin, decoratedMarks_);
209 }
210
211 std::string HiSysEventJsonDecorator::DecorateJsonStr(const std::string& origin, DecorateMarks marks)
212 {
213 if (marks.empty()) {
214 return origin;
215 }
216 JsonFlattenParser parser(origin);
217 return parser.Print([this, &marks] (KV& kv) -> std::string {
218 auto iter = marks.find(kv.first);
219 return this->Decorate((iter == marks.end() ? Validity::KV_BOTH_VALID : iter->second), kv.first, kv.second);
220 });
221 }
222
223 bool HiSysEventJsonDecorator::JudgeDataType(const std::string &dataType, const Json::Value &eventJson)
224 {
225 if (dataType.compare("BOOL") == 0) {
226 return eventJson.isBool() || (eventJson.isInt() && (eventJson.asInt() == 0 || eventJson.asInt() == 1));
227 } else if ((dataType.compare("INT8") == 0) || (dataType.compare("INT16") == 0) ||
228 (dataType.compare("INT32") == 0)) {
229 return eventJson.isInt();
230 } else if (dataType.compare("INT64") == 0) {
231 return eventJson.isInt64();
232 } else if ((dataType.compare("UINT8") == 0) || (dataType.compare("UINT16") == 0) ||
233 (dataType.compare("UINT32") == 0)) {
234 return eventJson.isUInt();
235 } else if (dataType.compare("UINT64") == 0) {
236 return eventJson.isUInt64();
237 } else if ((dataType.compare("FLOAT") == 0) || (dataType.compare("DOUBLE") == 0)) {
238 return eventJson.isDouble();
239 } else if (dataType.compare("STRING") == 0) {
240 return eventJson.isString();
241 } else {
242 return false;
243 }
244 }
245 } // namespace HiviewDFX
246 } // namespace OHOS
247