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