• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "extract_rule.h"
16 
17 #include <fstream>
18 #include <regex>
19 
20 #include "file_util.h"
21 #include "log_util.h"
22 #include "logger.h"
23 #include "string_util.h"
24 
25 using namespace std;
26 namespace OHOS {
27 namespace HiviewDFX {
28 DEFINE_LOG_TAG("ExtractRule");
ParseExtractRule(const string & eventType,const string & config,const string & path)29 void ExtractRule::ParseExtractRule(const string& eventType, const string& config, const string& path)
30 {
31     std::ifstream fin(config, std::ifstream::binary);
32 #ifdef JSONCPP_VERSION_STRING
33     Json::CharReaderBuilder builder;
34     Json::CharReaderBuilder::strictMode(&builder.settings_);
35     JSONCPP_STRING errs;
36 #else
37     Json::Reader reader(Json::Features::strictMode());
38 #endif
39 
40     Json::Value root;
41 #ifdef JSONCPP_VERSION_STRING
42     bool ret = parseFromStream(builder, fin, &root, &errs);
43     if (!ret || !errs.empty()) {
44         HIVIEW_LOGE("Json parse fail, err is %{public}s in %{public}s.", errs.c_str(), config.c_str());
45         return;
46     }
47 #else
48     if (!reader.parse(fin, root)) {
49         HIVIEW_LOGE("Json parse fail in %{public}s.", config.c_str());
50         return;
51     }
52 #endif
53     ParseSegStatusCfg(root);
54     ParseRule(eventType, root, path);
55     return;
56 }
57 
ParseSegStatusCfg(const Json::Value & json)58 void ExtractRule::ParseSegStatusCfg(const Json::Value& json)
59 {
60     if (!json.isMember(L1_SEG_STATUS)) {
61         HIVIEW_LOGE("failed to get json number %{public}s.", L1_SEG_STATUS.c_str());
62         return;
63     }
64 
65     Json::Value arrayObj = json[L1_SEG_STATUS];
66     int arrayObjSize = static_cast<int>(arrayObj.size());
67     if (arrayObjSize > JSON_ARRAY_THRESHOLD) {
68         arrayObjSize = JSON_ARRAY_THRESHOLD;
69         HIVIEW_LOGI("json array has been resized to threshold value.");
70     }
71     for (int i = 0; i < arrayObjSize; i++) {
72         string name = arrayObj[i]["namespace"].asString();
73         vector<string> cfg;
74         cfg.emplace_back(arrayObj[i]["matchKey"].asString());
75         cfg.emplace_back(arrayObj[i]["desc"].asString());
76         if (!name.empty() && !cfg[0].empty()) {
77             segStatusCfgMap_.emplace(make_pair(name, cfg));
78         }
79     }
80 }
81 
82 /*
83  * parse and store into feature set
84  */
ParseRule(const string & eventType,const Json::Value & json,const string & path)85 void ExtractRule::ParseRule(const string& eventType, const Json::Value& json, const string& path)
86 {
87     for (auto iter = json.begin(); iter != json.end(); iter++) {
88         auto key = iter.key().asString();
89         if (key.find("Rule") == std::string::npos) {
90             continue;
91         }
92         auto value = (*iter);
93         string dirOrFile = value[L2_DIR_OR_FILE].asString();
94         if (dirOrFile.empty()) {
95             continue;
96         }
97         string subcatalog = value[L2_SUBCATELOG].asString();
98         vector<string> featureIds = SplitFeatureId(value);
99         FeatureSet fsets{};
100         for (const auto& featureId : featureIds) {
101             if (!IsMatchId(eventType, featureId) || !IsMatchPath(path, dirOrFile, subcatalog, fsets.fullPath)) {
102                 continue;
103             }
104             fsets.skipStep = value[L2_SKIP].asInt();
105             fsets.segmentType = value[L2_SEGMENT_TYPE].asString();
106             fsets.startSegVec = GetJsonArray(value, L2_SEGMENT_START);
107             fsets.segStackVec = GetJsonArray(value, L2_SEGMENT_STACK);
108             // 1st: parse feature
109             ParseRule(value, fsets.rules);
110             featureSets_.emplace(pair<string, FeatureSet>(featureId, fsets));
111             featureIds_.emplace_back(featureId);
112             HIVIEW_LOGI("ParseFile eventId %{public}s, FeatureId %{public}s.", eventType.c_str(), featureId.c_str());
113         }
114     }
115     HIVIEW_LOGD("ParseFile end.");
116     return;
117 }
118 
GetFeatureId()119 vector<string> ExtractRule::GetFeatureId()
120 {
121     return featureIds_;
122 }
123 
IsMatchId(const string & eventType,const string & featureId) const124 bool ExtractRule::IsMatchId(const string& eventType, const string& featureId) const
125 {
126     string firstMatch = StringUtil::GetRightSubstr(featureId, "_");
127     if (StringUtil::GetRleftSubstr(firstMatch, "_") == eventType) {
128         return true;
129     }
130     return false;
131 }
132 
GetJsonArray(const Json::Value & json,const string & param)133 std::vector<std::string> ExtractRule::GetJsonArray(const Json::Value& json, const string& param)
134 {
135     if (json.isNull() || !json.isMember(param) || !json[param].isArray()) {
136         HIVIEW_LOGE("failed to get json array number %{public}s.\n", param.c_str());
137         return {};
138     }
139 
140     int jsonSize = static_cast<int>(json[param].size());
141     if (jsonSize > JSON_ARRAY_THRESHOLD) {
142         jsonSize = JSON_ARRAY_THRESHOLD;
143         HIVIEW_LOGI("json array has been resized to threshold value.");
144     }
145     std::vector<std::string> result;
146     for (int i = 0; i < jsonSize; i++) {
147         result.push_back(json[param][i].asString());
148     }
149     return result;
150 }
151 
152 /**
153  * sourcefile: the full path
154  * name: static path
155  * pattern: dynamic path
156  */
IsMatchPath(const string & sourceFile,const string & name,const string & pattern,string & desPath) const157 bool ExtractRule::IsMatchPath(const string& sourceFile, const string& name, const string& pattern,
158     string& desPath) const
159 {
160     HIVIEW_LOGI("sourceFile is %{public}s, name is %{public}s, pattern is %{public}s.\n",
161         sourceFile.c_str(), name.c_str(), pattern.c_str());
162     desPath = sourceFile;
163 
164     if (LogUtil::IsTestModel(sourceFile, name, pattern, desPath)) {
165         HIVIEW_LOGI("this is test model, desPath is %{public}s.\n", desPath.c_str());
166         return true;
167     }
168 
169     if (pattern.empty()) {
170         desPath = name;
171         return LogUtil::FileExist(desPath);
172     }
173 
174     std::vector<std::string> parts;
175     StringUtil::SplitStr(pattern, "/", parts, false, false);
176     std::string out = (name.back() == '/') ? name : (name + "/");
177     for (auto& part : parts) {
178         smatch result;
179         if (regex_match(sourceFile, result, regex(out + part))) {
180             out = ((*(sourceFile.rbegin())) == '/') ? sourceFile : (sourceFile + "/");
181         } else {
182             out += part + "/";
183         }
184     }
185     desPath = out.substr(0, out.size() - 1);
186     return LogUtil::FileExist(desPath);
187 }
188 
SplitFeatureId(const Json::Value & object) const189 vector<string> ExtractRule::SplitFeatureId(const Json::Value& object) const
190 {
191     if (!object.isMember(L2_FEATUREID)) {
192         HIVIEW_LOGE("failed to get json number %{public}s.", L1_SEG_STATUS.c_str());
193         return {};
194     }
195 
196     vector<string> result;
197     StringUtil::SplitStr(object[L2_FEATUREID].asString(), ",", result, false, false);
198     return result;
199 }
200 
ParseRule(const Json::Value & object,list<FeatureRule> & features) const201 void ExtractRule::ParseRule(const Json::Value& object, list<FeatureRule>& features) const
202 {
203     if (!object.isMember(L2_RULES)) {
204         return;
205     }
206     ParseRuleParam(object[L2_RULES], features, L2_RULES);
207 
208     if (!object.isMember(L2_SEGMENT_RULE)) {
209         return;
210     }
211     ParseRuleParam(object[L2_SEGMENT_RULE], features, L2_SEGMENT_RULE);
212 }
213 
ParseRuleParam(const Json::Value & object,list<FeatureRule> & features,const string & type) const214 void ExtractRule::ParseRuleParam(const Json::Value& object, list<FeatureRule>& features, const string& type) const
215 {
216     int objectSize = static_cast<int>(object.size());
217     if (objectSize > JSON_ARRAY_THRESHOLD) {
218         objectSize = JSON_ARRAY_THRESHOLD;
219         HIVIEW_LOGI("json array has been resized to threshold value.");
220     }
221     for (int i = 0; i < objectSize; i++) {
222         FeatureRule command{};
223         command.cmdType = type;
224         command.name = object[i][L3_NAMESPACE].asString();
225         command.source = object[i][L3_MATCH_KEY].asString();
226         command.depend = object[i][L3_DEPEND].asString();
227         GetExtractParam(object[i], command.param, L3_PARAM);
228         command.num = object[i][L3_NUM].asInt();
229         if (command.num > 0 && type == L2_RULES) {
230             HIVIEW_LOGE("rule command can't have num.\n");
231             continue;
232         }
233         features.emplace_back(command);
234     }
235 }
236 
GetExtractParam(const Json::Value & rules,std::map<std::string,std::string> & param,const std::string & preKey) const237 void ExtractRule::GetExtractParam(const Json::Value& rules,
238     std::map<std::string, std::string>& param, const std::string& preKey) const {
239     for (auto iter = rules.begin(); iter != rules.end(); iter++) {
240         auto pos = iter.key().asString().find(preKey);
241         if (pos == 0) {
242             param.emplace(iter.key().asString(), (*iter).asString());
243         }
244     }
245 }
246 } // namespace HiviewDFX
247 } // namespace OHOS
248