1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 "print_event_parser.h"
16 #include "animation_filter.h"
17 #include "clock_filter_ex.h"
18 #include "frame_filter.h"
19 #include "measure_filter.h"
20 #include "stat_filter.h"
21 #include "string_to_numerical.h"
22 #include <cinttypes>
23 namespace SysTuning {
24 namespace TraceStreamer {
25 const uint8_t POINT_LENGTH = 1;
26 const uint8_t MAX_POINT_LENGTH = 2;
27 const uint8_t CATEGORY_INDEX = 2;
28 const uint8_t PARSER_SYNC_SUM = 2;
29 const uint8_t PARSER_ASYNC_SUM = 3;
PrintEventParser(TraceDataCache * dataCache,const TraceStreamerFilters * filter)30 PrintEventParser::PrintEventParser(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
31 : EventParserBase(dataCache, filter)
32 {
33 rsOnDoCompositionEvent_ = traceDataCache_->GetDataIndex(rsOnDoCompositionStr_);
34 eventToFrameFunctionMap_ = {
35 {recvievVsync_, bind(&PrintEventParser::ReciveVsync, this, std::placeholders::_1, std::placeholders::_2,
36 std::placeholders::_3)},
37 {rsOnDoCompositionEvent_, bind(&PrintEventParser::RSReciveOnDoComposition, this, std::placeholders::_1,
38 std::placeholders::_2, std::placeholders::_3)},
39 {onVsyncEvent_, bind(&PrintEventParser::OnVsyncEvent, this, std::placeholders::_1, std::placeholders::_2,
40 std::placeholders::_3)},
41 {marshRwTransactionData_, bind(&PrintEventParser::OnRwTransaction, this, std::placeholders::_1,
42 std::placeholders::_2, std::placeholders::_3)},
43 {rsMainThreadProcessCmd_, bind(&PrintEventParser::OnMainThreadProcessCmd, this, std::placeholders::_1,
44 std::placeholders::_2, std::placeholders::_3)}};
45 }
46
ParsePrintEvent(const std::string & comm,uint64_t ts,uint32_t pid,std::string_view event,const BytraceLine & line)47 bool PrintEventParser::ParsePrintEvent(const std::string &comm,
48 uint64_t ts,
49 uint32_t pid,
50 std::string_view event,
51 const BytraceLine &line)
52 {
53 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED);
54 TracePoint point;
55 if (GetTracePoint(event, point) != PARSE_SUCCESS) {
56 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
57 return false;
58 }
59 if (point.tgid_) {
60 // tgid use 'B|' after with 'TGID', the '(TGID)' maybe wrong, eg: xxx-21675 ( 1264) ...: print: B|21675|...
61 const_cast<BytraceLine &>(line).tgid = point.tgid_;
62 streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_);
63 }
64 switch (point.phase_) {
65 case 'B': {
66 ParseBeginEvent(comm, ts, pid, point, line);
67 break;
68 }
69 case 'E': {
70 ParseEndEvent(ts, pid, point);
71 break;
72 }
73 case 'S': {
74 ParseStartEvent(comm, ts, pid, point, line);
75 break;
76 }
77 case 'F': {
78 ParseFinishEvent(ts, pid, point, line);
79 break;
80 }
81 case 'C': {
82 ParseCreateEvent(ts, point);
83 break;
84 }
85 case 'G': {
86 ParseGEvent(ts, pid, point);
87 break;
88 }
89 case 'H': {
90 ParseHEvent(ts, point);
91 break;
92 }
93 default:
94 TS_LOGD("point missing!");
95 return false;
96 }
97 return true;
98 }
ParseBeginEvent(const std::string & comm,uint64_t ts,uint32_t pid,TracePoint & point,const BytraceLine & line)99 void PrintEventParser::ParseBeginEvent(const std::string &comm,
100 uint64_t ts,
101 uint32_t pid,
102 TracePoint &point,
103 const BytraceLine &line)
104 {
105 uint32_t index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX,
106 traceDataCache_->GetDataIndex(point.name_));
107 if (index != INVALID_UINT32) {
108 // add distributed data
109 traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(index, point.chainId_, point.spanId_,
110 point.parentSpanId_, point.flag_);
111
112 // add traceMeta data
113 traceDataCache_->GetInternalSlicesData()->SetTraceMetadata(index, point.traceLevel_, point.traceTagId_,
114 point.customArgsId_);
115 if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) {
116 return;
117 }
118 bool isDiscontinued = false;
119 if (streamFilters_->configFilter_->GetSwitchConfig().TaskPoolConfigEnabled()) {
120 isDiscontinued = streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index);
121 }
122 if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled() && !isDiscontinued) {
123 (void)HandleAnimationBeginEvent(point, index, line);
124 }
125 } else {
126 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST);
127 }
128 }
ParseEndEvent(uint64_t ts,uint32_t pid,const TracePoint & point)129 void PrintEventParser::ParseEndEvent(uint64_t ts, uint32_t pid, const TracePoint &point)
130 {
131 uint32_t index = streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_);
132 HandleFrameSliceEndEvent(ts, point.tgid_, pid, index);
133 if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) {
134 streamFilters_->animationFilter_->EndDynamicFrameEvent(ts, index);
135 }
136 }
ParseStartEvent(const std::string & comm,uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)137 void PrintEventParser::ParseStartEvent(const std::string &comm,
138 uint64_t ts,
139 uint32_t pid,
140 const TracePoint &point,
141 const BytraceLine &line)
142 {
143 auto cookie = static_cast<int64_t>(point.value_);
144 auto index = streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie,
145 traceDataCache_->GetDataIndex(point.name_));
146 if (index == INVALID_UINT64) {
147 return;
148 }
149 // add traceMeta data
150 traceDataCache_->GetInternalSlicesData()->SetTraceMetadata(index, point.traceLevel_, point.traceTagId_,
151 point.customArgsId_, point.customCategoryId_);
152
153 if (point.name_ == onFrameQueeuStartEvent_) {
154 OnFrameQueueStart(ts, index, point.tgid_);
155 } else if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled() && index != INVALID_UINT64 &&
156 streamFilters_->configFilter_->GetAnimationConfig().CheckIfAnimationEvents(
157 comm)) { // the comm is taskName
158 streamFilters_->animationFilter_->StartAnimationEvent(line, point, index);
159 }
160 }
ParseFinishEvent(uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)161 void PrintEventParser::ParseFinishEvent(uint64_t ts, uint32_t pid, const TracePoint &point, const BytraceLine &line)
162 {
163 auto cookie = static_cast<int64_t>(point.value_);
164 auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie,
165 traceDataCache_->GetDataIndex(point.name_));
166 HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index);
167 if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) {
168 streamFilters_->animationFilter_->FinishAnimationEvent(line, index);
169 }
170 }
ParseCreateEvent(uint64_t ts,const TracePoint & point)171 void PrintEventParser::ParseCreateEvent(uint64_t ts, const TracePoint &point)
172 {
173 DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_);
174 uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_);
175 if (internalPid != INVALID_ID) {
176 streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, internalPid, nameIndex, ts,
177 point.value_);
178 streamFilters_->processFilter_->AddProcessMemory(internalPid);
179 } else {
180 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
181 }
182 }
ParseGEvent(uint64_t ts,uint32_t pid,TracePoint & point)183 void PrintEventParser::ParseGEvent(uint64_t ts, uint32_t pid, TracePoint &point)
184 {
185 auto cookie = static_cast<int64_t>(point.value_);
186 streamFilters_->sliceFilter_->StartGEvent(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_));
187 }
ParseHEvent(uint64_t ts,const TracePoint & point)188 void PrintEventParser::ParseHEvent(uint64_t ts, const TracePoint &point)
189 {
190 auto cookie = static_cast<int64_t>(point.value_);
191 streamFilters_->sliceFilter_->FinishHEvent(ts, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_));
192 }
HandleAnimationBeginEvent(const TracePoint & point,size_t callStackRow,const BytraceLine & line)193 bool PrintEventParser::HandleAnimationBeginEvent(const TracePoint &point, size_t callStackRow, const BytraceLine &line)
194 {
195 if (!streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line)) {
196 return streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, callStackRow);
197 }
198 return true;
199 }
SetTraceType(TraceFileType traceType)200 void PrintEventParser::SetTraceType(TraceFileType traceType)
201 {
202 streamFilters_->frameFilter_->SetTraceType(traceType);
203 }
SetTraceClockId(BuiltinClocks clock)204 void PrintEventParser::SetTraceClockId(BuiltinClocks clock)
205 {
206 if (clock != clock_) {
207 clock_ = clock;
208 }
209 }
Finish()210 void PrintEventParser::Finish()
211 {
212 eventToFrameFunctionMap_.clear();
213 frameCallIds_.clear();
214 vsyncSliceMap_.clear();
215 streamFilters_->animationFilter_->Clear();
216 streamFilters_->frameFilter_->Clear();
217 }
CheckTracePoint(std::string_view pointStr) const218 ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const
219 {
220 if (pointStr.size() == 0) {
221 TS_LOGD("get trace point data size is 0!");
222 return PARSE_ERROR;
223 }
224
225 std::string clockSyncSts = "trace_event_clock_sync";
226 if (pointStr.compare(0, clockSyncSts.length(), clockSyncSts.c_str()) == 0) {
227 TS_LOGD("skip trace point :%s!", clockSyncSts.c_str());
228 return PARSE_ERROR;
229 }
230
231 if (pointStr.find_first_of('B') != 0 && pointStr.find_first_of('E') != 0 && pointStr.find_first_of('C') != 0 &&
232 pointStr.find_first_of('S') != 0 && pointStr.find_first_of('F') != 0 && pointStr.find_first_of('G') != 0 &&
233 pointStr.find_first_of('H') != 0) {
234 TS_LOGD("trace point not supported : [%c] !", pointStr[0]);
235 return PARSE_ERROR;
236 }
237
238 if (pointStr.find_first_of('E') != 0 && pointStr.size() == 1) {
239 TS_LOGD("point string size error!");
240 return PARSE_ERROR;
241 }
242
243 if (pointStr.size() >= MAX_POINT_LENGTH) {
244 if ((pointStr[1] != '|') && (pointStr[1] != '\n')) {
245 TS_LOGD("not support data formart!");
246 return PARSE_ERROR;
247 }
248 }
249
250 return PARSE_SUCCESS;
251 }
252
GetPointNameForBegin(std::string_view pointStr,size_t tGidlength) const253 std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const
254 {
255 size_t index = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
256
257 size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0);
258 std::string_view name = std::string_view(pointStr.data() + index, length);
259 // remove space at the end
260 name = std::string_view(name.data(), name.find_last_not_of(" ") + 1);
261 return name;
262 }
263
ParseSplitTraceMetaData(const std::string & dataStr,TracePoint & outPoint,bool isAsynEvent) const264 void PrintEventParser::ParseSplitTraceMetaData(const std::string &dataStr, TracePoint &outPoint, bool isAsynEvent) const
265 {
266 std::string metaDataStr = base::Strip(dataStr);
267 uint32_t expectedCount = isAsynEvent ? PARSER_ASYNC_SUM : PARSER_SYNC_SUM;
268 std::vector<std::string> traceMetaDatas = base::SplitStringToVec(metaDataStr, "|", expectedCount);
269 if (traceMetaDatas.size() <= 1) {
270 TS_LOGD("traceMetaDatas size: %zu, dataStr: %s", traceMetaDatas.size(), dataStr.c_str());
271 return;
272 }
273
274 std::string &marker = traceMetaDatas[1];
275 if (!marker.empty()) {
276 outPoint.traceLevel_ = marker.substr(0, 1);
277 if (marker.size() > 1) {
278 std::string traceTag = marker.substr(1);
279 outPoint.traceTagId_ = traceDataCache_->GetDataIndex(traceTag);
280 }
281 }
282
283 if (isAsynEvent && traceMetaDatas.size() > CATEGORY_INDEX) {
284 std::string customCategory = traceMetaDatas[CATEGORY_INDEX];
285 outPoint.customCategoryId_ = traceDataCache_->GetDataIndex(customCategory);
286 }
287
288 if (traceMetaDatas.size() > expectedCount) {
289 std::string customArgs = traceMetaDatas[expectedCount];
290 outPoint.customArgsId_ = traceDataCache_->GetDataIndex(customArgs);
291 }
292 }
293
HandlerB(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const294 ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
295 {
296 outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength);
297 if (outPoint.name_.empty()) {
298 TS_LOGD("point name is empty!");
299 return PARSE_ERROR;
300 }
301 // Distributed data:
302 // <...>-357 (-------) .... 174330.287420: tracing_mark_write:
303 // B|1298|H:[8b00e96b2,2,1]#C##napi::NativeAsyncWork::QueueWithQos
304 std::smatch matcheLine;
305 bool matched = std::regex_match(outPoint.name_, matcheLine, distributeMatcher_);
306 if (matched) {
307 size_t index = 0;
308 outPoint.chainId_ = matcheLine[++index].str();
309 outPoint.spanId_ = matcheLine[++index].str();
310 outPoint.parentSpanId_ = matcheLine[++index].str();
311 outPoint.flag_ = matcheLine[++index].str();
312 } else {
313 auto space = outPoint.name_.find(' ');
314 if (space != std::string::npos) {
315 outPoint.funcPrefix_ = outPoint.name_.substr(0, space);
316 outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.funcPrefix_);
317 outPoint.funcArgs_ = outPoint.name_.substr(space + 1);
318 } else {
319 outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.name_);
320 }
321 }
322 // traceMetaDatasSrt: H:name|%X%TAG|customArgs
323 ParseSplitTraceMetaData(outPoint.name_, outPoint, false);
324 return PARSE_SUCCESS;
325 }
326
HandleFrameSliceBeginEvent(DataIndex eventName,size_t callStackRow,std::string & args,const BytraceLine & line)327 bool PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName,
328 size_t callStackRow,
329 std::string &args,
330 const BytraceLine &line)
331 {
332 auto it = eventToFrameFunctionMap_.find(eventName);
333 if (it != eventToFrameFunctionMap_.end()) {
334 it->second(callStackRow, args, line);
335 return true;
336 } else if (StartWith(traceDataCache_->GetDataFromDict(eventName), rsOnDoCompositionStr_)) {
337 RSReciveOnDoComposition(callStackRow, args, line);
338 return true;
339 } else if (StartWith(traceDataCache_->GetDataFromDict(eventName), uiVsyncTaskStr_)) {
340 DealUIVsyncTaskEvent(eventName, line);
341 }
342 return false;
343 }
ReciveVsync(size_t callStackRow,std::string & args,const BytraceLine & line)344 bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string &args, const BytraceLine &line)
345 {
346 streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_RECEIVED);
347 // args is like "dataCount:24bytes now:211306766162 expectedEnd:211323423844 vsyncId:3179"
348 std::sregex_iterator it(args.begin(), args.end(), recvVsyncPattern_);
349 std::sregex_iterator end;
350 uint64_t now = INVALID_UINT64;
351 uint64_t expectEnd = INVALID_UINT64;
352 uint32_t vsyncId = INVALID_UINT32;
353 while (it != end) {
354 std::smatch match = *it;
355 std::string key = match.str(1);
356 std::string value = match.str(2);
357 if (key == "now") {
358 now = base::StrToInt<uint64_t>(value).value();
359 } else if (key == "expectedEnd") {
360 expectEnd = base::StrToInt<uint64_t>(value).value();
361 } else if (key == "vsyncId") {
362 vsyncId = base::StrToInt<uint64_t>(value).value();
363 }
364 ++it;
365 }
366 if (now == 0 || expectEnd == 0 || vsyncId == 0) {
367 TS_LOGE("Now,expectedEnd or vsyncId should not be 0!");
368 return false;
369 }
370 streamFilters_->frameFilter_->BeginVsyncEvent(line, now, expectEnd, vsyncId, callStackRow);
371 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
372 if (vsyncSliceMap_.count(iTid)) {
373 vsyncSliceMap_[iTid].push_back(callStackRow);
374 } else {
375 vsyncSliceMap_[iTid] = {callStackRow};
376 }
377 return true;
378 }
379
DealUIVsyncTaskEvent(DataIndex eventName,const BytraceLine & line)380 bool PrintEventParser::DealUIVsyncTaskEvent(DataIndex eventName, const BytraceLine &line)
381 {
382 auto eventNameStr = traceDataCache_->GetDataFromDict(eventName);
383 std::sregex_iterator it(eventNameStr.begin(), eventNameStr.end(), uiVsyncTaskPattern_);
384 std::sregex_iterator end;
385 uint64_t timeId = 0;
386 while (it != end) {
387 std::smatch match = *it;
388 std::string key = match.str(1);
389 std::string value = match.str(2);
390 if (key == "timestamp") {
391 timeId = base::StrToInt<uint64_t>(value).value();
392 }
393 if (key == "vsyncID") {
394 (void)streamFilters_->frameFilter_->UpdateVsyncId(line, base::StrToInt<uint32_t>(value).value(), timeId);
395 return true;
396 }
397 ++it;
398 }
399 return false;
400 }
OnVsyncEvent(size_t callStackRow,std::string & args,const BytraceLine & line)401 bool PrintEventParser::OnVsyncEvent(size_t callStackRow, std::string &args, const BytraceLine &line)
402 {
403 Unused(args);
404 streamFilters_->frameFilter_->BeginParallelTraceEvent(line, callStackRow);
405 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
406 // when there are mutiple nested OnVsyncEvent,only handle the OnvsyncEvent of the next layer under ReceiveVsync
407 if (vsyncSliceMap_[iTid].size() >= maxVsyncEventSize_) {
408 return false;
409 }
410 vsyncSliceMap_[iTid].push_back(callStackRow);
411 return true;
412 }
RSReciveOnDoComposition(size_t callStackRow,std::string & args,const BytraceLine & line)413 bool PrintEventParser::RSReciveOnDoComposition(size_t callStackRow, std::string &args, const BytraceLine &line)
414 {
415 streamFilters_->statFilter_->IncreaseStat(TRACE_ON_DO_COMPOSITION, STAT_EVENT_RECEIVED);
416 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
417 (void)streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(iTid);
418 return true;
419 }
OnRwTransaction(size_t callStackRow,std::string & args,const BytraceLine & line)420 bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string &args, const BytraceLine &line)
421 {
422 // H:MarshRSTransactionData cmdCount:20 transactionFlag:[3799,8] isUni:1
423 std::smatch match;
424 if (std::regex_search(args, match, newTransFlagPattern_)) {
425 std::string mainTheadId = match.str(1);
426 std::string flag2 = match.str(2);
427 std::string currentThread = match.str(3);
428 std::string timeFlag = match.str(4);
429 auto mainThreadId =
430 streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(mainTheadId).value());
431 auto currentThreadId =
432 streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(currentThread).value());
433 auto timeId = base::StrToInt<uint64_t>(timeFlag).value();
434 return streamFilters_->frameFilter_->BeginRSTransactionData(
435 currentThreadId, base::StrToInt<uint32_t>(flag2).value(), mainThreadId, timeId);
436 }
437 if (std::regex_search(args, match, transFlagPattern_)) {
438 std::string mainTheadId = match.str(1);
439 std::string flag2 = match.str(2);
440 // use to update dstRenderSlice_
441 auto mainThreadId =
442 streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(mainTheadId).value());
443 // use to update vsyncRenderSlice_
444 auto currentThreadId = streamFilters_->processFilter_->GetInternalTid(line.pid);
445 return streamFilters_->frameFilter_->BeginRSTransactionData(
446 currentThreadId, base::StrToInt<uint32_t>(flag2).value(), mainThreadId);
447 }
448 return true;
449 }
OnMainThreadProcessCmd(size_t callStackRow,std::string & args,const BytraceLine & line)450 bool PrintEventParser::OnMainThreadProcessCmd(size_t callStackRow, std::string &args, const BytraceLine &line)
451 {
452 std::sregex_iterator it(args.begin(), args.end(), mainProcessCmdPattern_);
453 std::sregex_iterator end;
454 std::vector<FrameFilter::FrameMap> frames;
455 while (it != end) {
456 std::smatch match = *it;
457 std::string value1 = match.str(1);
458 std::string value2 = match.str(2);
459 frames.push_back({streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(value1).value()),
460 base::StrToInt<uint32_t>(value2).value()});
461 ++it;
462 }
463 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
464 return streamFilters_->frameFilter_->BeginProcessCommandUni(iTid, frames, callStackRow);
465 }
OnFrameQueueStart(uint64_t ts,size_t callStackRow,uint64_t pid)466 bool PrintEventParser::OnFrameQueueStart(uint64_t ts, size_t callStackRow, uint64_t pid)
467 {
468 streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_RECEIVED);
469 auto iTid = streamFilters_->processFilter_->GetInternalTid(pid);
470 if (streamFilters_->frameFilter_->StartFrameQueue(ts, iTid)) {
471 frameCallIds_.push_back(callStackRow);
472 }
473 return true;
474 }
HandleFrameSliceEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)475 void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
476 {
477 // it can be frame or slice
478 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
479 if (vsyncSliceMap_.count(iTid)) {
480 auto pos = std::find(vsyncSliceMap_[iTid].begin(), vsyncSliceMap_[iTid].end(), callStackRow);
481 if (pos != vsyncSliceMap_[iTid].end()) {
482 if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) {
483 streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH);
484 }
485 vsyncSliceMap_[iTid].erase(pos);
486 }
487 }
488 return;
489 }
490
HandleFrameQueueEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)491 void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
492 {
493 // it can be frame or slice
494 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
495 auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow);
496 if (pos != frameCallIds_.end()) {
497 TS_LOGD("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 "", ts, tid);
498 if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) {
499 streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH);
500 TS_LOGW("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 " failed", ts, tid);
501 }
502 frameCallIds_.erase(pos);
503 }
504 return;
505 }
HandlerE(void)506 ParseResult PrintEventParser::HandlerE(void)
507 {
508 return PARSE_SUCCESS;
509 }
510
GetNameLength(std::string_view pointStr,size_t nameIndex)511 size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex)
512 {
513 size_t namelength = 0;
514 for (size_t i = nameIndex; i < pointStr.size(); i++) {
515 if (pointStr[i] == ' ') {
516 namelength = i - nameIndex;
517 }
518 if (pointStr[i] == '|') {
519 namelength = i - nameIndex;
520 break;
521 }
522 }
523 return namelength;
524 }
525
GetValueLength(std::string_view pointStr,size_t valueIndex) const526 size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const
527 {
528 size_t valuePipe = pointStr.find('|', valueIndex);
529 size_t valueLen = pointStr.size() - valueIndex;
530 if (valuePipe != std::string_view::npos) {
531 valueLen = valuePipe - valueIndex;
532 }
533
534 if (valueLen == 0) {
535 return 0;
536 }
537
538 if (pointStr[valueIndex + valueLen - POINT_LENGTH] == '\n') {
539 valueLen--;
540 }
541
542 return valueLen;
543 }
544
HandlerCSF(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const545 ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
546 {
547 // point name
548 size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
549 size_t namelength = GetNameLength(pointStr, nameIndex);
550 if (namelength == 0) {
551 TS_LOGD("point name length is error!");
552 return PARSE_ERROR;
553 }
554 outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength);
555
556 // point value
557 size_t valueIndex = nameIndex + namelength + POINT_LENGTH;
558 size_t valueLen = GetValueLength(pointStr, valueIndex);
559 if (valueLen == 0) {
560 TS_LOGD("point value length is error!");
561 return PARSE_ERROR;
562 }
563
564 std::string valueStr(pointStr.data() + valueIndex, valueLen);
565 if (!base::StrToInt<int64_t>(valueStr).has_value()) {
566 TS_LOGD("point value is error!");
567 return PARSE_ERROR;
568 }
569 outPoint.value_ = base::StrToInt<int64_t>(valueStr).value();
570
571 size_t valuePipe = pointStr.find('|', valueIndex);
572 if (valuePipe != std::string_view::npos) {
573 size_t groupLen = pointStr.size() - valuePipe - POINT_LENGTH;
574 if (groupLen == 0) {
575 return PARSE_ERROR;
576 }
577
578 if (pointStr[pointStr.size() - POINT_LENGTH] == '\n') {
579 groupLen--;
580 }
581
582 outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen);
583 }
584 // traceMetaDatasSrt: taskId|%X%TAG|customCategory|customArgs
585 std::string metaDataStr(pointStr.data() + valueIndex);
586 if (outPoint.phase_ == 'S') {
587 ParseSplitTraceMetaData(metaDataStr, outPoint, true);
588 }
589 return PARSE_SUCCESS;
590 }
591
GetGHNameLength(std::string_view pointStr,size_t nameIndex)592 size_t PrintEventParser::GetGHNameLength(std::string_view pointStr, size_t nameIndex)
593 {
594 size_t endPos = pointStr.find('|', nameIndex);
595 if (endPos == std::string_view::npos) {
596 return 0;
597 }
598 size_t nextEndPos = pointStr.find('|', endPos + 1);
599 if (nextEndPos == std::string_view::npos) {
600 return 0;
601 }
602 return nextEndPos - nameIndex;
603 }
HandlerGH(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const604 ParseResult PrintEventParser::HandlerGH(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
605 {
606 size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
607 size_t nameLength = GetGHNameLength(pointStr, nameIndex);
608 if (nameLength == 0) {
609 TS_LOGD("point name length is error!");
610 return PARSE_ERROR;
611 }
612 outPoint.name_ = std::string_view(pointStr.data() + nameIndex, nameLength);
613 size_t valueIndex = nameIndex + nameLength + POINT_LENGTH;
614 size_t valueLen = GetValueLength(pointStr, valueIndex);
615 if (valueLen == 0) {
616 TS_LOGD("point value length is error!");
617 return PARSE_ERROR;
618 }
619 if (!base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).has_value()) {
620 TS_LOGD("point value is error!");
621 return PARSE_ERROR;
622 }
623 outPoint.value_ = base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).value();
624 return PARSE_SUCCESS;
625 }
626
GetTracePoint(std::string_view pointStr,TracePoint & outPoint) const627 ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint &outPoint) const
628 {
629 if (CheckTracePoint(pointStr) != PARSE_SUCCESS) {
630 return PARSE_ERROR;
631 }
632
633 size_t tGidlength = 0;
634 // we may get wrong format data like tracing_mark_write: E
635 // while the format data must be E|call-tid
636 // please use a regular-format to get all the data
637 outPoint.phase_ = pointStr.front();
638 outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength);
639
640 ParseResult ret = PARSE_ERROR;
641 switch (outPoint.phase_) {
642 case 'B': {
643 ret = HandlerB(pointStr, outPoint, tGidlength);
644 break;
645 }
646 case 'E': {
647 ret = HandlerE();
648 break;
649 }
650 case 'S':
651 case 'F':
652 case 'C': {
653 ret = HandlerCSF(pointStr, outPoint, tGidlength);
654 break;
655 }
656 case 'G':
657 case 'H': {
658 ret = HandlerGH(pointStr, outPoint, tGidlength);
659 break;
660 }
661 default:
662 return PARSE_ERROR;
663 }
664 return ret;
665 }
666
GetThreadGroupId(std::string_view pointStr,size_t & length) const667 uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t &length) const
668 {
669 for (size_t i = MAX_POINT_LENGTH; i < pointStr.size(); i++) {
670 if (pointStr[i] == '|' || pointStr[i] == '\n') {
671 break;
672 }
673
674 if (pointStr[i] < '0' || pointStr[i] > '9') {
675 return PARSE_ERROR;
676 }
677
678 length++;
679 }
680
681 std::string str(pointStr.data() + MAX_POINT_LENGTH, length);
682 return base::StrToInt<uint32_t>(str).value_or(0);
683 }
684 } // namespace TraceStreamer
685 } // namespace SysTuning
686