• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
PrintEventParser(TraceDataCache * dataCache,const TraceStreamerFilters * filter)27 PrintEventParser::PrintEventParser(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
28     : EventParserBase(dataCache, filter)
29 {
30     rsOnDoCompositionEvent_ = traceDataCache_->GetDataIndex(rsOnDoCompositionStr_);
31     eventToFrameFunctionMap_ = {
32         {recvievVsync_, bind(&PrintEventParser::ReciveVsync, this, std::placeholders::_1, std::placeholders::_2,
33                              std::placeholders::_3)},
34         {rsOnDoCompositionEvent_, bind(&PrintEventParser::RSReciveOnDoComposition, this, std::placeholders::_1,
35                                        std::placeholders::_2, std::placeholders::_3)},
36         {onVsyncEvent_, bind(&PrintEventParser::OnVsyncEvent, this, std::placeholders::_1, std::placeholders::_2,
37                              std::placeholders::_3)},
38         {marshRwTransactionData_, bind(&PrintEventParser::OnRwTransaction, this, std::placeholders::_1,
39                                        std::placeholders::_2, std::placeholders::_3)},
40         {rsMainThreadProcessCmd_, bind(&PrintEventParser::OnMainThreadProcessCmd, this, std::placeholders::_1,
41                                        std::placeholders::_2, std::placeholders::_3)},
42         {uvTrace_, bind(&PrintEventParser::DealUvTraceEvent, this, std::placeholders::_1, std::placeholders::_2,
43                         std::placeholders::_3)}};
44 }
45 
ParsePrintEvent(const std::string & comm,uint64_t ts,uint32_t pid,std::string_view event,const BytraceLine & line)46 bool PrintEventParser::ParsePrintEvent(const std::string &comm,
47                                        uint64_t ts,
48                                        uint32_t pid,
49                                        std::string_view event,
50                                        const BytraceLine &line)
51 {
52     streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED);
53     TracePoint point;
54     if (GetTracePoint(event, point) != PARSE_SUCCESS) {
55         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
56         return false;
57     }
58     if (point.tgid_) {
59         // tgid use 'B|' after with 'TGID', the '(TGID)' maybe wrong, eg: xxx-21675 ( 1264) ...: print: B|21675|...
60         const_cast<BytraceLine &>(line).tgid = point.tgid_;
61         streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_);
62     }
63     switch (point.phase_) {
64         case 'B': {
65             ParseBeginEvent(comm, ts, pid, point, line);
66             break;
67         }
68         case 'E': {
69             ParseEndEvent(ts, pid, point);
70             break;
71         }
72         case 'S': {
73             ParseStartEvent(comm, ts, pid, point, line);
74             break;
75         }
76         case 'F': {
77             ParseFinishEvent(ts, pid, point, line);
78             break;
79         }
80         case 'C': {
81             ParseCreateEvent(ts, point);
82             break;
83         }
84         case 'G': {
85             ParseGEvent(ts, pid, point);
86             break;
87         }
88         case 'H': {
89             ParseHEvent(ts, point);
90             break;
91         }
92         default:
93             TS_LOGD("point missing!");
94             return false;
95     }
96     return true;
97 }
ParseBeginEvent(const std::string & comm,uint64_t ts,uint32_t pid,TracePoint & point,const BytraceLine & line)98 void PrintEventParser::ParseBeginEvent(const std::string &comm,
99                                        uint64_t ts,
100                                        uint32_t pid,
101                                        TracePoint &point,
102                                        const BytraceLine &line)
103 {
104     uint32_t index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX,
105                                                               traceDataCache_->GetDataIndex(point.name_));
106     if (index != INVALID_UINT32) {
107         // add distributed data
108         traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(index, point.chainId_, point.spanId_,
109                                                                     point.parentSpanId_, point.flag_);
110         if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) {
111             return;
112         }
113         bool isDiscontinued = false;
114         if (traceDataCache_->TaskPoolTraceEnabled()) {
115             isDiscontinued = streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index);
116         }
117         if (traceDataCache_->AnimationTraceEnabled() && !isDiscontinued) {
118             (void)HandleAnimationBeginEvent(point, index, line);
119         }
120     } else {
121         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST);
122     }
123 }
ParseEndEvent(uint64_t ts,uint32_t pid,const TracePoint & point)124 void PrintEventParser::ParseEndEvent(uint64_t ts, uint32_t pid, const TracePoint &point)
125 {
126     uint32_t index = streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_);
127     HandleFrameSliceEndEvent(ts, point.tgid_, pid, index);
128     if (traceDataCache_->AnimationTraceEnabled()) {
129         streamFilters_->animationFilter_->EndDynamicFrameEvent(ts, index);
130     }
131 }
ParseStartEvent(const std::string & comm,uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)132 void PrintEventParser::ParseStartEvent(const std::string &comm,
133                                        uint64_t ts,
134                                        uint32_t pid,
135                                        const TracePoint &point,
136                                        const BytraceLine &line)
137 {
138     auto cookie = static_cast<int64_t>(point.value_);
139     auto index = streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie,
140                                                                traceDataCache_->GetDataIndex(point.name_));
141     if (point.name_ == onFrameQueeuStartEvent_ && index != INVALID_UINT64) {
142         OnFrameQueueStart(ts, index, point.tgid_);
143     } else if (traceDataCache_->AnimationTraceEnabled() && index != INVALID_UINT64 &&
144                (base::EndWith(comm, onAnimationProcEvent_) ||
145                 base::EndWith(comm, newOnAnimationProcEvent_))) { // the comm is taskName
146         streamFilters_->animationFilter_->StartAnimationEvent(line, point, index);
147     }
148 }
ParseFinishEvent(uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)149 void PrintEventParser::ParseFinishEvent(uint64_t ts, uint32_t pid, const TracePoint &point, const BytraceLine &line)
150 {
151     auto cookie = static_cast<int64_t>(point.value_);
152     auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie,
153                                                                 traceDataCache_->GetDataIndex(point.name_));
154     HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index);
155     if (traceDataCache_->AnimationTraceEnabled()) {
156         streamFilters_->animationFilter_->FinishAnimationEvent(line, index);
157     }
158 }
ParseCreateEvent(uint64_t ts,const TracePoint & point)159 void PrintEventParser::ParseCreateEvent(uint64_t ts, const TracePoint &point)
160 {
161     DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_);
162     uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_);
163     if (internalPid != INVALID_ID) {
164         streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, internalPid, nameIndex, ts,
165                                                              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     } else if (StartWith(traceDataCache_->GetDataFromDict(eventName), uiVsyncTaskStr_)) {
296         DealUIVsyncTaskEvent(eventName, line);
297     }
298     return false;
299 }
ReciveVsync(size_t callStackRow,std::string & args,const BytraceLine & line)300 bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string &args, const BytraceLine &line)
301 {
302     streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_RECEIVED);
303     // args is like "dataCount:24bytes now:211306766162 expectedEnd:211323423844 vsyncId:3179"
304     std::sregex_iterator it(args.begin(), args.end(), recvVsyncPattern_);
305     std::sregex_iterator end;
306     uint64_t now = INVALID_UINT64;
307     uint64_t expectEnd = INVALID_UINT64;
308     uint32_t vsyncId = INVALID_UINT32;
309     while (it != end) {
310         std::smatch match = *it;
311         std::string key = match.str(1);
312         std::string value = match.str(2);
313         if (key == "now") {
314             now = base::StrToInt<uint64_t>(value).value();
315         } else if (key == "expectedEnd") {
316             expectEnd = base::StrToInt<uint64_t>(value).value();
317         } else if (key == "vsyncId") {
318             vsyncId = base::StrToInt<uint64_t>(value).value();
319         }
320         ++it;
321     }
322     if (now == 0 || expectEnd == 0 || vsyncId == 0) {
323         TS_LOGE("Now,expectedEnd or vsyncId should not be 0!");
324         return false;
325     }
326     if (convertVsyncTs_ && traceType_ == TRACE_FILETYPE_H_TRACE) {
327         if (now != INVALID_UINT64) {
328             now = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, now);
329         }
330         if (expectEnd != INVALID_UINT64) {
331             expectEnd = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, expectEnd);
332         }
333     }
334     streamFilters_->frameFilter_->BeginVsyncEvent(line, now, expectEnd, vsyncId, callStackRow);
335     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
336     if (vsyncSliceMap_.count(iTid)) {
337         vsyncSliceMap_[iTid].push_back(callStackRow);
338     } else {
339         vsyncSliceMap_[iTid] = {callStackRow};
340     }
341     return true;
342 }
343 
DealUvTraceEvent(size_t callStackRow,std::string & args,const BytraceLine & line)344 bool PrintEventParser::DealUvTraceEvent(size_t callStackRow, std::string &args, const BytraceLine &line)
345 {
346     Unused(args);
347     // deal H:UV_TRACE event, this event's thread is not main thread.
348     // this event do not has expect now and end.
349     streamFilters_->frameFilter_->BeginUVTraceEvent(line, callStackRow);
350     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
351     if (vsyncSliceMap_.count(iTid)) {
352         vsyncSliceMap_[iTid].push_back(callStackRow);
353     } else {
354         vsyncSliceMap_[iTid] = {callStackRow};
355     }
356     return true;
357 }
358 
DealUIVsyncTaskEvent(DataIndex eventName,const BytraceLine & line)359 bool PrintEventParser::DealUIVsyncTaskEvent(DataIndex eventName, const BytraceLine &line)
360 {
361     auto eventNameStr = traceDataCache_->GetDataFromDict(eventName);
362     std::sregex_iterator it(eventNameStr.begin(), eventNameStr.end(), uiVsyncTaskPattern_);
363     std::sregex_iterator end;
364     while (it != end) {
365         std::smatch match = *it;
366         std::string key = match.str(1);
367         std::string value = match.str(2);
368         if (key == "vsyncID") {
369             (void)streamFilters_->frameFilter_->UpdateVsyncId(line, base::StrToInt<uint32_t>(value).value());
370             return true;
371         }
372         ++it;
373     }
374     return false;
375 }
OnVsyncEvent(size_t callStackRow,std::string & args,const BytraceLine & line)376 bool PrintEventParser::OnVsyncEvent(size_t callStackRow, std::string &args, const BytraceLine &line)
377 {
378     Unused(args);
379     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
380     if (!vsyncSliceMap_.count(iTid)) {
381         return false;
382     }
383     // when there are mutiple nested OnVsyncEvent,only handle the OnvsyncEvent of the next layer under ReceiveVsync
384     if (vsyncSliceMap_[iTid].size() >= maxVsyncEventSize_) {
385         return false;
386     }
387     vsyncSliceMap_[iTid].push_back(callStackRow);
388     return true;
389 }
RSReciveOnDoComposition(size_t callStackRow,std::string & args,const BytraceLine & line)390 bool PrintEventParser::RSReciveOnDoComposition(size_t callStackRow, std::string &args, const BytraceLine &line)
391 {
392     streamFilters_->statFilter_->IncreaseStat(TRACE_ON_DO_COMPOSITION, STAT_EVENT_RECEIVED);
393     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
394     (void)streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(iTid);
395     return true;
396 }
OnRwTransaction(size_t callStackRow,std::string & args,const BytraceLine & line)397 bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string &args, const BytraceLine &line)
398 {
399     // H:MarshRSTransactionData cmdCount:20 transactionFlag:[3799,8] isUni:1
400     std::smatch match;
401     if (std::regex_search(args, match, transFlagPattern_)) {
402         std::string mainTheadId = match.str(1);
403         std::string flag2 = match.str(2);
404         // use to update dstRenderSlice_
405         auto mainThreadId =
406             streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(mainTheadId).value());
407         // use to update vsyncRenderSlice_
408         auto currentThreadId = streamFilters_->processFilter_->GetInternalTid(line.pid);
409         return streamFilters_->frameFilter_->BeginRSTransactionData(
410             currentThreadId, base::StrToInt<uint32_t>(flag2).value(), mainThreadId);
411     }
412     return true;
413 }
OnMainThreadProcessCmd(size_t callStackRow,std::string & args,const BytraceLine & line)414 bool PrintEventParser::OnMainThreadProcessCmd(size_t callStackRow, std::string &args, const BytraceLine &line)
415 {
416     std::sregex_iterator it(args.begin(), args.end(), mainProcessCmdPattern_);
417     std::sregex_iterator end;
418     std::vector<FrameFilter::FrameMap> frames;
419     while (it != end) {
420         std::smatch match = *it;
421         std::string value1 = match.str(1);
422         std::string value2 = match.str(2);
423         frames.push_back({streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(value1).value()),
424                           base::StrToInt<uint32_t>(value2).value()});
425         ++it;
426     }
427     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
428     return streamFilters_->frameFilter_->BeginProcessCommandUni(iTid, frames, callStackRow);
429 }
OnFrameQueueStart(uint64_t ts,size_t callStackRow,uint64_t pid)430 bool PrintEventParser::OnFrameQueueStart(uint64_t ts, size_t callStackRow, uint64_t pid)
431 {
432     streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_RECEIVED);
433     auto iTid = streamFilters_->processFilter_->GetInternalTid(pid);
434     if (streamFilters_->frameFilter_->StartFrameQueue(ts, iTid)) {
435         frameCallIds_.push_back(callStackRow);
436     }
437     return true;
438 }
HandleFrameSliceEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)439 void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
440 {
441     // it can be frame or slice
442     auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
443     if (vsyncSliceMap_.count(iTid)) {
444         auto pos = std::find(vsyncSliceMap_[iTid].begin(), vsyncSliceMap_[iTid].end(), callStackRow);
445         if (pos != vsyncSliceMap_[iTid].end()) {
446             if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) {
447                 streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH);
448             }
449             vsyncSliceMap_[iTid].erase(pos);
450         }
451     }
452     return;
453 }
454 
HandleFrameQueueEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)455 void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
456 {
457     // it can be frame or slice
458     auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
459     auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow);
460     if (pos != frameCallIds_.end()) {
461         TS_LOGD("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 "", ts, tid);
462         if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) {
463             streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH);
464             TS_LOGW("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 " failed", ts, tid);
465         }
466         frameCallIds_.erase(pos);
467     }
468     return;
469 }
HandlerE(void)470 ParseResult PrintEventParser::HandlerE(void)
471 {
472     return PARSE_SUCCESS;
473 }
474 
GetNameLength(std::string_view pointStr,size_t nameIndex)475 size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex)
476 {
477     size_t namelength = 0;
478     for (size_t i = nameIndex; i < pointStr.size(); i++) {
479         if (pointStr[i] == ' ') {
480             namelength = i - nameIndex;
481         }
482         if (pointStr[i] == '|') {
483             namelength = i - nameIndex;
484             break;
485         }
486     }
487     return namelength;
488 }
489 
GetValueLength(std::string_view pointStr,size_t valueIndex) const490 size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const
491 {
492     size_t valuePipe = pointStr.find('|', valueIndex);
493     size_t valueLen = pointStr.size() - valueIndex;
494     if (valuePipe != std::string_view::npos) {
495         valueLen = valuePipe - valueIndex;
496     }
497 
498     if (valueLen == 0) {
499         return 0;
500     }
501 
502     if (pointStr[valueIndex + valueLen - POINT_LENGTH] == '\n') {
503         valueLen--;
504     }
505 
506     return valueLen;
507 }
508 
HandlerCSF(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const509 ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
510 {
511     // point name
512     size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
513     size_t namelength = GetNameLength(pointStr, nameIndex);
514     if (namelength == 0) {
515         TS_LOGD("point name length is error!");
516         return PARSE_ERROR;
517     }
518     outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength);
519 
520     // point value
521     size_t valueIndex = nameIndex + namelength + POINT_LENGTH;
522     size_t valueLen = GetValueLength(pointStr, valueIndex);
523     if (valueLen == 0) {
524         TS_LOGD("point value length is error!");
525         return PARSE_ERROR;
526     }
527 
528     std::string valueStr(pointStr.data() + valueIndex, valueLen);
529     if (!base::StrToInt<int64_t>(valueStr).has_value()) {
530         TS_LOGD("point value is error!");
531         return PARSE_ERROR;
532     }
533     outPoint.value_ = base::StrToInt<int64_t>(valueStr).value();
534 
535     size_t valuePipe = pointStr.find('|', valueIndex);
536     if (valuePipe != std::string_view::npos) {
537         size_t groupLen = pointStr.size() - valuePipe - POINT_LENGTH;
538         if (groupLen == 0) {
539             return PARSE_ERROR;
540         }
541 
542         if (pointStr[pointStr.size() - POINT_LENGTH] == '\n') {
543             groupLen--;
544         }
545 
546         outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen);
547     }
548 
549     return PARSE_SUCCESS;
550 }
551 
GetGHNameLength(std::string_view pointStr,size_t nameIndex)552 size_t PrintEventParser::GetGHNameLength(std::string_view pointStr, size_t nameIndex)
553 {
554     size_t endPos = pointStr.find('|', nameIndex);
555     if (endPos == std::string_view::npos) {
556         return 0;
557     }
558     size_t nextEndPos = pointStr.find('|', endPos + 1);
559     if (nextEndPos == std::string_view::npos) {
560         return 0;
561     }
562     return nextEndPos - nameIndex;
563 }
HandlerGH(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const564 ParseResult PrintEventParser::HandlerGH(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
565 {
566     size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
567     size_t nameLength = GetGHNameLength(pointStr, nameIndex);
568     if (nameLength == 0) {
569         TS_LOGD("point name length is error!");
570         return PARSE_ERROR;
571     }
572     outPoint.name_ = std::string_view(pointStr.data() + nameIndex, nameLength);
573     size_t valueIndex = nameIndex + nameLength + POINT_LENGTH;
574     size_t valueLen = GetValueLength(pointStr, valueIndex);
575     if (valueLen == 0) {
576         TS_LOGD("point value length is error!");
577         return PARSE_ERROR;
578     }
579     if (!base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).has_value()) {
580         TS_LOGD("point value is error!");
581         return PARSE_ERROR;
582     }
583     outPoint.value_ = base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).value();
584     return PARSE_SUCCESS;
585 }
586 
GetTracePoint(std::string_view pointStr,TracePoint & outPoint) const587 ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint &outPoint) const
588 {
589     if (CheckTracePoint(pointStr) != PARSE_SUCCESS) {
590         return PARSE_ERROR;
591     }
592 
593     size_t tGidlength = 0;
594     // we may get wrong format data like tracing_mark_write: E
595     // while the format data must be E|call-tid
596     // please use a regular-format to get all the data
597     outPoint.phase_ = pointStr.front();
598     outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength);
599 
600     ParseResult ret = PARSE_ERROR;
601     switch (outPoint.phase_) {
602         case 'B': {
603             ret = HandlerB(pointStr, outPoint, tGidlength);
604             break;
605         }
606         case 'E': {
607             ret = HandlerE();
608             break;
609         }
610         case 'S':
611         case 'F':
612         case 'C': {
613             ret = HandlerCSF(pointStr, outPoint, tGidlength);
614             break;
615         }
616         case 'G':
617         case 'H': {
618             ret = HandlerGH(pointStr, outPoint, tGidlength);
619             break;
620         }
621         default:
622             return PARSE_ERROR;
623     }
624     return ret;
625 }
626 
GetThreadGroupId(std::string_view pointStr,size_t & length) const627 uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t &length) const
628 {
629     for (size_t i = MAX_POINT_LENGTH; i < pointStr.size(); i++) {
630         if (pointStr[i] == '|' || pointStr[i] == '\n') {
631             break;
632         }
633 
634         if (pointStr[i] < '0' || pointStr[i] > '9') {
635             return PARSE_ERROR;
636         }
637 
638         length++;
639     }
640 
641     std::string str(pointStr.data() + MAX_POINT_LENGTH, length);
642     return base::StrToInt<uint32_t>(str).value_or(0);
643 }
644 } // namespace TraceStreamer
645 } // namespace SysTuning
646