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 #include "log_parse.h"
16
17 #include "string_util.h"
18 #include "tbox.h"
19
20 using namespace std;
21 namespace OHOS {
22 namespace HiviewDFX {
23 // some stack function is invalid, so it should be ignored
24 const std::map<std::string, std::set<std::string>> LogParse::ignoreList_ = {
25 {"Level1", {
26 "libc.so",
27 "libc++.so",
28 "ld-musl-aarch64.so",
29 "libc_fdleak_debug.so",
30 "unknown",
31 "watchdog",
32 "kthread",
33 "rdr_system_error"}
34 },
35 {"Level2", {
36 "libart.so",
37 "__switch_to",
38 "dump_backtrace",
39 "show_stack",
40 "dump_stack"}
41 },
42 {"Level3", {
43 "panic"}
44 }
45 };
46
IsIgnoreLibrary(const string & val) const47 bool LogParse::IsIgnoreLibrary(const string& val) const
48 {
49 for (const auto &list : ignoreList_) {
50 for (const auto &str : list.second) {
51 if (val.find(str, 0) != string::npos) {
52 return true;
53 }
54 }
55 }
56 return false;
57 }
58
GetStackTop(const vector<string> & validStack,const size_t num) const59 stack<string> LogParse::GetStackTop(const vector<string>& validStack, const size_t num) const
60 {
61 size_t len = validStack.size();
62 stack<string> stackTop;
63 for (size_t i = 0; i < len; i++) {
64 if (i == 0 || len - i < num) {
65 stackTop.push(validStack.at(i));
66 }
67 }
68 return stackTop;
69 }
70
StackToPart(stack<string> & inStack,size_t num) const71 vector<string> LogParse::StackToPart(stack<string>& inStack, size_t num) const
72 {
73 stack<string> partStack;
74 while (!inStack.empty()) {
75 string topStr = inStack.top();
76 StringUtil::EraseString(topStr, "\t");
77 partStack.push(topStr);
78 inStack.pop();
79 }
80 vector<string> validPart;
81 if (!partStack.empty()) {
82 validPart = GetValidStack(num, partStack);
83 }
84 return validPart;
85 }
86
GetValidBlock(stack<string> inStack,vector<string> & lastPart) const87 string LogParse::GetValidBlock(stack<string> inStack, vector<string>& lastPart) const
88 {
89 vector<string> validStack;
90
91 lastPart = StackToPart(inStack, 3); // 3 : first/second/last frame
92 if (lastPart.empty()) {
93 return "";
94 } else if (lastPart.size() > STACK_LEN_MAX) {
95 // keep the begin 28 lines and the end 2 lines
96 lastPart.erase(lastPart.begin() + (STACK_LEN_MAX - 2), lastPart.end() - 2); // 2 : end 2 lines
97 }
98
99 reverse(lastPart.begin(), lastPart.end());
100
101 for (auto& it : lastPart) {
102 it = Tbox::GetStackName(it);
103 }
104 return string{Tbox::ARRAY_STR} + StringUtil::VectorToString(lastPart, false);
105 }
106
GetValidStack(size_t num,stack<string> & inStack) const107 vector<string> LogParse::GetValidStack(size_t num, stack<string>& inStack) const
108 {
109 stack<string> src = inStack;
110 vector<string> validStack;
111 stack<string> outStatck;
112 size_t len = src.size();
113 for (size_t i = 0; i < len; i++) {
114 auto stackFrame = src.top();
115 if (!IsIgnoreLibrary(stackFrame)) {
116 validStack.push_back(stackFrame);
117 }
118 src.pop();
119 }
120 if (validStack.empty()) {
121 MatchIgnoreLibrary(inStack, outStatck, num);
122 len = outStatck.size();
123 for (size_t i = 0; i < len; i++) {
124 validStack.push_back(outStatck.top());
125 outStatck.pop();
126 }
127 }
128 return validStack;
129 }
130
MatchIgnoreLibrary(stack<string> inStack,stack<string> & outStack,size_t num) const131 void LogParse::MatchIgnoreLibrary(stack<string> inStack, stack<string>& outStack, size_t num) const
132 {
133 if (inStack.size() <= num) {
134 outStack = inStack;
135 return;
136 }
137 size_t count = 0;
138 for (auto it = ignoreList_.rbegin(); it != ignoreList_.rend(); ++it) {
139 if (count == ignoreList_.size() - 1) {
140 outStack = inStack;
141 return;
142 }
143
144 stack<string> src = inStack;
145 while (src.size() > num) {
146 string name = src.top();
147 for (auto str : it->second) {
148 if (name.find(str, 0) != string::npos) {
149 outStack = src;
150 return;
151 }
152 }
153 src.pop();
154 }
155 count++;
156 }
157 }
158
159 /*
160 * INPUT :
161 * info : trace spliting by "\n"
162 * OUTPUT :
163 * trace : last part trace to get Frame
164 * return string : valid trace spliting by "\n"
165 */
GetFilterTrace(const std::string & info,std::vector<std::string> & trace,std::string eventType) const166 std::string LogParse::GetFilterTrace(const std::string& info, std::vector<std::string>& trace,
167 std::string eventType) const
168 {
169 std::string newInfo = info;
170 if (eventType == "JS_ERROR" && newInfo.find("libace_napi.z.so") != std::string::npos) {
171 newInfo = StringUtil::GetRightSubstr(info, "libace_napi.z.so");
172 }
173 StringUtil::SplitStr(newInfo, "\n", trace, false, false);
174 std::stack<std::string> traceStack;
175 for (const auto& str : trace) {
176 traceStack.push(str);
177 }
178 trace.clear();
179 return GetValidBlock(traceStack, trace);
180 }
181
SetFrame(std::stack<std::string> & stack,std::map<std::string,std::string> & eventInfo) const182 void LogParse::SetFrame(std::stack<std::string>& stack, std::map<std::string, std::string>& eventInfo) const
183 {
184 std::vector<std::string> name = {"FIRST_FRAME", "SECOND_FRAME", "LAST_FRAME"};
185 size_t len = stack.size();
186 for (size_t i = 0; i < len; i++) {
187 if (eventInfo.find(name[i]) == eventInfo.end()) {
188 eventInfo[name[i]] = stack.top();
189 }
190 stack.pop();
191 }
192 }
193 }
194 }
195