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
16 #include "audit_log_parser.h"
17 #include "audit.h"
18 #include "string_util.h"
19
20 namespace OHOS {
21 namespace HiviewDFX {
22 namespace {
23 constexpr int LOG_ELEMENT_MIN_COUNT = 3;
24 constexpr int LOG_ELEMENT_TIMESTAMP_POS = 0;
25 constexpr int LOG_ELEMENT_SERIAL_ID_POS = 1;
26 constexpr int LOG_ELEMENT_EVENT_TYPE_POS = 2;
27 constexpr int LOG_ELEMENT_NORMAL_EVENT_SENDER_POS = 3;
28 constexpr int LOG_ELEMENT_NORMAL_EVENT_PROCESSOR_POS = 4;
29 constexpr int LOG_ELEMENT_NORMAL_EVENT_THREAD_POS = 5;
30 constexpr int LOG_ELEMENT_NORMAL_EVENT_DIGEST_POS = 6;
31 constexpr int LOG_ELEMENT_PIPE_EVENT_CREATOR_POS = 3;
32 constexpr int LOG_ELEMENT_PIPE_EVENT_DIGEST_POS = 4;
33 constexpr int LOG_ELEMENT_PIPE_EVENT_PROCESSOR_POS = 3;
34 constexpr int LOG_ELEMENT_PIPE_EVENT_THREAD_POS = 3;
35 constexpr int LOG_ELEMENT_PIPE_EVENT_PIPELINE_POS = 3;
36 constexpr int QUEUE_EVENT_IN_ELEMENT_SIZE = 7;
37 constexpr int QUEUE_EVENT_OUT_ELEMENT_SIZE = 3;
38 constexpr int PIPELINE_EVENT_CREATE_ELEMENT_SIZE = 5;
39 constexpr int PIPELINE_EVENT_HANDLE_IN_ELEMENT_SIZE = 4;
40 constexpr int PIPELINE_EVENT_HANDLE_OUT_ELEMENT_SIZE = 4;
41 constexpr int PIPELINE_EVENT_DONE_ELEMENT_SIZE = 4;
42
CreateEventInfo(uint64_t serialId,const std::string & digest,const std::vector<std::string> & eventElements)43 AuditLogParser::EventInfo CreateEventInfo(uint64_t serialId, const std::string& digest,
44 const std::vector<std::string>& eventElements)
45 {
46 AuditLogParser::EventInfo info;
47 info.isPipelineEvent = true;
48 info.eventSerialId = serialId;
49 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_TIMESTAMP_POS], info.inTime);
50 info.processor = eventElements[LOG_ELEMENT_PIPE_EVENT_PROCESSOR_POS];
51 info.digest = digest;
52 return info;
53 }
54
SplitStr(const std::string & log)55 std::vector<std::string> SplitStr(const std::string& log)
56 {
57 std::vector<std::string> elements;
58 std::string sep(1, Audit::DOMAIN_DELIMITER);
59 StringUtil::SplitStr(log, sep, elements);
60 return elements;
61 }
62 } // namespace
63
StartParse()64 void AuditLogParser::StartParse()
65 {
66 std::list<std::string> logList;
67 if (!Audit::GetAuditLog(true, logList)) {
68 return;
69 }
70
71 ParseTimeScope(logList);
72 for (auto& log : logList) {
73 auto elements = SplitStr(log);
74 if (elements.size() < LOG_ELEMENT_MIN_COUNT) {
75 continue;
76 }
77
78 int eventType = -1;
79 StringUtil::ConvertStringTo<int>(elements[LOG_ELEMENT_EVENT_TYPE_POS], eventType);
80 if (std::to_string(eventType) != elements[LOG_ELEMENT_EVENT_TYPE_POS]) {
81 eventType = -1;
82 }
83 if (eventType < Audit::StatsEvent::QUEUE_EVENT_IN) {
84 continue;
85 }
86
87 if (eventType <= Audit::StatsEvent::QUEUE_EVENT_OUT) {
88 ParseNormalAuditEvent(eventType, elements);
89 } else if (eventType <= Audit::StatsEvent::PIPELINE_EVENT_DONE) {
90 ParsePipelineAuditEvent(eventType, elements);
91 }
92 }
93 }
94
GetThreadSummary(const std::string & name)95 std::list<std::string> AuditLogParser::GetThreadSummary(const std::string& name)
96 {
97 std::list<std::string> ret;
98 std::string pid = name;
99 auto pos = pid.find("@");
100 if (pos != std::string::npos) {
101 pid = pid.substr(pos + 1);
102 }
103
104 for (auto& event : eventList_) {
105 if (event.threadNameOrTid.find(pid) != std::string::npos) {
106 ret.push_back(event.ToString());
107 }
108 }
109
110 for (auto& pipeEvent : pipelineEventList_) {
111 for (auto& chainEvent : pipeEvent.processChain) {
112 if (chainEvent.threadNameOrTid.find(pid) != std::string::npos) {
113 ret.push_back(chainEvent.ToString());
114 }
115 }
116 }
117 return ret;
118 }
119
GetPluginSummary(const std::string & name)120 std::list<std::string> AuditLogParser::GetPluginSummary(const std::string& name)
121 {
122 std::list<std::string> ret;
123 for (auto& event : eventList_) {
124 if (event.processor.find(name) != std::string::npos) {
125 ret.push_back(event.ToString());
126 }
127 }
128
129 for (auto& pipeEvent : pipelineEventList_) {
130 for (auto& chainEvent : pipeEvent.processChain) {
131 if (chainEvent.processor.find(name) != std::string::npos) {
132 ret.push_back(chainEvent.ToString());
133 }
134 }
135 }
136 return ret;
137 }
138
GetPipelineSummary(const std::string & name)139 std::list<std::string> AuditLogParser::GetPipelineSummary(const std::string& name)
140 {
141 std::list<std::string> ret;
142 for (auto& pipeEvent : pipelineEventList_) {
143 if (pipeEvent.pipeline.find(name) != std::string::npos) {
144 ret.push_back(pipeEvent.ToString());
145 }
146 }
147 return ret;
148 }
149
GetAuditLogTimeScope()150 std::string AuditLogParser::GetAuditLogTimeScope()
151 {
152 return "Audit Logs From " + std::to_string(logStartTime_) + " to " + std::to_string(logEndTime_);
153 }
154
ParseTimeScope(const std::list<std::string> & logList)155 void AuditLogParser::ParseTimeScope(const std::list<std::string>& logList)
156 {
157 if (logList.empty()) {
158 return;
159 }
160
161 auto beginLog = SplitStr(*(logList.begin()));
162 StringUtil::ConvertStringTo<uint64_t>(beginLog[LOG_ELEMENT_TIMESTAMP_POS], logStartTime_);
163 auto endLog = SplitStr(*(logList.rbegin()));
164 StringUtil::ConvertStringTo<uint64_t>(endLog[LOG_ELEMENT_TIMESTAMP_POS], logEndTime_);
165 }
166
ParseNormalAuditEvent(int eventType,const std::vector<std::string> & eventElements)167 void AuditLogParser::ParseNormalAuditEvent(int eventType, const std::vector<std::string>& eventElements)
168 {
169 if (eventType == Audit::StatsEvent::QUEUE_EVENT_IN && eventElements.size() >= QUEUE_EVENT_IN_ELEMENT_SIZE) {
170 ParseNormalEnqueueEvent(eventElements);
171 return;
172 }
173
174 if (eventType == Audit::StatsEvent::QUEUE_EVENT_OUT && eventElements.size() >= QUEUE_EVENT_OUT_ELEMENT_SIZE) {
175 ParseNormalDequeueEvent(eventElements);
176 }
177 }
178
ParseNormalEnqueueEvent(const std::vector<std::string> & eventElements)179 void AuditLogParser::ParseNormalEnqueueEvent(const std::vector<std::string>& eventElements)
180 {
181 EventInfo info;
182 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_TIMESTAMP_POS], info.inTime);
183 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_SERIAL_ID_POS], info.eventSerialId);
184 info.sender = eventElements[LOG_ELEMENT_NORMAL_EVENT_SENDER_POS];
185 info.processor = eventElements[LOG_ELEMENT_NORMAL_EVENT_PROCESSOR_POS];
186 info.threadNameOrTid = eventElements[LOG_ELEMENT_NORMAL_EVENT_THREAD_POS];
187 info.digest = eventElements[LOG_ELEMENT_NORMAL_EVENT_DIGEST_POS];
188 eventList_.push_back(std::move(info));
189 }
190
ParseNormalDequeueEvent(const std::vector<std::string> & eventElements)191 void AuditLogParser::ParseNormalDequeueEvent(const std::vector<std::string>& eventElements)
192 {
193 uint64_t eventSerialId = 0;
194 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_SERIAL_ID_POS], eventSerialId);
195 for (auto rit = eventList_.rbegin(); rit != eventList_.rend(); ++rit) {
196 if (rit->eventSerialId == eventSerialId) {
197 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_TIMESTAMP_POS], rit->outTime);
198 return;
199 }
200 }
201 }
202
ParsePipelineAuditEvent(int eventType,const std::vector<std::string> & eventElements)203 void AuditLogParser::ParsePipelineAuditEvent(int eventType, const std::vector<std::string>& eventElements)
204 {
205 if (eventType == Audit::StatsEvent::PIPELINE_EVENT_CREATE &&
206 eventElements.size() >= PIPELINE_EVENT_CREATE_ELEMENT_SIZE) {
207 ParsePipelineCreateEvent(eventElements);
208 return;
209 }
210
211 if (eventType == Audit::StatsEvent::PIPELINE_EVENT_HANDLE_IN &&
212 eventElements.size() >= PIPELINE_EVENT_HANDLE_IN_ELEMENT_SIZE) {
213 ParsePipelineHandleInEvent(eventElements);
214 return;
215 }
216
217 if (eventType == Audit::StatsEvent::PIPELINE_EVENT_HANDLE_OUT &&
218 eventElements.size() >= PIPELINE_EVENT_HANDLE_OUT_ELEMENT_SIZE) {
219 ParsePipelineHandleOutEvent(eventElements);
220 return;
221 }
222
223 if (eventType == Audit::StatsEvent::PIPELINE_EVENT_DONE &&
224 eventElements.size() >= PIPELINE_EVENT_DONE_ELEMENT_SIZE) {
225 ParsePipelineDoneEvent(eventElements);
226 return;
227 }
228 }
229
ParsePipelineCreateEvent(const std::vector<std::string> & eventElements)230 void AuditLogParser::ParsePipelineCreateEvent(const std::vector<std::string>& eventElements)
231 {
232 PipelineEventInfo info;
233 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_TIMESTAMP_POS], info.createTime);
234 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_SERIAL_ID_POS], info.eventSerialId);
235 info.creator = eventElements[LOG_ELEMENT_PIPE_EVENT_CREATOR_POS];
236 info.digest = eventElements[LOG_ELEMENT_PIPE_EVENT_DIGEST_POS];
237 pipelineEventList_.push_back(std::move(info));
238 }
239
ParsePipelineHandleInEvent(const std::vector<std::string> & eventElements)240 void AuditLogParser::ParsePipelineHandleInEvent(const std::vector<std::string>& eventElements)
241 {
242 uint64_t eventSerialId = 0;
243 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_SERIAL_ID_POS], eventSerialId);
244 for (auto rit = pipelineEventList_.rbegin(); rit != pipelineEventList_.rend(); ++rit) {
245 if (rit->eventSerialId == eventSerialId) {
246 rit->processChain.push_back(CreateEventInfo(eventSerialId, rit->digest, eventElements));
247 return;
248 }
249 }
250
251 for (auto rit = eventList_.rbegin(); rit != eventList_.rend(); ++rit) {
252 if (rit->eventSerialId == eventSerialId) {
253 PipelineEventInfo info(*rit);
254 info.processChain.push_back(CreateEventInfo(eventSerialId, info.digest, eventElements));
255 pipelineEventList_.push_back(std::move(info));
256 return;
257 }
258 }
259 }
260
ParsePipelineHandleOutEvent(const std::vector<std::string> & eventElements)261 void AuditLogParser::ParsePipelineHandleOutEvent(const std::vector<std::string>& eventElements)
262 {
263 uint64_t eventSerialId = 0;
264 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_SERIAL_ID_POS], eventSerialId);
265 for (auto rit = pipelineEventList_.rbegin(); rit != pipelineEventList_.rend(); ++rit) {
266 if (rit->eventSerialId == eventSerialId) {
267 auto& info = rit->processChain.back();
268 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_TIMESTAMP_POS], info.outTime);
269 info.threadNameOrTid = eventElements[LOG_ELEMENT_PIPE_EVENT_THREAD_POS];
270 return;
271 }
272 }
273 }
274
ParsePipelineDoneEvent(const std::vector<std::string> & eventElements)275 void AuditLogParser::ParsePipelineDoneEvent(const std::vector<std::string>& eventElements)
276 {
277 uint64_t eventSerialId = 0;
278 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_SERIAL_ID_POS], eventSerialId);
279 for (auto rit = pipelineEventList_.rbegin(); rit != pipelineEventList_.rend(); ++rit) {
280 if (rit->eventSerialId == eventSerialId) {
281 StringUtil::ConvertStringTo<uint64_t>(eventElements[LOG_ELEMENT_TIMESTAMP_POS], rit->destroyTime);
282 rit->pipeline = eventElements[LOG_ELEMENT_PIPE_EVENT_PIPELINE_POS];
283 return;
284 }
285 }
286 }
287 } // namespace HiviewDFX
288 } // namespace OHOS
289