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