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