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 "print_event_parser.h"
16 #include "animation_filter.h"
17 #include "clock_filter_ex.h"
18 #include "frame_filter.h"
19 #include "stat_filter.h"
20 #include "string_to_numerical.h"
21 #include <cinttypes>
22 namespace SysTuning {
23 namespace TraceStreamer {
24 const uint8_t POINT_LENGTH = 1;
25 const uint8_t MAX_POINT_LENGTH = 2;
PrintEventParser(TraceDataCache * dataCache,const TraceStreamerFilters * filter)26 PrintEventParser::PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter)
27 : EventParserBase(dataCache, filter)
28 {
29 eventToFrameFunctionMap_ = {
30 {recvievVsync_, bind(&PrintEventParser::ReciveVsync, this, std::placeholders::_1, std::placeholders::_2,
31 std::placeholders::_3)},
32 {rsOnDoCompositionEvent_, bind(&PrintEventParser::RSReciveOnDoComposition, this, std::placeholders::_1,
33 std::placeholders::_2, std::placeholders::_3)},
34 {marshRwTransactionData_, bind(&PrintEventParser::OnRwTransaction, this, std::placeholders::_1,
35 std::placeholders::_2, std::placeholders::_3)},
36 {rsMainThreadProcessCmd_, bind(&PrintEventParser::OnMainThreadProcessCmd, this, std::placeholders::_1,
37 std::placeholders::_2, std::placeholders::_3)}};
38 }
39
ParsePrintEvent(const std::string & comm,uint64_t ts,uint32_t pid,std::string_view event,const BytraceLine & line)40 bool PrintEventParser::ParsePrintEvent(const std::string& comm,
41 uint64_t ts,
42 uint32_t pid,
43 std::string_view event,
44 const BytraceLine& line)
45 {
46 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED);
47 TracePoint point;
48 if (GetTracePoint(event, point) != PARSE_SUCCESS) {
49 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
50 return false;
51 }
52 if (point.tgid_) {
53 // tgid use 'B|' after with 'TGID', the '(TGID)' maybe wrong, eg: xxx-21675 ( 1264) ...: print: B|21675|...
54 const_cast<BytraceLine&>(line).tgid = point.tgid_;
55 streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_);
56 }
57 switch (point.phase_) {
58 case 'B': {
59 ParseBeginEvent(comm, ts, pid, point, line);
60 break;
61 }
62 case 'E': {
63 ParseEndEvent(ts, pid, point);
64 break;
65 }
66 case 'S': {
67 ParseStartEvent(comm, ts, pid, point, line);
68 break;
69 }
70 case 'F': {
71 ParseFinishEvent(ts, pid, point, line);
72 break;
73 }
74 case 'C': {
75 ParseCreateEvent(ts, point);
76 break;
77 }
78 default:
79 TS_LOGD("point missing!");
80 return false;
81 }
82 return true;
83 }
ParseBeginEvent(const std::string & comm,uint64_t ts,uint32_t pid,TracePoint & point,const BytraceLine & line)84 void PrintEventParser::ParseBeginEvent(const std::string& comm,
85 uint64_t ts,
86 uint32_t pid,
87 TracePoint& point,
88 const BytraceLine& line)
89 {
90 uint32_t index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX,
91 traceDataCache_->GetDataIndex(point.name_));
92 if (index != INVALID_UINT32) {
93 // add distributed data
94 traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(index, point.chainId_, point.spanId_,
95 point.parentSpanId_, point.flag_, point.args_);
96 if (pid == point.tgid_) {
97 if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) {
98 return;
99 }
100 }
101 bool isDiscontinued = false;
102 if (traceDataCache_->TaskPoolTraceEnabled()) {
103 isDiscontinued = streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index);
104 }
105 if (traceDataCache_->AnimationTraceEnabled() && !isDiscontinued) {
106 (void)HandleAnimationBeginEvent(point, index, line);
107 }
108 } else {
109 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST);
110 }
111 }
ParseEndEvent(uint64_t ts,uint32_t pid,const TracePoint & point)112 void PrintEventParser::ParseEndEvent(uint64_t ts, uint32_t pid, const TracePoint& point)
113 {
114 uint32_t index = streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_);
115 if (pid == point.tgid_) {
116 HandleFrameSliceEndEvent(ts, point.tgid_, pid, index);
117 }
118 if (traceDataCache_->AnimationTraceEnabled()) {
119 streamFilters_->animationFilter_->EndDynamicFrameEvent(ts, index);
120 }
121 }
ParseStartEvent(const std::string & comm,uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)122 void PrintEventParser::ParseStartEvent(const std::string& comm,
123 uint64_t ts,
124 uint32_t pid,
125 const TracePoint& point,
126 const BytraceLine& line)
127 {
128 auto cookie = static_cast<uint64_t>(point.value_);
129 auto index = streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie,
130 traceDataCache_->GetDataIndex(point.name_));
131 if (point.name_ == onFrameQueeuStartEvent_ && index != INVALID_UINT64) {
132 OnFrameQueueStart(ts, index, point.tgid_);
133 } else if (traceDataCache_->AnimationTraceEnabled() && index != INVALID_UINT64 &&
134 base::EndWith(comm, onAnimationProcEvent_)) { // the comm is taskName
135 streamFilters_->animationFilter_->StartAnimationEvent(line, point, index);
136 }
137 }
ParseFinishEvent(uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)138 void PrintEventParser::ParseFinishEvent(uint64_t ts, uint32_t pid, const TracePoint& point, const BytraceLine& line)
139 {
140 auto cookie = static_cast<uint64_t>(point.value_);
141 auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie,
142 traceDataCache_->GetDataIndex(point.name_));
143 HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index);
144 if (traceDataCache_->AnimationTraceEnabled()) {
145 streamFilters_->animationFilter_->FinishAnimationEvent(line, index);
146 }
147 }
ParseCreateEvent(uint64_t ts,const TracePoint & point)148 void PrintEventParser::ParseCreateEvent(uint64_t ts, const TracePoint& point)
149 {
150 DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_);
151 uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_);
152 if (internalPid != INVALID_ID) {
153 streamFilters_->processMeasureFilter_->AppendNewMeasureData(internalPid, nameIndex, ts, point.value_);
154 streamFilters_->processFilter_->AddProcessMemory(internalPid);
155 } else {
156 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
157 }
158 }
HandleAnimationBeginEvent(const TracePoint & point,size_t callStackRow,const BytraceLine & line)159 bool PrintEventParser::HandleAnimationBeginEvent(const TracePoint& point, size_t callStackRow, const BytraceLine& line)
160 {
161 if (!streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line)) {
162 return streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, callStackRow);
163 }
164 return true;
165 }
SetTraceType(TraceFileType traceType)166 void PrintEventParser::SetTraceType(TraceFileType traceType)
167 {
168 traceType_ = traceType;
169 }
SetTraceClockId(BuiltinClocks clock)170 void PrintEventParser::SetTraceClockId(BuiltinClocks clock)
171 {
172 if (clock != clock_) {
173 clock_ = clock;
174 }
175 }
Finish()176 void PrintEventParser::Finish()
177 {
178 eventToFrameFunctionMap_.clear();
179 frameCallIds_.clear();
180 vsyncSliceIds_.clear();
181 streamFilters_->animationFilter_->Clear();
182 streamFilters_->frameFilter_->Clear();
183 }
CheckTracePoint(std::string_view pointStr) const184 ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const
185 {
186 if (pointStr.size() == 0) {
187 TS_LOGD("get trace point data size is 0!");
188 return PARSE_ERROR;
189 }
190
191 std::string clockSyncSts = "trace_event_clock_sync";
192 if (pointStr.compare(0, clockSyncSts.length(), clockSyncSts.c_str()) == 0) {
193 TS_LOGD("skip trace point :%s!", clockSyncSts.c_str());
194 return PARSE_ERROR;
195 }
196
197 if (pointStr.find_first_of('B') != 0 && pointStr.find_first_of('E') != 0 && pointStr.find_first_of('C') != 0 &&
198 pointStr.find_first_of('S') != 0 && pointStr.find_first_of('F') != 0) {
199 TS_LOGD("trace point not supported : [%c] !", pointStr[0]);
200 return PARSE_ERROR;
201 }
202
203 if (pointStr.find_first_of('E') != 0 && pointStr.size() == 1) {
204 TS_LOGD("point string size error!");
205 return PARSE_ERROR;
206 }
207
208 if (pointStr.size() >= MAX_POINT_LENGTH) {
209 if ((pointStr[1] != '|') && (pointStr[1] != '\n')) {
210 TS_LOGD("not support data formart!");
211 return PARSE_ERROR;
212 }
213 }
214
215 return PARSE_SUCCESS;
216 }
217
GetPointNameForBegin(std::string_view pointStr,size_t tGidlength) const218 std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const
219 {
220 size_t index = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
221
222 size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0);
223 std::string_view name = std::string_view(pointStr.data() + index, length);
224 // remove space at the end
225 name = std::string_view(name.data(), name.find_last_not_of(" ") + 1);
226 return name;
227 }
228
HandlerB(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const229 ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const
230 {
231 outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength);
232 if (outPoint.name_.empty()) {
233 TS_LOGD("point name is empty!");
234 return PARSE_ERROR;
235 }
236 // Use $# to differentiate distributed data
237 if (outPoint.name_.find("$#") == std::string::npos) {
238 auto space = outPoint.name_.find(' ');
239 if (space != std::string::npos) {
240 outPoint.funcPrefix_ = outPoint.name_.substr(0, space);
241 outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.funcPrefix_);
242 outPoint.funcArgs_ = outPoint.name_.substr(space + 1);
243 } else {
244 outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.name_);
245 }
246 return PARSE_SUCCESS;
247 }
248 // Resolve distributed calls
249 // the normal data mybe like:
250 // system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#"
251 // "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \
252 // system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n
253 const std::regex distributeMatcher = std::regex(R"((?:^\[([a-z0-9]+),(\d+),(\d+)\]:?([CS]?)\$#)?(.*)\$#(.*)$)");
254 std::smatch matcheLine;
255 bool matched = std::regex_match(outPoint.name_, matcheLine, distributeMatcher);
256 if (matched) {
257 size_t index = 0;
258 outPoint.chainId_ = matcheLine[++index].str();
259 outPoint.spanId_ = matcheLine[++index].str();
260 outPoint.parentSpanId_ = matcheLine[++index].str();
261 outPoint.flag_ = matcheLine[++index].str();
262 outPoint.name_ = matcheLine[++index].str();
263 outPoint.args_ = matcheLine[++index].str();
264 }
265 return PARSE_SUCCESS;
266 }
267
HandleFrameSliceBeginEvent(DataIndex eventName,size_t callStackRow,std::string & args,const BytraceLine & line)268 bool PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName,
269 size_t callStackRow,
270 std::string& args,
271 const BytraceLine& line)
272 {
273 auto it = eventToFrameFunctionMap_.find(eventName);
274 if (it != eventToFrameFunctionMap_.end()) {
275 it->second(callStackRow, args, line);
276 return true;
277 }
278 return false;
279 }
ReciveVsync(size_t callStackRow,std::string & args,const BytraceLine & line)280 bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string& args, const BytraceLine& line)
281 {
282 streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_RECEIVED);
283 // args is like "dataCount:24bytes now:211306766162 expectedEnd:211323423844 vsyncId:3179"
284 std::sregex_iterator it(args.begin(), args.end(), recvVsyncPattern_);
285 std::sregex_iterator end;
286 uint64_t now = INVALID_UINT64;
287 uint64_t expectEnd = INVALID_UINT64;
288 uint32_t vsyncId = INVALID_UINT32;
289 while (it != end) {
290 std::smatch match = *it;
291 std::string key = match.str(1);
292 std::string value = match.str(2);
293 if (key == "now") {
294 now = base::StrToInt<uint64_t>(value).value();
295 } else if (key == "expectedEnd") {
296 expectEnd = base::StrToInt<uint64_t>(value).value();
297 } else if (key == "vsyncId") {
298 vsyncId = base::StrToInt<uint64_t>(value).value();
299 }
300 ++it;
301 }
302 if (convertVsyncTs_ && traceType_ == TRACE_FILETYPE_H_TRACE) {
303 if (now != INVALID_UINT64) {
304 now = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, now);
305 }
306 if (expectEnd != INVALID_UINT64) {
307 expectEnd = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, expectEnd);
308 }
309 }
310 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
311 auto iPid = streamFilters_->processFilter_->GetInternalPid(line.tgid);
312 streamFilters_->frameFilter_->BeginVsyncEvent(line.ts, iPid, iTid, now, expectEnd, vsyncId, callStackRow);
313 vsyncSliceIds_.push_back(callStackRow);
314 return true;
315 }
RSReciveOnDoComposition(size_t callStackRow,std::string & args,const BytraceLine & line)316 bool PrintEventParser::RSReciveOnDoComposition(size_t callStackRow, std::string& args, const BytraceLine& line)
317 {
318 streamFilters_->statFilter_->IncreaseStat(TRACE_ON_DO_COMPOSITION, STAT_EVENT_RECEIVED);
319 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
320 (void)streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(line.ts, iTid);
321 return true;
322 }
OnRwTransaction(size_t callStackRow,std::string & args,const BytraceLine & line)323 bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string& args, const BytraceLine& line)
324 {
325 // H:MarshRSTransactionData cmdCount:20 transactionFlag:[3799,8] isUni:1
326 std::smatch match;
327 if (std::regex_search(args, match, transFlagPattern_)) {
328 std::string flag2 = match.str(2);
329 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
330 return streamFilters_->frameFilter_->BeginRSTransactionData(line.ts, iTid,
331 base::StrToInt<uint32_t>(flag2).value());
332 }
333 return true;
334 }
OnMainThreadProcessCmd(size_t callStackRow,std::string & args,const BytraceLine & line)335 bool PrintEventParser::OnMainThreadProcessCmd(size_t callStackRow, std::string& args, const BytraceLine& line)
336 {
337 std::sregex_iterator it(args.begin(), args.end(), mainProcessCmdPattern);
338 std::sregex_iterator end;
339 std::vector<FrameFilter::FrameMap> frames;
340 while (it != end) {
341 std::smatch match = *it;
342 std::string value1 = match.str(1);
343 std::string value2 = match.str(2);
344 frames.push_back({streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(value1).value()),
345 base::StrToInt<uint32_t>(value2).value()});
346 ++it;
347 }
348 auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
349 return streamFilters_->frameFilter_->BeginProcessCommandUni(line.ts, iTid, frames, callStackRow);
350 }
OnFrameQueueStart(uint64_t ts,size_t callStackRow,uint64_t pid)351 bool PrintEventParser::OnFrameQueueStart(uint64_t ts, size_t callStackRow, uint64_t pid)
352 {
353 streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_RECEIVED);
354 auto iTid = streamFilters_->processFilter_->GetInternalTid(pid);
355 if (streamFilters_->frameFilter_->StartFrameQueue(ts, iTid)) {
356 frameCallIds_.push_back(callStackRow);
357 }
358 return true;
359 }
HandleFrameSliceEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)360 void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
361 {
362 // it can be frame or slice
363 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
364 auto pos = std::find(vsyncSliceIds_.begin(), vsyncSliceIds_.end(), callStackRow);
365 if (pos != vsyncSliceIds_.end()) {
366 if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) {
367 streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH);
368 }
369 vsyncSliceIds_.erase(pos);
370 }
371 return;
372 }
373
HandleFrameQueueEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)374 void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
375 {
376 // it can be frame or slice
377 auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
378 auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow);
379 if (pos != frameCallIds_.end()) {
380 TS_LOGD("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 "", ts, tid);
381 if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) {
382 streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH);
383 TS_LOGW("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 " failed", ts, tid);
384 }
385 frameCallIds_.erase(pos);
386 }
387 return;
388 }
HandlerE(void)389 ParseResult PrintEventParser::HandlerE(void)
390 {
391 return PARSE_SUCCESS;
392 }
393
GetNameLength(std::string_view pointStr,size_t nameIndex)394 size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex)
395 {
396 size_t namelength = 0;
397 for (size_t i = nameIndex; i < pointStr.size(); i++) {
398 if (pointStr[i] == ' ') {
399 namelength = i - nameIndex;
400 }
401 if (pointStr[i] == '|') {
402 namelength = i - nameIndex;
403 break;
404 }
405 }
406 return namelength;
407 }
408
GetValueLength(std::string_view pointStr,size_t valueIndex) const409 size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const
410 {
411 size_t valuePipe = pointStr.find('|', valueIndex);
412 size_t valueLen = pointStr.size() - valueIndex;
413 if (valuePipe != std::string_view::npos) {
414 valueLen = valuePipe - valueIndex;
415 }
416
417 if (valueLen == 0) {
418 return 0;
419 }
420
421 if (pointStr[valueIndex + valueLen - POINT_LENGTH] == '\n') {
422 valueLen--;
423 }
424
425 return valueLen;
426 }
427
HandlerCSF(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const428 ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const
429 {
430 // point name
431 size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
432 size_t namelength = GetNameLength(pointStr, nameIndex);
433 if (namelength == 0) {
434 TS_LOGD("point name length is error!");
435 return PARSE_ERROR;
436 }
437 outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength);
438
439 // point value
440 size_t valueIndex = nameIndex + namelength + POINT_LENGTH;
441 size_t valueLen = GetValueLength(pointStr, valueIndex);
442 if (valueLen == 0) {
443 TS_LOGD("point value length is error!");
444 return PARSE_ERROR;
445 }
446
447 std::string valueStr(pointStr.data() + valueIndex, valueLen);
448 if (!base::StrToInt<uint64_t>(valueStr).has_value()) {
449 TS_LOGD("point value is error!");
450 return PARSE_ERROR;
451 }
452 outPoint.value_ = base::StrToInt<uint64_t>(valueStr).value();
453
454 size_t valuePipe = pointStr.find('|', valueIndex);
455 if (valuePipe != std::string_view::npos) {
456 size_t groupLen = pointStr.size() - valuePipe - POINT_LENGTH;
457 if (groupLen == 0) {
458 return PARSE_ERROR;
459 }
460
461 if (pointStr[pointStr.size() - POINT_LENGTH] == '\n') {
462 groupLen--;
463 }
464
465 outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen);
466 }
467
468 return PARSE_SUCCESS;
469 }
470
GetTracePoint(std::string_view pointStr,TracePoint & outPoint) const471 ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint& outPoint) const
472 {
473 if (CheckTracePoint(pointStr) != PARSE_SUCCESS) {
474 return PARSE_ERROR;
475 }
476
477 size_t tGidlength = 0;
478 // we may get wrong format data like tracing_mark_write: E
479 // while the format data must be E|call-tid
480 // please use a regular-format to get all the data
481 outPoint.phase_ = pointStr.front();
482 outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength);
483
484 ParseResult ret = PARSE_ERROR;
485 switch (outPoint.phase_) {
486 case 'B': {
487 ret = HandlerB(pointStr, outPoint, tGidlength);
488 break;
489 }
490 case 'E': {
491 ret = HandlerE();
492 break;
493 }
494 case 'S':
495 case 'F':
496 case 'C': {
497 ret = HandlerCSF(pointStr, outPoint, tGidlength);
498 break;
499 }
500 default:
501 return PARSE_ERROR;
502 }
503 return ret;
504 }
505
GetThreadGroupId(std::string_view pointStr,size_t & length) const506 uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t& length) const
507 {
508 for (size_t i = MAX_POINT_LENGTH; i < pointStr.size(); i++) {
509 if (pointStr[i] == '|' || pointStr[i] == '\n') {
510 break;
511 }
512
513 if (pointStr[i] < '0' || pointStr[i] > '9') {
514 return PARSE_ERROR;
515 }
516
517 length++;
518 }
519
520 std::string str(pointStr.data() + MAX_POINT_LENGTH, length);
521 return base::StrToInt<uint32_t>(str).value_or(0);
522 }
523 } // namespace TraceStreamer
524 } // namespace SysTuning
525