1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "feature_analysis.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include <algorithm> 18020a203aSopenharmony_ci#include <list> 19020a203aSopenharmony_ci#include <regex> 20020a203aSopenharmony_ci#include <string> 21020a203aSopenharmony_ci#include <vector> 22020a203aSopenharmony_ci 23020a203aSopenharmony_ci#include "file_util.h" 24020a203aSopenharmony_ci#include "log_util.h" 25020a203aSopenharmony_ci#include "hiview_logger.h" 26020a203aSopenharmony_ci#include "string_util.h" 27020a203aSopenharmony_ci 28020a203aSopenharmony_ciusing namespace std; 29020a203aSopenharmony_cinamespace OHOS { 30020a203aSopenharmony_cinamespace HiviewDFX { 31020a203aSopenharmony_ciDEFINE_LOG_TAG("FeatureAnalysis"); 32020a203aSopenharmony_ci 33020a203aSopenharmony_ciconst string FeatureAnalysis::COMPOSE_PLUS = "+"; 34020a203aSopenharmony_ciconst string FeatureAnalysis::COMPOSE_COLON = ":"; 35020a203aSopenharmony_cinamespace { 36020a203aSopenharmony_ci const string PARAMETER_REASON = "REASON"; 37020a203aSopenharmony_ci} 38020a203aSopenharmony_ci 39020a203aSopenharmony_ciFeatureAnalysis::~FeatureAnalysis() 40020a203aSopenharmony_ci{ 41020a203aSopenharmony_ci HIVIEW_LOGD("<%{public}d> FeatureAnalysis::~FeatureAnalysis.", taskId_); 42020a203aSopenharmony_ci} 43020a203aSopenharmony_ci 44020a203aSopenharmony_cibool FeatureAnalysis::AnalysisLog() 45020a203aSopenharmony_ci{ 46020a203aSopenharmony_ci HIVIEW_LOGI("<%{public}d> begin analysis <%{public}s>, eventType is <%{public}s>.", taskId_, 47020a203aSopenharmony_ci featureSet_.fullPath.c_str(), eventType_.c_str()); 48020a203aSopenharmony_ci 49020a203aSopenharmony_ci Extract(); 50020a203aSopenharmony_ci if (paramSeekRecord_.empty()) { 51020a203aSopenharmony_ci errorCode_ = EXTRACT_ERROR; 52020a203aSopenharmony_ci return false; 53020a203aSopenharmony_ci } 54020a203aSopenharmony_ci Compose(); 55020a203aSopenharmony_ci return true; 56020a203aSopenharmony_ci} 57020a203aSopenharmony_ci 58020a203aSopenharmony_civoid FeatureAnalysis::Extract() 59020a203aSopenharmony_ci{ 60020a203aSopenharmony_ci stringstream buffer(""); 61020a203aSopenharmony_ci if (!LogUtil::ReadFileBuff(featureSet_.fullPath, buffer) || !buffer.good() || buffer.eof()) { 62020a203aSopenharmony_ci errorCode_ = BUFFER_ERROR; 63020a203aSopenharmony_ci HIVIEW_LOGE("<%{public}d> file is invalid", taskId_); 64020a203aSopenharmony_ci return; 65020a203aSopenharmony_ci } 66020a203aSopenharmony_ci 67020a203aSopenharmony_ci // extract info 68020a203aSopenharmony_ci RawInfoPosition(buffer); 69020a203aSopenharmony_ci} 70020a203aSopenharmony_ci 71020a203aSopenharmony_civoid FeatureAnalysis::RawInfoPosition(stringstream& buffer) 72020a203aSopenharmony_ci{ 73020a203aSopenharmony_ci int skipStep = (featureSet_.skipStep > 0) ? featureSet_.skipStep : MAX_SKIP_LINE; 74020a203aSopenharmony_ci int dismatchCount = 1; // default : countDismatch - 1 >= skipSpace 75020a203aSopenharmony_ci string line; 76020a203aSopenharmony_ci bool segmentStart = false; 77020a203aSopenharmony_ci HIVIEW_LOGI("<%{public}d> skipStep is %{public}d. size:%{public}zu", taskId_, skipStep, featureSet_.rules.size()); 78020a203aSopenharmony_ci while (getline(buffer, line)) { 79020a203aSopenharmony_ci if (line.length() > 2048 || // 2048 : max length of line 80020a203aSopenharmony_ci (CheckStartSegment(segmentStart) && (line.empty() || line[0] == ' ' || line[0] == '\t'))) { 81020a203aSopenharmony_ci continue; 82020a203aSopenharmony_ci } 83020a203aSopenharmony_ci GetCursorInfo(buffer, line); 84020a203aSopenharmony_ci for (auto iterCmd = featureSet_.rules.begin(); iterCmd != featureSet_.rules.end();) { 85020a203aSopenharmony_ci // Check the variable symbol and replace it with the parameter value of the variable 86020a203aSopenharmony_ci FeatureRule& featureCmd = *iterCmd; 87020a203aSopenharmony_ci 88020a203aSopenharmony_ci if (CheckDepend(featureCmd) || (!CheckVariableParam(featureCmd)) || (!IsSourceMatch(line, featureCmd))) { 89020a203aSopenharmony_ci iterCmd++; 90020a203aSopenharmony_ci continue; 91020a203aSopenharmony_ci } 92020a203aSopenharmony_ci int num = featureCmd.num; 93020a203aSopenharmony_ci bool matchFlag = ParseElementForParam(line, featureCmd); 94020a203aSopenharmony_ci while (--num > 0 && getline(buffer, line)) { 95020a203aSopenharmony_ci GetCursorInfo(buffer, line); 96020a203aSopenharmony_ci ParseElementForParam(line, featureCmd); 97020a203aSopenharmony_ci } 98020a203aSopenharmony_ci 99020a203aSopenharmony_ci if (matchFlag && featureCmd.cmdType == L2_RULES) { 100020a203aSopenharmony_ci iterCmd = featureSet_.rules.erase(iterCmd); // erase will iterCmd++, but break avoid out of range 101020a203aSopenharmony_ci } else { 102020a203aSopenharmony_ci iterCmd++; 103020a203aSopenharmony_ci } 104020a203aSopenharmony_ci dismatchCount = 0; 105020a203aSopenharmony_ci break; 106020a203aSopenharmony_ci } 107020a203aSopenharmony_ci dismatchCount++; 108020a203aSopenharmony_ci if (featureSet_.rules.empty() || dismatchCount - 1 >= skipStep) { 109020a203aSopenharmony_ci break; 110020a203aSopenharmony_ci } 111020a203aSopenharmony_ci } 112020a203aSopenharmony_ci} 113020a203aSopenharmony_ci 114020a203aSopenharmony_civoid FeatureAnalysis::GetCursorInfo(stringstream& buff, const string& line) 115020a203aSopenharmony_ci{ 116020a203aSopenharmony_ci line_ = line; 117020a203aSopenharmony_ci lineCursor_ = static_cast<int>(buff.tellg()) - static_cast<int>(line.length()) - 1; 118020a203aSopenharmony_ci} 119020a203aSopenharmony_ci 120020a203aSopenharmony_cibool FeatureAnalysis::CheckStartSegment(bool& segmentStart) const 121020a203aSopenharmony_ci{ 122020a203aSopenharmony_ci if (segmentStart) { 123020a203aSopenharmony_ci return segmentStart; 124020a203aSopenharmony_ci } 125020a203aSopenharmony_ci vector<std::pair<std::string, LineFeature>> info = paramSeekRecord_; 126020a203aSopenharmony_ci for (const auto& one : info) { 127020a203aSopenharmony_ci if (one.first.find("LayerTwoCmd") != string::npos || 128020a203aSopenharmony_ci one.first.find("LayerOneCmd") != string::npos) { 129020a203aSopenharmony_ci segmentStart = true; 130020a203aSopenharmony_ci break; 131020a203aSopenharmony_ci } 132020a203aSopenharmony_ci } 133020a203aSopenharmony_ci return segmentStart; 134020a203aSopenharmony_ci} 135020a203aSopenharmony_ci 136020a203aSopenharmony_ci// line match source or not 137020a203aSopenharmony_cibool FeatureAnalysis::IsSourceMatch(const string& line, const FeatureRule& rule) const 138020a203aSopenharmony_ci{ 139020a203aSopenharmony_ci string cmdSrc = rule.source; 140020a203aSopenharmony_ci // if startwith "@R@" 141020a203aSopenharmony_ci if (L3_REGULAR_DESCRIPTOR == cmdSrc.substr(0, L3_REGULAR_DESCRIPTOR.length())) { 142020a203aSopenharmony_ci cmdSrc = cmdSrc.substr(L3_REGULAR_DESCRIPTOR.length()); 143020a203aSopenharmony_ci return regex_search(line, regex(cmdSrc)); 144020a203aSopenharmony_ci } 145020a203aSopenharmony_ci 146020a203aSopenharmony_ci // handle OR or AND expression 147020a203aSopenharmony_ci bool isOrExp = (cmdSrc.find(L3_OR_DESCRIPTOR) == string::npos) ? false : true; 148020a203aSopenharmony_ci bool isAndExp = (cmdSrc.find(L3_AND_DESCRIPTOR) == string::npos) ? false : true; 149020a203aSopenharmony_ci if (!isOrExp && !isAndExp) { 150020a203aSopenharmony_ci return line.find(cmdSrc) != string::npos; 151020a203aSopenharmony_ci } else if (isOrExp) { 152020a203aSopenharmony_ci return IsMatchOrExpression(line, cmdSrc); 153020a203aSopenharmony_ci } else if (isAndExp) { 154020a203aSopenharmony_ci return IsMatchAndExpression(line, cmdSrc); 155020a203aSopenharmony_ci } 156020a203aSopenharmony_ci return false; 157020a203aSopenharmony_ci} 158020a203aSopenharmony_ci 159020a203aSopenharmony_cibool FeatureAnalysis::IsMatchOrExpression(const string& line, const string& src) const 160020a203aSopenharmony_ci{ 161020a203aSopenharmony_ci vector<string> srcSplit; 162020a203aSopenharmony_ci StringUtil::SplitStr(src, L3_OR_DESCRIPTOR, srcSplit, false, false); 163020a203aSopenharmony_ci for (auto str : srcSplit) { 164020a203aSopenharmony_ci if (line.find(str) != string::npos) { 165020a203aSopenharmony_ci return true; 166020a203aSopenharmony_ci } 167020a203aSopenharmony_ci } 168020a203aSopenharmony_ci return false; 169020a203aSopenharmony_ci} 170020a203aSopenharmony_ci 171020a203aSopenharmony_cibool FeatureAnalysis::IsMatchAndExpression(const string& line, const string& src) const 172020a203aSopenharmony_ci{ 173020a203aSopenharmony_ci string lineCpy = line; 174020a203aSopenharmony_ci size_t pos; 175020a203aSopenharmony_ci vector<string> srcSplit; 176020a203aSopenharmony_ci StringUtil::SplitStr(src, L3_AND_DESCRIPTOR, srcSplit, false, false); 177020a203aSopenharmony_ci for (auto str : srcSplit) { 178020a203aSopenharmony_ci pos = lineCpy.find(str); 179020a203aSopenharmony_ci if (pos == string::npos) { 180020a203aSopenharmony_ci return false; 181020a203aSopenharmony_ci } 182020a203aSopenharmony_ci lineCpy = lineCpy.substr(pos + str.length()); 183020a203aSopenharmony_ci } 184020a203aSopenharmony_ci return true; 185020a203aSopenharmony_ci} 186020a203aSopenharmony_ci 187020a203aSopenharmony_cibool FeatureAnalysis::ParseElementForParam(const string& src, FeatureRule& rule) 188020a203aSopenharmony_ci{ 189020a203aSopenharmony_ci if (rule.param.empty()) { 190020a203aSopenharmony_ci return true; // if param is empty, erase the rule 191020a203aSopenharmony_ci } 192020a203aSopenharmony_ci 193020a203aSopenharmony_ci bool hasContinue = false; 194020a203aSopenharmony_ci for (auto iter = rule.param.begin(); iter != rule.param.end();) { 195020a203aSopenharmony_ci // subParam.first: parameter name; subParam.second: the expression to match 196020a203aSopenharmony_ci string reg = ""; 197020a203aSopenharmony_ci smatch result; 198020a203aSopenharmony_ci int seekType = GetSeekInfo(iter->second, reg); 199020a203aSopenharmony_ci hasContinue = (seekType == LAST_MATCH) ? true : hasContinue; 200020a203aSopenharmony_ci if (reg.find(L3_VARIABLE_TRACE_BLOCK) != string::npos || regex_search(src, result, regex(reg))) { 201020a203aSopenharmony_ci string value = result.str(1).empty() ? "" : string(result.str(1)); 202020a203aSopenharmony_ci SetParamRecord(rule.name + "." + iter->first, FormatLineFeature(value, reg), seekType); 203020a203aSopenharmony_ci SetStackRegex(rule.name + "." + iter->first, reg); 204020a203aSopenharmony_ci if (seekType == FIRST_MATCH && rule.cmdType == L2_RULES) { 205020a203aSopenharmony_ci iter = rule.param.erase(iter); 206020a203aSopenharmony_ci } else { 207020a203aSopenharmony_ci iter++; 208020a203aSopenharmony_ci } 209020a203aSopenharmony_ci } else { 210020a203aSopenharmony_ci iter++; 211020a203aSopenharmony_ci } 212020a203aSopenharmony_ci } 213020a203aSopenharmony_ci 214020a203aSopenharmony_ci return hasContinue ? false : rule.param.empty(); 215020a203aSopenharmony_ci} 216020a203aSopenharmony_ci 217020a203aSopenharmony_ciint FeatureAnalysis::GetSeekInfo(const string& param, string& value) const 218020a203aSopenharmony_ci{ 219020a203aSopenharmony_ci if (param.find(L3_SEEK_LAST) != string::npos) { 220020a203aSopenharmony_ci value = StringUtil::GetRightSubstr(param, L3_SEEK_LAST); 221020a203aSopenharmony_ci return LAST_MATCH; 222020a203aSopenharmony_ci } 223020a203aSopenharmony_ci value = param; 224020a203aSopenharmony_ci return FIRST_MATCH; 225020a203aSopenharmony_ci} 226020a203aSopenharmony_ci 227020a203aSopenharmony_cibool FeatureAnalysis::CheckVariableParam(FeatureRule& rule) const 228020a203aSopenharmony_ci{ 229020a203aSopenharmony_ci // Check whether there is a variable operator &@& in the command 230020a203aSopenharmony_ci string symbol = ""; 231020a203aSopenharmony_ci string value = ""; 232020a203aSopenharmony_ci bool hasValSymbol = CheckVariable(rule, L3_DESCRIPTOR_LEFT, L3_DESCRIPTOR_RIGHT); 233020a203aSopenharmony_ci if (!hasValSymbol) { 234020a203aSopenharmony_ci return true; 235020a203aSopenharmony_ci } 236020a203aSopenharmony_ci // To replace it if there is one or more variable symbol 237020a203aSopenharmony_ci for (const auto& param : paramSeekRecord_) { 238020a203aSopenharmony_ci symbol = L3_DESCRIPTOR_LEFT + param.first + L3_DESCRIPTOR_RIGHT; 239020a203aSopenharmony_ci value = param.second.value; 240020a203aSopenharmony_ci ReplaceVariable(rule, symbol, value); 241020a203aSopenharmony_ci } 242020a203aSopenharmony_ci return !CheckVariable(rule, L3_DESCRIPTOR_LEFT, L3_DESCRIPTOR_RIGHT); // check var in config 243020a203aSopenharmony_ci} 244020a203aSopenharmony_ci 245020a203aSopenharmony_cibool FeatureAnalysis::CheckVariable(const FeatureRule& rule, const string& leftTag, const string& rightTag) const 246020a203aSopenharmony_ci{ 247020a203aSopenharmony_ci if ((rule.source.find(leftTag) != string::npos && rule.source.find(rightTag) != string::npos) || 248020a203aSopenharmony_ci (rule.depend.find(leftTag) != string::npos && rule.depend.find(rightTag) != string::npos)) { 249020a203aSopenharmony_ci return true; 250020a203aSopenharmony_ci } 251020a203aSopenharmony_ci for (auto subParam : rule.param) { 252020a203aSopenharmony_ci if (subParam.second.find(leftTag) != string::npos && subParam.second.find(rightTag) != string::npos) { 253020a203aSopenharmony_ci return true; 254020a203aSopenharmony_ci } 255020a203aSopenharmony_ci } 256020a203aSopenharmony_ci 257020a203aSopenharmony_ci return false; 258020a203aSopenharmony_ci} 259020a203aSopenharmony_ci 260020a203aSopenharmony_civoid FeatureAnalysis::ReplaceVariable(FeatureRule& rule, const string& symbol, const string& value) const 261020a203aSopenharmony_ci{ 262020a203aSopenharmony_ci ReplaceVariable(rule.source, symbol, value, rule.source); 263020a203aSopenharmony_ci ReplaceVariable(rule.depend, symbol, value, rule.depend); 264020a203aSopenharmony_ci for (auto subParam : rule.param) { 265020a203aSopenharmony_ci if (ReplaceVariable(subParam.second, symbol, value, subParam.second)) { 266020a203aSopenharmony_ci rule.param[subParam.first] = subParam.second; 267020a203aSopenharmony_ci } 268020a203aSopenharmony_ci } 269020a203aSopenharmony_ci} 270020a203aSopenharmony_ci 271020a203aSopenharmony_cibool FeatureAnalysis::ReplaceVariable(const string& src, const string& param, 272020a203aSopenharmony_ci const string& value, string& des) const 273020a203aSopenharmony_ci{ 274020a203aSopenharmony_ci des = src; 275020a203aSopenharmony_ci size_t pos = src.find(param); 276020a203aSopenharmony_ci if (pos != string::npos) { 277020a203aSopenharmony_ci des.replace(pos, param.length(), value, 0, value.length()); 278020a203aSopenharmony_ci return true; 279020a203aSopenharmony_ci } 280020a203aSopenharmony_ci 281020a203aSopenharmony_ci return false; 282020a203aSopenharmony_ci} 283020a203aSopenharmony_ci 284020a203aSopenharmony_ci/* 285020a203aSopenharmony_ci * return false if the depend element does not exist 286020a203aSopenharmony_ci * return false if the depend element exists and the feature that the depend element relies on has a value 287020a203aSopenharmony_ci * return true if the depend element exists and the feature that the depend element relies on has no value 288020a203aSopenharmony_ci */ 289020a203aSopenharmony_cibool FeatureAnalysis::CheckDepend(const FeatureRule& rule) const 290020a203aSopenharmony_ci{ 291020a203aSopenharmony_ci bool result = false; 292020a203aSopenharmony_ci if (rule.depend.empty()) { 293020a203aSopenharmony_ci return result; 294020a203aSopenharmony_ci } 295020a203aSopenharmony_ci 296020a203aSopenharmony_ci if (paramSeekRecord_.empty()) { // depend exist but no value 297020a203aSopenharmony_ci return true; 298020a203aSopenharmony_ci } 299020a203aSopenharmony_ci 300020a203aSopenharmony_ci result = true; 301020a203aSopenharmony_ci for (const auto& one : paramSeekRecord_) { 302020a203aSopenharmony_ci if (one.first.find(rule.depend) != string::npos) { 303020a203aSopenharmony_ci result = false; // depend exist but value exist 304020a203aSopenharmony_ci break; 305020a203aSopenharmony_ci } 306020a203aSopenharmony_ci } 307020a203aSopenharmony_ci return result; 308020a203aSopenharmony_ci} 309020a203aSopenharmony_ci 310020a203aSopenharmony_ciLineFeature FeatureAnalysis::FormatLineFeature(const string& value, const string& regex) const 311020a203aSopenharmony_ci{ 312020a203aSopenharmony_ci LineFeature paramRecord{}; 313020a203aSopenharmony_ci paramRecord.value = value; 314020a203aSopenharmony_ci paramRecord.lineCursor = lineCursor_; 315020a203aSopenharmony_ci return paramRecord; 316020a203aSopenharmony_ci} 317020a203aSopenharmony_ci 318020a203aSopenharmony_ci/* 319020a203aSopenharmony_ci * info : eventinfo_ or relatedInfo_ result 320020a203aSopenharmony_ci * params : rule info, for example : key : value 321020a203aSopenharmony_ci * "SUBJECT": "BasicParam.s_subject", 322020a203aSopenharmony_ci * "END_STACK": "MainCallTrace.s_trust_stack", 323020a203aSopenharmony_ci * features : Log feature 324020a203aSopenharmony_ci */ 325020a203aSopenharmony_civoid FeatureAnalysis::Compose() 326020a203aSopenharmony_ci{ 327020a203aSopenharmony_ci string result; 328020a203aSopenharmony_ci for (const auto& param : composeRule_) { 329020a203aSopenharmony_ci // keep ordered rule_prio, REASON is specially composed 330020a203aSopenharmony_ci if (eventInfo_.find(param.first) != eventInfo_.end() && param.first != PARAMETER_REASON) { 331020a203aSopenharmony_ci continue; 332020a203aSopenharmony_ci } 333020a203aSopenharmony_ci result = ComposeParam(param.second); 334020a203aSopenharmony_ci if (!result.empty()) { 335020a203aSopenharmony_ci eventInfo_[param.first] = (param.first == PARAMETER_REASON) ? 336020a203aSopenharmony_ci (eventInfo_[param.first] + COMPOSE_COLON + result) : result; 337020a203aSopenharmony_ci } 338020a203aSopenharmony_ci } 339020a203aSopenharmony_ci ProcessReason(eventInfo_); 340020a203aSopenharmony_ci} 341020a203aSopenharmony_ci 342020a203aSopenharmony_cistring FeatureAnalysis::ComposeTrace(const string& filePath, const string& param, 343020a203aSopenharmony_ci const vector<pair<string, LineFeature>>& lineFeatures, const string& regex) const 344020a203aSopenharmony_ci{ 345020a203aSopenharmony_ci string result; 346020a203aSopenharmony_ci auto iter = find_if(lineFeatures.begin(), lineFeatures.end(), 347020a203aSopenharmony_ci [¶m](const pair<string, LineFeature>& one) {return one.first == param;}); 348020a203aSopenharmony_ci if (iter != lineFeatures.end()) { 349020a203aSopenharmony_ci stringstream buffer(""); 350020a203aSopenharmony_ci if (LogUtil::ReadFileBuff(filePath, buffer)) { 351020a203aSopenharmony_ci LogUtil::GetTrace(buffer, iter->second.lineCursor, regex, result); 352020a203aSopenharmony_ci } 353020a203aSopenharmony_ci } 354020a203aSopenharmony_ci return result; 355020a203aSopenharmony_ci} 356020a203aSopenharmony_ci 357020a203aSopenharmony_cistring FeatureAnalysis::ComposeParam(const string& param) const 358020a203aSopenharmony_ci{ 359020a203aSopenharmony_ci std::vector<std::pair<std::string, LineFeature>> lineFeatures = paramSeekRecord_; 360020a203aSopenharmony_ci vector<string> params = SplitParam(param); 361020a203aSopenharmony_ci vector<string> results; 362020a203aSopenharmony_ci for (const auto& key : params) { 363020a203aSopenharmony_ci auto iter = find_if(lineFeatures.begin(), lineFeatures.end(), 364020a203aSopenharmony_ci [&key](const pair<string, LineFeature>& one) {return one.first == key;}); 365020a203aSopenharmony_ci if (iter != lineFeatures.end()) { 366020a203aSopenharmony_ci auto regexIter = stackRegex_.find(key); 367020a203aSopenharmony_ci if (regexIter != stackRegex_.end()) { 368020a203aSopenharmony_ci auto value = ComposeTrace(featureSet_.fullPath, key, lineFeatures, regexIter->second); 369020a203aSopenharmony_ci results.emplace_back(value); 370020a203aSopenharmony_ci } else { 371020a203aSopenharmony_ci results.emplace_back(iter->second.value); 372020a203aSopenharmony_ci } 373020a203aSopenharmony_ci } 374020a203aSopenharmony_ci } 375020a203aSopenharmony_ci 376020a203aSopenharmony_ci string tag; 377020a203aSopenharmony_ci if (!results.empty()) { 378020a203aSopenharmony_ci if (param.find(COMPOSE_PLUS) != string::npos) { 379020a203aSopenharmony_ci tag = " "; 380020a203aSopenharmony_ci } else if (param.find(COMPOSE_COLON) != string::npos) { 381020a203aSopenharmony_ci tag = COMPOSE_COLON; 382020a203aSopenharmony_ci } else { 383020a203aSopenharmony_ci tag = ""; 384020a203aSopenharmony_ci } 385020a203aSopenharmony_ci } 386020a203aSopenharmony_ci string result = StringUtil::VectorToString(results, false, tag); 387020a203aSopenharmony_ci auto end = result.size() - tag.size(); 388020a203aSopenharmony_ci return (end > 0) ? result.substr(0, end) : result; 389020a203aSopenharmony_ci} 390020a203aSopenharmony_ci 391020a203aSopenharmony_civector<string> FeatureAnalysis::SplitParam(const string& param) const 392020a203aSopenharmony_ci{ 393020a203aSopenharmony_ci vector<string> params; 394020a203aSopenharmony_ci if (param.find(COMPOSE_PLUS) != string::npos) { 395020a203aSopenharmony_ci StringUtil::SplitStr(param, COMPOSE_PLUS, params, false, false); 396020a203aSopenharmony_ci } else if (param.find(COMPOSE_COLON) != string::npos) { 397020a203aSopenharmony_ci StringUtil::SplitStr(param, COMPOSE_COLON, params, false, false); 398020a203aSopenharmony_ci } else { 399020a203aSopenharmony_ci params.emplace_back(param); 400020a203aSopenharmony_ci } 401020a203aSopenharmony_ci return params; 402020a203aSopenharmony_ci} 403020a203aSopenharmony_ci 404020a203aSopenharmony_civoid FeatureAnalysis::ProcessReason(map<string, string>& info) 405020a203aSopenharmony_ci{ 406020a203aSopenharmony_ci if (info.find(PARAMETER_REASON) != info.end() && 407020a203aSopenharmony_ci info[PARAMETER_REASON].substr(0, 1) == COMPOSE_COLON) { // 1: first char 408020a203aSopenharmony_ci info[PARAMETER_REASON] = info[PARAMETER_REASON].substr(1); 409020a203aSopenharmony_ci } 410020a203aSopenharmony_ci} 411020a203aSopenharmony_ci 412020a203aSopenharmony_civoid FeatureAnalysis::SetParamRecord(const std::string& key, const LineFeature& value, const int type) 413020a203aSopenharmony_ci{ 414020a203aSopenharmony_ci if (type == LAST_MATCH) { 415020a203aSopenharmony_ci for (auto iter = paramSeekRecord_.begin(); iter != paramSeekRecord_.end(); iter++) { 416020a203aSopenharmony_ci if (iter->first == key) { 417020a203aSopenharmony_ci paramSeekRecord_.erase(iter); 418020a203aSopenharmony_ci break; 419020a203aSopenharmony_ci } 420020a203aSopenharmony_ci } 421020a203aSopenharmony_ci } 422020a203aSopenharmony_ci paramSeekRecord_.emplace_back(pair<string, LineFeature>(key, value)); 423020a203aSopenharmony_ci} 424020a203aSopenharmony_ci 425020a203aSopenharmony_civoid FeatureAnalysis::SetStackRegex(const std::string& key, const std::string& regex) 426020a203aSopenharmony_ci{ 427020a203aSopenharmony_ci if (regex.find(L3_VARIABLE_TRACE_BLOCK) != string::npos) { 428020a203aSopenharmony_ci stackRegex_.emplace(pair(key, StringUtil::EraseString(regex, L3_VARIABLE_TRACE_BLOCK))); 429020a203aSopenharmony_ci } 430020a203aSopenharmony_ci} 431020a203aSopenharmony_ci} // namespace HiviewDFX 432020a203aSopenharmony_ci} // namespace OHOS 433