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