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
16 #include "pbreader_parser.h"
17 #include <unistd.h>
18 #include "app_start_filter.h"
19 #include "binder_filter.h"
20 #include "common_types.pbreader.h"
21 #include "cpu_filter.h"
22 #include "data_area.h"
23 #ifdef ENABLE_HTRACE
24 #include "ftrace_event.pbreader.h"
25 #include "trace_plugin_result.pbreader.h"
26 #endif
27 #ifdef ENABLE_MEMORY
28 #include "memory_plugin_result.pbreader.h"
29 #endif
30 #include "stat_filter.h"
31 #if IS_WASM
32 #include "wasm_func.h"
33 #endif
34 namespace SysTuning {
35 namespace TraceStreamer {
PbreaderParser(TraceDataCache * dataCache,const TraceStreamerFilters * filters)36 PbreaderParser::PbreaderParser(TraceDataCache *dataCache, const TraceStreamerFilters *filters)
37 : ParserBase(filters),
38 pbreaderClockDetailParser_(std::make_unique<PbreaderClockDetailParser>(dataCache, filters)),
39 #ifdef ENABLE_HTRACE
40 htraceCpuDetailParser_(std::make_unique<HtraceCpuDetailParser>(dataCache, filters)),
41 htraceSymbolsDetailParser_(std::make_unique<HtraceSymbolsDetailParser>(dataCache, filters)),
42 #endif
43 #ifdef ENABLE_FFRT
44 pbreaderFfrtParser_(
45 std::make_unique<PbreaderFfrtDetailParser>(dataCache, filters, htraceCpuDetailParser_->eventParser_.get())),
46 #endif
47 #ifdef ENABLE_MEMORY
48 pbreaderMemParser_(std::make_unique<PbreaderMemParser>(dataCache, filters)),
49 #endif
50 #ifdef ENABLE_HILOG
51 pbreaderHiLogParser_(std::make_unique<PbreaderHiLogParser>(dataCache, filters)),
52 #endif
53 #ifdef ENABLE_NATIVE_HOOK
54 pbreaderNativeHookParser_(std::make_unique<PbreaderNativeHookParser>(dataCache, filters)),
55 #endif
56 #ifdef ENABLE_HTDUMP
57 pbreaderHidumpParser_(std::make_unique<PbreaderHidumpParser>(dataCache, filters)),
58 #endif
59 #ifdef ENABLE_CPUDATA
60 cpuUsageParser_(std::make_unique<PbreaderCpuDataParser>(dataCache, filters)),
61 #endif
62 #ifdef ENABLE_NETWORK
63 networkParser_(std::make_unique<PbreaderNetworkParser>(dataCache, filters)),
64 #endif
65 #ifdef ENABLE_DISKIO
66 diskIOParser_(std::make_unique<PbreaderDiskIOParser>(dataCache, filters)),
67 #endif
68 #ifdef ENABLE_PROCESS
69 processParser_(std::make_unique<PbreaderProcessParser>(dataCache, filters)),
70 #endif
71 #ifdef ENABLE_HISYSEVENT
72 hisyseventParser_(std::make_unique<PbreaderHisyseventParser>(dataCache, filters)),
73 #endif
74 #ifdef ENABLE_ARKTS
75 jsMemoryParser_(std::make_unique<PbreaderJSMemoryParser>(dataCache, filters)),
76 #endif
77 #ifdef ENABLE_HIPERF
78 perfDataParser_(std::make_unique<PerfDataParser>(dataCache, filters)),
79 #endif
80 #ifdef ENABLE_EBPF
81 ebpfDataParser_(std::make_unique<EbpfDataParser>(dataCache, filters)),
82 #endif
83 #ifdef ENABLE_XPOWER
84 xpowerParser_(std::make_unique<PbreaderXpowerParser>(dataCache, filters)),
85 #endif
86 #ifdef ENABLE_STREAM_EXTEND
87 pbreaderStreamParser_(std::make_unique<PbreaderStreamParser>(dataCache, filters)),
88 #endif
89 traceDataCache_(dataCache)
90 {
91 InitPluginNameIndex();
92 if (traceDataCache_->supportThread_) {
93 dataSegArray_ = std::make_unique<PbreaderDataSegment[]>(maxSegArraySize);
94 } else {
95 dataSegArray_ = std::make_unique<PbreaderDataSegment[]>(1);
96 }
97 }
InitHookPluginNameIndex()98 inline void PbreaderParser::InitHookPluginNameIndex()
99 {
100 #ifdef ENABLE_NATIVE_HOOK
101 nativeHookPluginIndex_.insert(traceDataCache_->GetDataIndex("nativehook"));
102 nativeHookPluginIndex_.insert(traceDataCache_->GetDataIndex("hookdaemon"));
103 nativeHookConfigIndex_ = traceDataCache_->GetDataIndex("nativehook_config");
104 supportPluginNameIndex_.insert(nativeHookPluginIndex_.begin(), nativeHookPluginIndex_.end());
105 supportPluginNameIndex_.insert(nativeHookConfigIndex_);
106 #endif
107 }
InitMemoryPluginNameIndex()108 inline void PbreaderParser::InitMemoryPluginNameIndex()
109 {
110 #ifdef ENABLE_MEMORY
111 memPluginIndex_ = traceDataCache_->GetDataIndex("memory-plugin");
112 memoryPluginConfigIndex_ = traceDataCache_->GetDataIndex("memory-plugin_config");
113 supportPluginNameIndex_.insert(memPluginIndex_);
114 supportPluginNameIndex_.insert(memoryPluginConfigIndex_);
115 #endif
116 }
InitHiPluginNameIndex()117 inline void PbreaderParser::InitHiPluginNameIndex()
118 {
119 #ifdef ENABLE_HTDUMP
120 hidumpPluginIndex_.insert(traceDataCache_->GetDataIndex("hidump-plugin"));
121 hidumpPluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libhidumpplugin.z.so"));
122 supportPluginNameIndex_.insert(hidumpPluginIndex_.begin(), hidumpPluginIndex_.end());
123 #endif
124 #ifdef ENABLE_HILOG
125 hilogPluginIndex_.insert(traceDataCache_->GetDataIndex("hilog-plugin"));
126 hilogPluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libhilogplugin.z.so"));
127 supportPluginNameIndex_.insert(hilogPluginIndex_.begin(), hilogPluginIndex_.end());
128 #endif
129 #ifdef ENABLE_HISYSEVENT
130 hisyseventPluginIndex_ = traceDataCache_->GetDataIndex("hisysevent-plugin");
131 hisyseventPluginConfigIndex_ = traceDataCache_->GetDataIndex("hisysevent-plugin_config");
132 supportPluginNameIndex_.insert(hisyseventPluginIndex_);
133 supportPluginNameIndex_.insert(hisyseventPluginConfigIndex_);
134 #endif
135 }
InitPluginNameIndex()136 void PbreaderParser::InitPluginNameIndex()
137 {
138 #ifdef ENABLE_PROCESS
139 processPluginIndex_ = traceDataCache_->GetDataIndex("process-plugin");
140 supportPluginNameIndex_.insert(processPluginIndex_);
141 #endif
142 #ifdef ENABLE_DISKIO
143 diskioPluginIndex_ = traceDataCache_->GetDataIndex("diskio-plugin");
144 supportPluginNameIndex_.insert(diskioPluginIndex_);
145 #endif
146 InitMemoryPluginNameIndex();
147 InitHiPluginNameIndex();
148 #ifdef ENABLE_CPUDATA
149 cpuPluginIndex_ = traceDataCache_->GetDataIndex("cpu-plugin");
150 supportPluginNameIndex_.insert(cpuPluginIndex_);
151 #endif
152 #ifdef ENABLE_NETWORK
153 networkPluginIndex_ = traceDataCache_->GetDataIndex("network-plugin");
154 supportPluginNameIndex_.insert(networkPluginIndex_);
155 #endif
156 InitHookPluginNameIndex();
157 #ifdef ENABLE_ARKTS
158 arktsPluginIndex_ = traceDataCache_->GetDataIndex("arkts-plugin");
159 arktsPluginConfigIndex_ = traceDataCache_->GetDataIndex("arkts-plugin_config");
160 supportPluginNameIndex_.insert(arktsPluginIndex_);
161 supportPluginNameIndex_.insert(arktsPluginConfigIndex_);
162 #endif
163 #ifdef ENABLE_HTRACE
164 ftracePluginIndex_.insert(traceDataCache_->GetDataIndex("ftrace-plugin"));
165 ftracePluginIndex_.insert(traceDataCache_->GetDataIndex("/data/local/tmp/libftrace_plugin.z.so"));
166 supportPluginNameIndex_.insert(ftracePluginIndex_.begin(), ftracePluginIndex_.end());
167 #endif
168 #ifdef ENABLE_FFRT
169 ffrtPluginIndex_ = traceDataCache_->GetDataIndex("ffrt-profiler");
170 ffrtPluginConfigIndex_ = traceDataCache_->GetDataIndex("ffrt-profiler_config");
171 supportPluginNameIndex_.insert(ffrtPluginIndex_);
172 supportPluginNameIndex_.insert(ffrtPluginConfigIndex_);
173 #endif
174 #ifdef ENABLE_STREAM_EXTEND
175 streamPluginIndex_ = traceDataCache_->GetDataIndex("stream-plugin");
176 supportPluginNameIndex_.insert(streamPluginIndex_);
177 #endif
178 #ifdef ENABLE_XPOWER
179 xpowerPluginIndex_ = traceDataCache_->GetDataIndex("xpower-plugin");
180 supportPluginNameIndex_.insert(xpowerPluginIndex_);
181 #endif
182 }
183
184 #if defined(ENABLE_HIPERF) || defined(ENABLE_NATIVE_HOOK) || defined(ENABLE_EBPF)
ParseELF(const std::string & directory,const std::string & fileName)185 std::unique_ptr<SymbolsFile> PbreaderParser::ParseELF(const std::string &directory, const std::string &fileName)
186 {
187 auto symbolsFile = OHOS::Developtools::HiPerf::SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, fileName);
188 if (!symbolsFile) {
189 return nullptr;
190 }
191 symbolsFile->setSymbolsFilePath(directory);
192 if (!symbolsFile->LoadSymbols(nullptr, fileName)) {
193 return nullptr;
194 }
195 return symbolsFile;
196 }
197 #endif
198
~PbreaderParser()199 PbreaderParser::~PbreaderParser()
200 {
201 TS_LOGI("clockid 2 is for RealTime and 1 is for BootTime");
202 }
203
ReparseSymbolFileAndResymbolization(const std::string & directory,const std::string & fileName)204 bool PbreaderParser::ReparseSymbolFileAndResymbolization(const std::string &directory, const std::string &fileName)
205 {
206 auto parseStatus = false;
207 #if defined(ENABLE_HIPERF) || defined(ENABLE_NATIVE_HOOK) || defined(ENABLE_EBPF)
208 auto symbolsFile = ParseELF(directory, fileName);
209 #endif
210 #ifdef ENABLE_HIPERF
211 if (traceDataCache_->GetPerfFilesData()->Size() > 0) {
212 perfDataParser_->PerfReloadSymbolFile(symbolsFile);
213 #ifdef ENABLE_ADDR2LINE
214 perfDataParser_->ParseSourceLocation(directory, fileName);
215 #endif
216 parseStatus = true;
217 }
218 #endif
219 #ifdef ENABLE_NATIVE_HOOK
220 if (traceDataCache_->GetNativeHookFrameData()->Size() > 0) {
221 pbreaderNativeHookParser_->NativeHookReloadElfSymbolTable(symbolsFile);
222 parseStatus = true;
223 }
224 #endif
225 #ifdef ENABLE_EBPF
226 if (traceDataCache_->GetEbpfCallStack()->Size() > 0) {
227 ebpfDataParser_->EBPFReloadElfSymbolTable(symbolsFile);
228 parseStatus = true;
229 }
230 #endif
231 return parseStatus;
232 }
233
WaitForHPluginParserEnd()234 inline void PbreaderParser::WaitForHPluginParserEnd()
235 {
236 #ifdef ENABLE_HTRACE
237 htraceCpuDetailParser_->FilterAllEvents();
238 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE,
239 dataSourceTypeTraceClockid_);
240 #endif
241 #ifdef ENABLE_HILOG
242 pbreaderHiLogParser_->Finish();
243 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HILOG,
244 dataSourceTypeHilogClockid_);
245 #endif
246 #ifdef ENABLE_HTDUMP
247 pbreaderHidumpParser_->Finish();
248 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_FPS, dataSourceTypeFpsClockid_);
249 #endif
250 #ifdef ENABLE_HISYSEVENT
251 hisyseventParser_->Finish();
252 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HISYSEVENT,
253 dataSourceTypeHisyseventClockid_);
254 #endif
255 }
256
WaitForOtherPluginParserEnd()257 inline void PbreaderParser::WaitForOtherPluginParserEnd()
258 {
259 #ifdef ENABLE_NATIVE_HOOK
260 pbreaderNativeHookParser_->FinishParseNativeHookData();
261 pbreaderNativeHookParser_->Finish();
262 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NATIVEHOOK,
263 dataSourceTypeNativeHookClockid_);
264 #endif
265 #ifdef ENABLE_CPUDATA
266 cpuUsageParser_->Finish();
267 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_CPU, dataSourceTypeCpuClockid_);
268 #endif
269 #ifdef ENABLE_NETWORK
270 networkParser_->Finish();
271 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NETWORK,
272 dataSourceTypeNetworkClockid_);
273 #endif
274 #ifdef ENABLE_PROCESS
275 processParser_->Finish();
276 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_PROCESS,
277 dataSourceTypeProcessClockid_);
278 #endif
279 #ifdef ENABLE_DISKIO
280 diskIOParser_->Finish();
281 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_DISKIO,
282 dataSourceTypeDiskioClockid_);
283 #endif
284 #ifdef ENABLE_ARKTS
285 jsMemoryParser_->Finish();
286 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_JSMEMORY,
287 dataSourceTypeJSMemoryClockid_);
288 #endif
289 #ifdef ENABLE_EBPF
290 ebpfDataParser_->Finish(); // keep final upate perf and ebpf data time range
291 #endif
292 #ifdef ENABLE_HIPERF
293 perfDataParser_->Finish();
294 #endif
295 #ifdef ENABLE_MEMORY
296 pbreaderMemParser_->Finish();
297 traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_MEM, dataSourceTypeMemClockid_);
298 #endif
299 }
300
WaitForParserEnd()301 void PbreaderParser::WaitForParserEnd()
302 {
303 if (parseThreadStarted_ || filterThreadStarted_) {
304 toExit_ = true;
305 while (!exited_) {
306 usleep(sleepDur_ * sleepDur_);
307 }
308 }
309 hasGotHeader_ = false;
310 WaitForHPluginParserEnd();
311 WaitForOtherPluginParserEnd();
312 #if defined(ENABLE_HTRACE) && defined(ENABLE_NATIVE_HOOK) && defined(ENABLE_HIPERF)
313 ParseNapiAsync();
314 #endif
315 traceDataCache_->GetDataSourceClockIdData()->Finish();
316 dataSegArray_.reset();
317 processedDataLen_ = 0;
318 }
319
ParseTraceDataItem(const std::string & buffer)320 void PbreaderParser::ParseTraceDataItem(const std::string &buffer)
321 {
322 int32_t head = rawDataHead_;
323 if (!traceDataCache_->supportThread_ || traceDataCache_->isSplitFile_) {
324 dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
325 dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
326 ParserData(dataSegArray_[head], traceDataCache_->isSplitFile_);
327 return;
328 }
329 while (!toExit_) {
330 if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) {
331 usleep(sleepDur_);
332 continue;
333 }
334 dataSegArray_[head].seg = std::make_shared<std::string>(std::move(buffer));
335 dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED;
336 rawDataHead_ = (rawDataHead_ + 1) % maxSegArraySize;
337 break;
338 }
339 if (!parseThreadStarted_) {
340 parseThreadStarted_ = true;
341 int32_t tmp = traceDataCache_->parserThreadNum_;
342 while (tmp--) {
343 parserThreadCount_++;
344 std::thread ParseTypeThread(&PbreaderParser::ParseThread, this);
345 ParseTypeThread.detach();
346 TS_LOGI("parser Thread:%d/%d start working ...\n", traceDataCache_->parserThreadNum_ - tmp,
347 traceDataCache_->parserThreadNum_);
348 }
349 }
350 if (!filterThreadStarted_) {
351 filterThreadStarted_ = true;
352 std::thread FilterTypeThread(&PbreaderParser::FilterThread, this);
353 TS_LOGI("FilterThread start working ...");
354 FilterTypeThread.detach();
355 }
356 }
357
358 #ifdef ENABLE_ARKTS
EnableFileSeparate(bool enabled)359 void PbreaderParser::EnableFileSeparate(bool enabled)
360 {
361 jsMemoryParser_->EnableSaveFile(enabled);
362 }
363 #endif
FilterData(PbreaderDataSegment & seg,bool isSplitFile)364 void PbreaderParser::FilterData(PbreaderDataSegment &seg, bool isSplitFile)
365 {
366 bool haveSplitSeg = false;
367 if (seg.dataType == DATA_SOURCE_TYPE_TRACE) {
368 #ifdef ENABLE_HTRACE
369 htraceCpuDetailParser_->FilterAllEventsReader();
370 #endif
371 }
372 #ifdef ENABLE_FFRT
373 else if (seg.dataType == DATA_SOURCE_TYPE_FFRT) {
374 pbreaderFfrtParser_->FilterAllEventsReader();
375 }
376 #endif
377 #ifdef ENABLE_NATIVE_HOOK
378 else if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK) {
379 pbreaderNativeHookParser_->Parse(seg, haveSplitSeg);
380 } else if (seg.dataType == DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG) {
381 pbreaderNativeHookParser_->ParseConfigInfo(seg);
382 }
383 #endif
384 #ifdef ENABLE_MEMORY
385 else if (seg.dataType == DATA_SOURCE_TYPE_MEM) {
386 pbreaderMemParser_->Parse(seg, seg.timeStamp, seg.clockId);
387 } else if (seg.dataType == DATA_SOURCE_TYPE_MEM_CONFIG) {
388 pbreaderMemParser_->ParseMemoryConfig(seg);
389 }
390 #endif
391 #ifdef ENABLE_HILOG
392 else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) {
393 pbreaderHiLogParser_->Parse(seg.protoData, haveSplitSeg);
394 }
395 #endif
396 #ifdef ENABLE_CPUDATA
397 else if (seg.dataType == DATA_SOURCE_TYPE_CPU) {
398 cpuUsageParser_->Parse(seg.protoData, seg.timeStamp);
399 }
400 #endif
401 #ifdef ENABLE_HTDUMP
402 else if (seg.dataType == DATA_SOURCE_TYPE_FPS) {
403 pbreaderHidumpParser_->Parse(seg.protoData);
404 dataSourceTypeFpsClockid_ = pbreaderHidumpParser_->ClockId();
405 }
406 #endif
407 #ifdef ENABLE_NETWORK
408 else if (seg.dataType == DATA_SOURCE_TYPE_NETWORK) {
409 networkParser_->Parse(seg.protoData, seg.timeStamp);
410 }
411 #endif
412 #ifdef ENABLE_PROCESS
413 else if (seg.dataType == DATA_SOURCE_TYPE_PROCESS) {
414 processParser_->Parse(seg.protoData, seg.timeStamp);
415 }
416 #endif
417 #ifdef ENABLE_DISKIO
418 else if (seg.dataType == DATA_SOURCE_TYPE_DISKIO) {
419 diskIOParser_->Parse(seg.protoData, seg.timeStamp);
420 }
421 #endif
422 #ifdef ENABLE_ARKTS
423 else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY) {
424 jsMemoryParser_->Parse(seg.protoData, seg.timeStamp, traceDataCache_->SplitFileMinTime(),
425 traceDataCache_->SplitFileMaxTime(), profilerPluginData_);
426 } else if (seg.dataType == DATA_SOURCE_TYPE_JSMEMORY_CONFIG) {
427 jsMemoryParser_->ParseJSMemoryConfig(seg.protoData);
428 }
429 #endif
430 #ifdef ENABLE_HISYSEVENT
431 else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT) {
432 ProtoReader::HisyseventInfo_Reader hisyseventInfo(seg.protoData.data_, seg.protoData.size_);
433 hisyseventParser_->Parse(&hisyseventInfo, seg.timeStamp, haveSplitSeg);
434 } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT_CONFIG) {
435 ProtoReader::HisyseventConfig_Reader hisyseventConfig(seg.protoData.data_, seg.protoData.size_);
436 hisyseventParser_->Parse(&hisyseventConfig, seg.timeStamp);
437 }
438 #endif
439 #ifdef ENABLE_XPOWER
440 else if (seg.dataType == DATA_SOURCE_TYPE_XPOWER) {
441 xpowerParser_->Parse(seg, seg.timeStamp, seg.clockId);
442 }
443 #endif
444 #ifdef ENABLE_STREAM_EXTEND
445 else if (seg.dataType == DATA_SOURCE_TYPE_STREAM) {
446 pbreaderStreamParser_->Parse(seg);
447 }
448 #endif
449 if (traceDataCache_->isSplitFile_ && haveSplitSeg) {
450 mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
451 }
452 if (traceDataCache_->supportThread_ && !traceDataCache_->isSplitFile_) {
453 filterHead_ = (filterHead_ + 1) % maxSegArraySize;
454 }
455 seg.status = TS_PARSE_STATUS_INIT;
456 }
FilterThread()457 void PbreaderParser::FilterThread()
458 {
459 TS_LOGI("filter thread start work!");
460 while (true) {
461 PbreaderDataSegment &seg = dataSegArray_[filterHead_];
462 if (seg.status.load() == TS_PARSE_STATUS_INVALID) {
463 seg.status = TS_PARSE_STATUS_INIT;
464 filterHead_ = (filterHead_ + 1) % maxSegArraySize;
465 TS_LOGD("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_);
466 continue;
467 }
468 if (seg.status.load() != TS_PARSE_STATUS_PARSED) {
469 if (toExit_ && !parserThreadCount_) {
470 TS_LOGI("exiting Filter Thread");
471 exited_ = true;
472 filterThreadStarted_ = false;
473 TS_LOGI("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
474 filterHead_, seg.status.load());
475 return;
476 }
477 TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_,
478 filterHead_, seg.status.load());
479 usleep(sleepDur_);
480 continue;
481 }
482 FilterData(seg, false);
483 }
484 }
485
SpliteConfigData(const std::string & pluginName,const PbreaderDataSegment & dataSeg)486 bool PbreaderParser::SpliteConfigData(const std::string &pluginName, const PbreaderDataSegment &dataSeg)
487 {
488 if (EndWith(pluginName, "arkts-plugin_config")) {
489 std::string dataString(dataSeg.seg->c_str(), dataSeg.seg->length());
490 arkTsConfigData_ = lenBuffer_ + dataString;
491 return true;
492 } else if (EndWith(pluginName, "config")) {
493 mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
494 return true;
495 }
496 return false;
497 }
498
SpliteDataBySegment(DataIndex pluginNameIndex,PbreaderDataSegment & dataSeg)499 bool PbreaderParser::SpliteDataBySegment(DataIndex pluginNameIndex, PbreaderDataSegment &dataSeg)
500 {
501 bool isOtherPlugin = false;
502 #ifdef ENABLE_HTRACE
503 isOtherPlugin = isOtherPlugin || ftracePluginIndex_.count(pluginNameIndex);
504 #endif
505 #ifdef ENABLE_FFRT
506 isOtherPlugin = isOtherPlugin || (ffrtPluginIndex_ == pluginNameIndex);
507 #endif
508 #ifdef ENABLE_HISYSEVENT
509 isOtherPlugin = isOtherPlugin || (hisyseventPluginIndex_ == pluginNameIndex);
510 #endif
511 #ifdef ENABLE_NATIVE_HOOK
512 isOtherPlugin = isOtherPlugin || nativeHookPluginIndex_.count(pluginNameIndex);
513 #endif
514 #ifdef ENABLE_HILOG
515 isOtherPlugin = isOtherPlugin || hilogPluginIndex_.count(pluginNameIndex);
516 #endif
517 if (isOtherPlugin) {
518 return false;
519 }
520 // need convert to Primary Time Plugin
521 #ifdef ENABLE_MEMORY
522 if (pluginNameIndex == memPluginIndex_) {
523 dataSeg.timeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, dataSeg.timeStamp);
524 UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, dataSeg.timeStamp, dataSeg.timeStamp);
525 }
526 #endif
527 if (dataSeg.timeStamp >= traceDataCache_->SplitFileMinTime() &&
528 dataSeg.timeStamp <= traceDataCache_->SplitFileMaxTime()) {
529 mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
530 }
531 if (pluginNameIndex == arktsPluginConfigIndex_ || pluginNameIndex == arktsPluginIndex_) {
532 return false;
533 }
534 return true;
535 }
ParseDataByPluginName(PbreaderDataSegment & dataSeg,DataIndex pulginNameIndex,const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,bool isSplitFile)536 void PbreaderParser::ParseDataByPluginName(PbreaderDataSegment &dataSeg,
537 DataIndex pulginNameIndex,
538 const ProtoReader::ProfilerPluginData_Reader &pluginDataZero,
539 bool isSplitFile)
540 {
541 if (ftracePluginIndex_.count(pulginNameIndex)) { // ok
542 #ifdef ENABLE_HTRACE
543 ParseFtrace(dataSeg);
544 #endif
545 }
546 #ifdef ENABLE_FFRT
547 else if (ffrtPluginIndex_ == pulginNameIndex) {
548 ParseFfrt(dataSeg);
549 } else if (ffrtPluginConfigIndex_ == pulginNameIndex) {
550 ParseFfrtConfig(dataSeg);
551 }
552 #endif
553 #ifdef ENABLE_NATIVE_HOOK
554 else if (nativeHookPluginIndex_.count(pulginNameIndex)) {
555 ParseNativeHook(dataSeg, isSplitFile);
556 } else if (pulginNameIndex == nativeHookConfigIndex_) {
557 ParseNativeHookConfig(dataSeg);
558 }
559 #endif
560 #ifdef ENABLE_MEMORY
561 else if (pulginNameIndex == memPluginIndex_) {
562 ParseMemory(pluginDataZero, dataSeg);
563 } else if (pulginNameIndex == memoryPluginConfigIndex_) {
564 ParseMemoryConfig(dataSeg, pluginDataZero);
565 }
566 #endif
567 #ifdef ENABLE_HILOG
568 else if (hilogPluginIndex_.count(pulginNameIndex)) {
569 ParseHilog(dataSeg);
570 }
571 #endif
572 #ifdef ENABLE_HTDUMP
573 else if (hidumpPluginIndex_.count(pulginNameIndex)) {
574 ParseFPS(dataSeg);
575 }
576 #endif
577 #ifdef ENABLE_CPUDATA
578 else if (pulginNameIndex == cpuPluginIndex_) {
579 ParseCpuUsage(dataSeg);
580 }
581 #endif
582 #ifdef ENABLE_NETWORK
583 else if (pulginNameIndex == networkPluginIndex_) {
584 ParseNetwork(dataSeg);
585 }
586 #endif
587 #ifdef ENABLE_DISKIO
588 else if (pulginNameIndex == diskioPluginIndex_) {
589 ParseDiskIO(dataSeg);
590 }
591 #endif
592 #ifdef ENABLE_PROCESS
593 else if (pulginNameIndex == processPluginIndex_) {
594 ParseProcess(dataSeg);
595 }
596 #endif
597 #ifdef ENABLE_HISYSEVENT
598 else if (pulginNameIndex == hisyseventPluginIndex_) {
599 ParseHisysevent(dataSeg);
600 } else if (pulginNameIndex == hisyseventPluginConfigIndex_) {
601 ParseHisyseventConfig(dataSeg);
602 }
603 #endif
604 #ifdef ENABLE_ARKTS
605 else if (pulginNameIndex == arktsPluginIndex_) {
606 ParseJSMemory(pluginDataZero, dataSeg, isSplitFile);
607 } else if (pulginNameIndex == arktsPluginConfigIndex_) {
608 ParseJSMemoryConfig(dataSeg);
609 }
610 #endif
611 #ifdef ENABLE_XPOWER
612 else if (pulginNameIndex == xpowerPluginIndex_) {
613 ParseXpower(dataSeg);
614 }
615 #endif
616 #ifdef ENABLE_STREAM_EXTEND
617 else if (pulginNameIndex == streamPluginIndex_) { // for trace extend demo
618 ParseStream(dataSeg);
619 }
620 #endif
621 }
622
ParserData(PbreaderDataSegment & dataSeg,bool isSplitFile)623 void PbreaderParser::ParserData(PbreaderDataSegment &dataSeg, bool isSplitFile)
624 {
625 ProtoReader::ProfilerPluginData_Reader pluginDataZero(reinterpret_cast<const uint8_t *>(dataSeg.seg->c_str()),
626 dataSeg.seg->length());
627 if (!pluginDataZero.has_name()) {
628 return;
629 }
630 auto pluginName = pluginDataZero.name().ToStdString();
631 auto pluginNameIndex = traceDataCache_->GetDataIndex(pluginName);
632 if (isSplitFile && SpliteConfigData(pluginName, dataSeg)) {
633 return;
634 }
635 if (pluginDataZero.has_tv_sec() && pluginDataZero.has_tv_nsec()) {
636 dataSeg.timeStamp = pluginDataZero.tv_sec() * SEC_TO_NS + pluginDataZero.tv_nsec();
637 }
638
639 if (isSplitFile && SpliteDataBySegment(pluginNameIndex, dataSeg)) {
640 return;
641 }
642 if (supportPluginNameIndex_.count(pluginNameIndex)) {
643 dataSeg.protoData = pluginDataZero.data();
644 ParseDataByPluginName(dataSeg, pluginNameIndex, pluginDataZero, isSplitFile);
645 } else {
646 #if IS_WASM
647 TraceStreamerPluginOutFilter(reinterpret_cast<const char *>(pluginDataZero.data().data_),
648 pluginDataZero.data().size_, pluginName);
649 #endif
650 dataSeg.status = TS_PARSE_STATUS_INVALID;
651 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID);
652 return;
653 }
654 if (!traceDataCache_->supportThread_ || traceDataCache_->isSplitFile_) {
655 FilterData(dataSeg, isSplitFile);
656 }
657 }
ParseThread()658 void PbreaderParser::ParseThread()
659 {
660 TS_LOGI("parser thread start work!\n");
661 while (true) {
662 int32_t head = GetNextSegment();
663 if (head < 0) {
664 if (head == ERROR_CODE_EXIT) {
665 TS_LOGI("parse thread exit");
666 return;
667 } else if (head == ERROR_CODE_NODATA) {
668 continue;
669 }
670 }
671 PbreaderDataSegment &dataSeg = dataSegArray_[head];
672 ParserData(dataSeg, false);
673 }
674 }
675
676 #ifdef ENABLE_MEMORY
ParseMemory(const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,PbreaderDataSegment & dataSeg)677 void PbreaderParser::ParseMemory(const ProtoReader::ProfilerPluginData_Reader &pluginDataZero,
678 PbreaderDataSegment &dataSeg)
679 {
680 BuiltinClocks clockId = TS_CLOCK_REALTIME;
681 dataSourceTypeMemClockid_ = clockId;
682 dataSeg.dataType = DATA_SOURCE_TYPE_MEM;
683 dataSeg.clockId = clockId;
684 dataSeg.status = TS_PARSE_STATUS_PARSED;
685 }
ParseMemoryConfig(PbreaderDataSegment & dataSeg,const ProtoReader::ProfilerPluginData_Reader & pluginDataZero)686 void PbreaderParser::ParseMemoryConfig(PbreaderDataSegment &dataSeg,
687 const ProtoReader::ProfilerPluginData_Reader &pluginDataZero)
688 {
689 if (pluginDataZero.has_sample_interval()) {
690 uint32_t sampleInterval = pluginDataZero.sample_interval();
691 traceDataCache_->GetTraceConfigData()->AppendNewData("memory_config", "sample_interval",
692 std::to_string(sampleInterval));
693 }
694 dataSeg.dataType = DATA_SOURCE_TYPE_MEM_CONFIG;
695 dataSeg.status = TS_PARSE_STATUS_PARSED;
696 }
697 #endif
698 #ifdef ENABLE_HILOG
ParseHilog(PbreaderDataSegment & dataSeg)699 void PbreaderParser::ParseHilog(PbreaderDataSegment &dataSeg)
700 {
701 dataSeg.dataType = DATA_SOURCE_TYPE_HILOG;
702 dataSourceTypeHilogClockid_ = TS_CLOCK_REALTIME;
703 dataSeg.status = TS_PARSE_STATUS_PARSED;
704 }
705 #endif
706 #ifdef ENABLE_NATIVE_HOOK
ParseNativeHookConfig(PbreaderDataSegment & dataSeg)707 void PbreaderParser::ParseNativeHookConfig(PbreaderDataSegment &dataSeg)
708 {
709 dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK_CONFIG;
710 dataSeg.status = TS_PARSE_STATUS_PARSED;
711 }
ParseNativeHook(PbreaderDataSegment & dataSeg,bool isSplitFile)712 void PbreaderParser::ParseNativeHook(PbreaderDataSegment &dataSeg, bool isSplitFile)
713 {
714 dataSourceTypeNativeHookClockid_ = TS_CLOCK_REALTIME;
715 dataSeg.dataType = DATA_SOURCE_TYPE_NATIVEHOOK;
716 dataSeg.status = TS_PARSE_STATUS_PARSED;
717 if (isSplitFile) {
718 dataSourceType_ = DATA_SOURCE_TYPE_NATIVEHOOK;
719 }
720 }
721 #endif
722
723 #ifdef ENABLE_HTRACE
ParseFtrace(PbreaderDataSegment & dataSeg)724 void PbreaderParser::ParseFtrace(PbreaderDataSegment &dataSeg)
725 {
726 dataSeg.dataType = DATA_SOURCE_TYPE_TRACE;
727 ProtoReader::TracePluginResult_Reader tracePluginResult(dataSeg.protoData);
728 if (tracePluginResult.has_ftrace_cpu_stats()) {
729 auto cpuStats = *tracePluginResult.ftrace_cpu_stats();
730 ProtoReader::FtraceCpuStatsMsg_Reader ftraceCpuStatsMsg(cpuStats.data_, cpuStats.size_);
731 auto s = *ftraceCpuStatsMsg.per_cpu_stats();
732 ProtoReader::PerCpuStatsMsg_Reader perCpuStatsMsg(s.data_, s.size_);
733 TS_LOGD("s.overrun():%" PRIu64 "", perCpuStatsMsg.overrun());
734 TS_LOGD("s.dropped_events():%" PRIu64 "", perCpuStatsMsg.dropped_events());
735 auto clock = ftraceCpuStatsMsg.trace_clock().ToStdString();
736 if (clock == "boot") {
737 clock_ = TS_CLOCK_BOOTTIME;
738 } else if (clock == "mono") {
739 clock_ = TS_MONOTONIC;
740 } else {
741 TS_LOGI("invalid clock:%s", clock.c_str());
742 dataSeg.status = TS_PARSE_STATUS_INVALID;
743 return;
744 }
745 dataSeg.clockId = clock_;
746 dataSourceTypeTraceClockid_ = clock_;
747 dataSeg.status = TS_PARSE_STATUS_PARSED;
748 return;
749 }
750 bool haveSplitSeg = false;
751 dataSeg.clockId = clock_;
752 if (tracePluginResult.has_ftrace_cpu_detail()) {
753 htraceCpuDetailParser_->Parse(dataSeg, tracePluginResult, haveSplitSeg);
754 }
755 if (tracePluginResult.has_symbols_detail()) {
756 htraceSymbolsDetailParser_->Parse(dataSeg.protoData); // has Event
757 haveSplitSeg = true;
758 }
759 if (tracePluginResult.has_clocks_detail()) {
760 pbreaderClockDetailParser_->Parse(dataSeg.protoData); // has Event
761 haveSplitSeg = true;
762 }
763 if (traceDataCache_->isSplitFile_ && haveSplitSeg) {
764 mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
765 }
766 if (tracePluginResult.has_ftrace_cpu_detail() || tracePluginResult.has_clocks_detail() ||
767 tracePluginResult.has_symbols_detail()) {
768 dataSeg.status = TS_PARSE_STATUS_PARSED;
769 } else {
770 dataSeg.status = TS_PARSE_STATUS_INVALID;
771 }
772 }
773 #endif
774 #ifdef ENABLE_FFRT
ParseFfrtConfig(PbreaderDataSegment & dataSeg)775 void PbreaderParser::ParseFfrtConfig(PbreaderDataSegment &dataSeg)
776 {
777 pbreaderFfrtParser_->SetFfrtSrcClockid(dataSeg);
778 dataSeg.dataType = DATA_SOURCE_TYPE_FFRT_CONFIG;
779 dataSeg.status = TS_PARSE_STATUS_PARSED;
780 }
ParseFfrt(PbreaderDataSegment & dataSeg)781 void PbreaderParser::ParseFfrt(PbreaderDataSegment &dataSeg)
782 {
783 bool haveSplitSeg = false;
784 pbreaderFfrtParser_->Parser(dataSeg, haveSplitSeg);
785 if (haveSplitSeg) {
786 mPbreaderSplitData_.emplace(splitFileOffset_, nextLength_ + packetSegLength_);
787 }
788 dataSeg.dataType = DATA_SOURCE_TYPE_FFRT;
789 dataSeg.status = TS_PARSE_STATUS_PARSED;
790 }
791 #endif
792 #ifdef ENABLE_HTDUMP
ParseFPS(PbreaderDataSegment & dataSeg)793 void PbreaderParser::ParseFPS(PbreaderDataSegment &dataSeg)
794 {
795 dataSeg.dataType = DATA_SOURCE_TYPE_FPS;
796 dataSeg.status = TS_PARSE_STATUS_PARSED;
797 }
798 #endif
799
800 #ifdef ENABLE_CPUDATA
ParseCpuUsage(PbreaderDataSegment & dataSeg)801 void PbreaderParser::ParseCpuUsage(PbreaderDataSegment &dataSeg)
802 {
803 dataSourceTypeCpuClockid_ = TS_CLOCK_REALTIME;
804 dataSeg.dataType = DATA_SOURCE_TYPE_CPU;
805 dataSeg.status = TS_PARSE_STATUS_PARSED;
806 }
807 #endif
808 #ifdef ENABLE_NETWORK
ParseNetwork(PbreaderDataSegment & dataSeg)809 void PbreaderParser::ParseNetwork(PbreaderDataSegment &dataSeg)
810 {
811 dataSourceTypeNetworkClockid_ = TS_CLOCK_REALTIME;
812 dataSeg.dataType = DATA_SOURCE_TYPE_NETWORK;
813 dataSeg.status = TS_PARSE_STATUS_PARSED;
814 }
815 #endif
816 #ifdef ENABLE_XPOWER
ParseXpower(PbreaderDataSegment & dataSeg)817 void PbreaderParser::ParseXpower(PbreaderDataSegment &dataSeg)
818 {
819 dataSeg.dataType = DATA_SOURCE_TYPE_XPOWER;
820 dataSeg.status = TS_PARSE_STATUS_PARSED;
821 }
822 #endif
823 #ifdef ENABLE_DISKIO
ParseDiskIO(PbreaderDataSegment & dataSeg)824 void PbreaderParser::ParseDiskIO(PbreaderDataSegment &dataSeg)
825 {
826 dataSourceTypeDiskioClockid_ = TS_CLOCK_REALTIME;
827 dataSeg.dataType = DATA_SOURCE_TYPE_DISKIO;
828 dataSeg.status = TS_PARSE_STATUS_PARSED;
829 }
830 #endif
831
832 #ifdef ENABLE_PROCESS
ParseProcess(PbreaderDataSegment & dataSeg)833 void PbreaderParser::ParseProcess(PbreaderDataSegment &dataSeg)
834 {
835 dataSourceTypeProcessClockid_ = TS_CLOCK_BOOTTIME;
836 dataSeg.dataType = DATA_SOURCE_TYPE_PROCESS;
837 dataSeg.status = TS_PARSE_STATUS_PARSED;
838 }
839 #endif
840
841 #ifdef ENABLE_HISYSEVENT
ParseHisysevent(PbreaderDataSegment & dataSeg)842 void PbreaderParser::ParseHisysevent(PbreaderDataSegment &dataSeg)
843 {
844 dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
845 dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT;
846 dataSeg.status = TS_PARSE_STATUS_PARSED;
847 }
ParseHisyseventConfig(PbreaderDataSegment & dataSeg)848 void PbreaderParser::ParseHisyseventConfig(PbreaderDataSegment &dataSeg)
849 {
850 dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME;
851 dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT_CONFIG;
852 dataSeg.status = TS_PARSE_STATUS_PARSED;
853 }
854 #endif
855
856 #ifdef ENABLE_ARKTS
ParseJSMemory(const ProtoReader::ProfilerPluginData_Reader & pluginDataZero,PbreaderDataSegment & dataSeg,bool isSplitFile)857 void PbreaderParser::ParseJSMemory(const ProtoReader::ProfilerPluginData_Reader &pluginDataZero,
858 PbreaderDataSegment &dataSeg,
859 bool isSplitFile)
860 {
861 if (isSplitFile) {
862 dataSourceType_ = DATA_SOURCE_TYPE_JSMEMORY;
863 profilerPluginData_.name = pluginDataZero.name().ToStdString();
864 profilerPluginData_.status = pluginDataZero.status();
865 profilerPluginData_.clockId = pluginDataZero.clock_id();
866 profilerPluginData_.tvSec = pluginDataZero.tv_sec();
867 profilerPluginData_.tvNsec = pluginDataZero.tv_nsec();
868 profilerPluginData_.version = pluginDataZero.version().ToStdString();
869 profilerPluginData_.sampleInterval = pluginDataZero.sample_interval();
870 }
871 dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
872 dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY;
873 dataSeg.status = TS_PARSE_STATUS_PARSED;
874 }
ParseJSMemoryConfig(PbreaderDataSegment & dataSeg)875 void PbreaderParser::ParseJSMemoryConfig(PbreaderDataSegment &dataSeg)
876 {
877 dataSourceTypeJSMemoryClockid_ = TS_CLOCK_REALTIME;
878 dataSeg.dataType = DATA_SOURCE_TYPE_JSMEMORY_CONFIG;
879 dataSeg.status = TS_PARSE_STATUS_PARSED;
880 }
881 #endif
882
883 #ifdef ENABLE_STREAM_EXTEND
ParseStream(PbreaderDataSegment & dataSeg)884 void PbreaderParser::ParseStream(PbreaderDataSegment &dataSeg)
885 {
886 dataSeg.dataType = DATA_SOURCE_TYPE_STREAM;
887 dataSeg.status = TS_PARSE_STATUS_PARSED;
888 }
889 #endif
890
GetNextSegment()891 int32_t PbreaderParser::GetNextSegment()
892 {
893 int32_t head;
894 std::lock_guard<std::mutex> muxLockGuard(pbreaderDataSegMux_);
895 head = parseHead_;
896 PbreaderDataSegment &pbreaderDataSegmentSeg = dataSegArray_[head];
897 if (pbreaderDataSegmentSeg.status.load() != TS_PARSE_STATUS_SEPRATED) {
898 if (toExit_) {
899 parserThreadCount_--;
900 TS_LOGI("exiting parser, parserThread Count:%d\n", parserThreadCount_);
901 TS_LOGI("seprateHead_x:\t%d, parseHead_:\t%d, filterHead_:\t%d status:%d\n", rawDataHead_, parseHead_,
902 filterHead_, pbreaderDataSegmentSeg.status.load());
903 if (!parserThreadCount_ && !filterThreadStarted_) {
904 exited_ = true;
905 }
906 return ERROR_CODE_EXIT;
907 }
908 usleep(sleepDur_);
909 return ERROR_CODE_NODATA;
910 }
911 parseHead_ = (parseHead_ + 1) % maxSegArraySize;
912 pbreaderDataSegmentSeg.status = TS_PARSE_STATUS_PARSING;
913 return head;
914 }
915 #ifdef ENABLE_EBPF
CalcEbpfCutOffset(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)916 bool PbreaderParser::CalcEbpfCutOffset(std::deque<uint8_t>::iterator &packagesBegin, size_t ¤tLength)
917 {
918 auto standaloneDataLength = profilerDataLength_ - packetHeaderLength_;
919 if (traceDataCache_->isSplitFile_ && !parsedEbpfOver_) {
920 if (!hasInitEbpfPublicData_) {
921 // Record the offset of Hiperf's 1024-byte header relative to the entire file.
922 ebpfDataParser_->SetEbpfDataOffset(processedDataLen_);
923 ebpfDataParser_->SetSpliteTimeRange(traceDataCache_->SplitFileMinTime(),
924 traceDataCache_->SplitFileMaxTime());
925 parsedFileOffset_ += profilerDataLength_ - packetHeaderLength_;
926 hasInitEbpfPublicData_ = true;
927 }
928 parsedEbpfOver_ = ebpfDataParser_->AddAndSplitEbpfData(packagesBuffer_);
929 if (parsedEbpfOver_) {
930 profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
931 hasGotHeader_ = false;
932 processedDataLen_ += standaloneDataLength;
933 }
934 return false;
935 }
936 if (!traceDataCache_->isSplitFile_ && packagesBuffer_.size() >= standaloneDataLength) {
937 ebpfDataParser_->InitAndParseEbpfData(packagesBuffer_, standaloneDataLength);
938 currentLength -= standaloneDataLength;
939 packagesBegin += standaloneDataLength;
940 profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
941 hasGotHeader_ = false;
942 return true;
943 }
944 return false;
945 }
946 #endif
947
GetHeaderAndUpdateLengthMark(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)948 bool PbreaderParser::GetHeaderAndUpdateLengthMark(std::deque<uint8_t>::iterator &packagesBegin, size_t ¤tLength)
949 {
950 if (!hasGotHeader_) {
951 if (!InitProfilerTraceFileHeader()) {
952 return false;
953 }
954 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + packetHeaderLength_);
955 processedDataLen_ += packetHeaderLength_;
956 currentLength -= packetHeaderLength_;
957 packagesBegin += packetHeaderLength_;
958 parsedFileOffset_ += packetHeaderLength_;
959 pbreaderCurentLength_ = profilerDataLength_ - packetHeaderLength_;
960 hasGotHeader_ = true;
961 if (!currentLength) {
962 return false;
963 }
964 }
965 return true;
966 }
967 #if IS_WASM
ParseSDKData()968 bool PbreaderParser::ParseSDKData()
969 {
970 if (packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_) {
971 auto thirdPartySize = profilerDataLength_ - packetHeaderLength_;
972 auto buffer = std::make_unique<uint8_t[]>(thirdPartySize).get();
973 std::copy(packagesBuffer_.begin(), packagesBuffer_.begin() + thirdPartySize, buffer);
974 TraceStreamerPluginOutFilter(reinterpret_cast<const char *>(buffer), thirdPartySize, standalonePluginName_);
975 return true;
976 }
977 return false;
978 }
979 #endif
980
ParseSegLengthAndEnsureSegDataEnough(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)981 bool PbreaderParser::ParseSegLengthAndEnsureSegDataEnough(std::deque<uint8_t>::iterator &packagesBegin,
982 size_t ¤tLength)
983 {
984 std::string bufferLine;
985 if (!hasGotSegLength_) {
986 if (currentLength < packetSegLength_) {
987 return false;
988 }
989 bufferLine.assign(packagesBegin, packagesBegin + packetSegLength_);
990 const uint32_t *len = reinterpret_cast<const uint32_t *>(bufferLine.data());
991 nextLength_ = *len;
992 lenBuffer_ = bufferLine;
993 pbreaderLength_ += nextLength_ + packetSegLength_;
994 hasGotSegLength_ = true;
995 currentLength -= packetSegLength_;
996 packagesBegin += packetSegLength_;
997 parsedFileOffset_ += packetSegLength_;
998 splitFileOffset_ = profilerDataLength_ - pbreaderCurentLength_;
999 pbreaderCurentLength_ -= packetSegLength_;
1000 }
1001 if (currentLength < nextLength_) {
1002 return false;
1003 }
1004 return true;
1005 }
ParseDataRecursively(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)1006 bool PbreaderParser::ParseDataRecursively(std::deque<uint8_t>::iterator &packagesBegin, size_t ¤tLength)
1007 {
1008 TS_CHECK_TRUE_RET(GetHeaderAndUpdateLengthMark(packagesBegin, currentLength), false);
1009 #ifdef ENABLE_HIPERF
1010 if (profilerDataType_ == ProfilerTraceFileHeader::HIPERF_DATA) {
1011 return ParseHiperfData(packagesBegin, currentLength);
1012 }
1013 #endif
1014 if (profilerDataType_ == ProfilerTraceFileHeader::STANDALONE_DATA) {
1015 if (EBPF_PLUGIN_NAME.compare(standalonePluginName_) == 0) {
1016 #ifdef ENABLE_EBPF
1017 return CalcEbpfCutOffset(packagesBegin, currentLength);
1018 #else
1019 return false;
1020 #endif
1021 } else {
1022 #if IS_WASM
1023 TS_CHECK_TRUE_RET(ParseSDKData(), false); // 三方sdk逻辑待验证。
1024 #endif
1025 }
1026 }
1027 std::string bufferLine;
1028 while (true) {
1029 TS_CHECK_TRUE_RET(ParseSegLengthAndEnsureSegDataEnough(packagesBegin, currentLength), true);
1030 bufferLine.assign(packagesBegin, packagesBegin + nextLength_);
1031 ParseTraceDataItem(bufferLine);
1032 hasGotSegLength_ = false;
1033 packagesBegin += nextLength_;
1034 currentLength -= nextLength_;
1035 parsedFileOffset_ += nextLength_;
1036 if (nextLength_ > pbreaderCurentLength_) {
1037 TS_LOGE("fatal error, data length not match nextLength_:%u, pbreaderCurentLength_:%" PRIu64 "", nextLength_,
1038 pbreaderCurentLength_);
1039 }
1040 pbreaderCurentLength_ -= nextLength_;
1041 if (pbreaderCurentLength_ == 0) {
1042 hasGotHeader_ = false;
1043 processedDataLen_ += packagesBegin - packagesBuffer_.begin();
1044 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
1045 profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
1046 TS_LOGD("read proto finished!");
1047 return ParseDataRecursively(packagesBegin, currentLength);
1048 }
1049 }
1050 return true;
1051 }
1052
ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size,bool isFinish)1053 void PbreaderParser::ParseTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, bool isFinish)
1054 {
1055 packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
1056 auto packagesBegin = packagesBuffer_.begin();
1057 auto currentLength = packagesBuffer_.size();
1058 if (ParseDataRecursively(packagesBegin, currentLength)) {
1059 processedDataLen_ += packagesBegin - packagesBuffer_.begin();
1060 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin);
1061 }
1062 return;
1063 }
1064 #ifdef ENABLE_HIPERF
ParseHiperfData(std::deque<uint8_t>::iterator & packagesBegin,size_t & currentLength)1065 bool PbreaderParser::ParseHiperfData(std::deque<uint8_t>::iterator &packagesBegin, size_t ¤tLength)
1066 {
1067 if (!traceDataCache_->isSplitFile_) {
1068 if (packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_) {
1069 auto size = profilerDataLength_ - packetHeaderLength_;
1070 (void)perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size, processedDataLen_, false, true);
1071 currentLength -= size;
1072 packagesBegin += size;
1073 profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
1074 hasGotHeader_ = false;
1075 return true;
1076 }
1077 return false;
1078 }
1079 bool isFinish = perfProcessedLen_ + packagesBuffer_.size() >= profilerDataLength_ - packetHeaderLength_;
1080 auto size = packagesBuffer_.size();
1081 if (isFinish) {
1082 size = profilerDataLength_ - packetHeaderLength_ - perfProcessedLen_;
1083 }
1084 auto ret = perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size, processedDataLen_, true, isFinish);
1085 perfProcessedLen_ += ret;
1086 currentLength -= ret;
1087 packagesBegin += ret;
1088 if (isFinish) {
1089 profilerDataType_ = ProfilerTraceFileHeader::UNKNOW_TYPE;
1090 hasGotHeader_ = false;
1091 }
1092 return true;
1093 }
StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr,size_t size,int32_t isFinish)1094 void PbreaderParser::StoreTraceDataSegment(std::unique_ptr<uint8_t[]> bufferStr, size_t size, int32_t isFinish)
1095 {
1096 packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]);
1097 if (!traceDataCache_->isSplitFile_) {
1098 return;
1099 }
1100
1101 uint64_t length = packagesBuffer_.size();
1102 auto ret = perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, length, 0, true, isFinish);
1103 perfProcessedLen_ += ret;
1104 processedDataLen_ += ret;
1105 packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + ret);
1106 return;
1107 }
TraceDataSegmentEnd(bool isSplitFile)1108 void PbreaderParser::TraceDataSegmentEnd(bool isSplitFile)
1109 {
1110 perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, packagesBuffer_.size(), 0, isSplitFile, true);
1111 packagesBuffer_.clear();
1112 return;
1113 }
1114 #endif
1115
InitProfilerTraceFileHeader()1116 bool PbreaderParser::InitProfilerTraceFileHeader()
1117 {
1118 if (packagesBuffer_.size() < packetHeaderLength_) {
1119 TS_LOGI("buffer size less than profiler trace file header");
1120 return false;
1121 }
1122 uint8_t buffer[packetHeaderLength_];
1123 (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
1124 int32_t i = 0;
1125 for (auto it = packagesBuffer_.begin(); it != packagesBuffer_.begin() + packetHeaderLength_; ++it, ++i) {
1126 buffer[i] = *it;
1127 }
1128 ProfilerTraceFileHeader *pHeader = reinterpret_cast<ProfilerTraceFileHeader *>(buffer);
1129 if (pHeader->data.length <= packetHeaderLength_ || pHeader->data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
1130 TS_LOGE("Profiler Trace data is truncated or invalid magic! len = %" PRIu64 ", maigc = %" PRIx64 "",
1131 pHeader->data.length, pHeader->data.magic);
1132 return false;
1133 }
1134 if (pHeader->data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) {
1135 #ifdef ENABLE_HIPERF
1136 perfDataParser_->RecordPerfProfilerHeader(buffer, packetHeaderLength_);
1137 #endif
1138 } else if (pHeader->data.dataType == ProfilerTraceFileHeader::STANDALONE_DATA &&
1139 EBPF_PLUGIN_NAME.compare(pHeader->data.standalonePluginName) == 0) {
1140 #ifdef ENABLE_EBPF
1141 ebpfDataParser_->RecordEbpfProfilerHeader(buffer, packetHeaderLength_);
1142 #endif
1143 } else {
1144 auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, packetHeaderLength_);
1145 if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) {
1146 TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %" PRIx64 "", ret,
1147 profilerTraceFileHeader_.data.magic);
1148 return false;
1149 }
1150 }
1151 profilerDataLength_ = pHeader->data.length;
1152 profilerDataType_ = pHeader->data.dataType;
1153 memcpy_s(standalonePluginName_, sizeof(standalonePluginName_), pHeader->data.standalonePluginName,
1154 sizeof(standalonePluginName_));
1155
1156 TS_LOGI("magic = %" PRIx64 ", length = %" PRIu64 ", dataType = %x, boottime = %" PRIu64 "", pHeader->data.magic,
1157 pHeader->data.length, pHeader->data.dataType, pHeader->data.boottime);
1158 #if IS_WASM
1159 const int32_t DATA_TYPE_CLOCK = 100;
1160 TraceStreamerPluginOutSendData(reinterpret_cast<char *>(buffer), packetHeaderLength_, DATA_TYPE_CLOCK);
1161 #endif
1162 pbreaderClockDetailParser_->Parse(pHeader);
1163 return true;
1164 }
1165
1166 #if defined(ENABLE_HTRACE) && defined(ENABLE_NATIVE_HOOK) && defined(ENABLE_HIPERF)
ParseNapiAsync()1167 void PbreaderParser::ParseNapiAsync()
1168 {
1169 // 将native memory中存在的traceid取出, 并记录其对应的callstackid
1170 std::unordered_map<std::string, uint32_t> traceidToCallchainidMap;
1171 GetTraceidInfoFromNativeHook(traceidToCallchainidMap);
1172
1173 // 从callstack表中获取所有的traceid, 根据其所属的itid将SliceInfo存入对应queue
1174 std::unordered_map<uint64_t, std::queue<SliceInfo>> itidToCallstackIdsMap;
1175 GetTraceidInfoFromCallstack(traceidToCallchainidMap, itidToCallstackIdsMap);
1176
1177 // 筛选出包含NativeAsyncWork::AsyncWorkCallback的函数栈的callchainid, 将其存入callchainIdSet
1178 std::unordered_set<uint32_t> callchainIdSet;
1179 GetCallchainIdSetFromHiperf(callchainIdSet);
1180
1181 DumpDataFromHiperf(traceidToCallchainidMap, callchainIdSet, itidToCallstackIdsMap);
1182 }
1183
GetTraceidInfoFromNativeHook(std::unordered_map<std::string,uint32_t> & traceidToCallchainidMap)1184 void PbreaderParser::GetTraceidInfoFromNativeHook(std::unordered_map<std::string, uint32_t> &traceidToCallchainidMap)
1185 {
1186 auto nativeHook = traceDataCache_->GetConstNativeHookData();
1187 std::string preWord("napi:");
1188 for (int i = 0; i < nativeHook.Size(); i++) {
1189 auto subType = nativeHook.SubTypes()[i];
1190 if (subType == INVALID_UINT64) {
1191 continue;
1192 }
1193 auto subTypeStr = traceDataCache_->GetDataFromDict(subType);
1194 if (!StartWith(subTypeStr, preWord)) {
1195 continue;
1196 }
1197 auto pos = subTypeStr.find(preWord) + preWord.size();
1198 auto traceidStr = subTypeStr.substr(pos, subTypeStr.find_last_of(':') - pos);
1199 auto traceidIndex = traceDataCache_->GetDataIndex(traceidStr);
1200 traceidToCallchainidMap.emplace(std::move(traceidStr), nativeHook.CallChainIds()[i]);
1201 }
1202 }
1203
GetTraceidInfoFromCallstack(const std::unordered_map<std::string,uint32_t> & traceidToCallchainidMap,std::unordered_map<uint64_t,std::queue<SliceInfo>> & itidToCallstackIdsMap)1204 void PbreaderParser::GetTraceidInfoFromCallstack(
1205 const std::unordered_map<std::string, uint32_t> &traceidToCallchainidMap,
1206 std::unordered_map<uint64_t, std::queue<SliceInfo>> &itidToCallstackIdsMap)
1207 {
1208 auto callStack = traceDataCache_->GetConstInternalSlicesData();
1209 std::string preWord("traceid:");
1210 std::string invalidTraceidStr("0x0");
1211 for (int i = 0; i < callStack.Size(); i++) {
1212 auto name = traceDataCache_->GetDataFromDict(callStack.NamesData()[i]);
1213 if (!StartWith(name, "H:Napi execute, name:") || callStack.DursData()[i] == INVALID_UINT64) {
1214 continue;
1215 }
1216 auto traceidStr = name.substr(name.find(preWord) + preWord.size());
1217 if (traceidStr == invalidTraceidStr) {
1218 continue;
1219 }
1220 if (traceidToCallchainidMap.find(traceidStr) == traceidToCallchainidMap.end()) {
1221 continue;
1222 }
1223 auto iter = itidToCallstackIdsMap.find(callStack.CallIds()[i]);
1224 if (iter == itidToCallstackIdsMap.end()) {
1225 itidToCallstackIdsMap.emplace(callStack.CallIds()[i], std::queue<SliceInfo>());
1226 iter = itidToCallstackIdsMap.find(callStack.CallIds()[i]);
1227 }
1228 iter->second.emplace(callStack.TimeStampData()[i], callStack.TimeStampData()[i] + callStack.DursData()[i],
1229 traceidStr);
1230 }
1231 }
1232
GetCallchainIdSetFromHiperf(std::unordered_set<uint32_t> & callchainIdSet)1233 void PbreaderParser::GetCallchainIdSetFromHiperf(std::unordered_set<uint32_t> &callchainIdSet)
1234 {
1235 auto perfCallChain = traceDataCache_->GetConstPerfCallChainData();
1236 std::string asyncWork("NativeAsyncWork::AsyncWorkCallback");
1237 for (int i = 0; i < perfCallChain.Size(); i++) {
1238 auto callchainId = perfCallChain.CallChainIds()[i];
1239 if (callchainIdSet.find(callchainId) != callchainIdSet.end()) {
1240 continue;
1241 }
1242 auto nameIndex = perfCallChain.Names()[i];
1243 if (nameIndex == INVALID_UINT64) {
1244 continue;
1245 }
1246 auto name = traceDataCache_->GetDataFromDict(nameIndex);
1247 if (name.find(asyncWork) != std::string::npos) {
1248 callchainIdSet.emplace(perfCallChain.CallChainIds()[i]);
1249 }
1250 }
1251 }
1252
DumpDataFromHiperf(const std::unordered_map<std::string,uint32_t> & traceidToCallchainidMap,const std::unordered_set<uint32_t> & callchainIdSet,std::unordered_map<uint64_t,std::queue<SliceInfo>> & itidToCallstackIdsMap)1253 void PbreaderParser::DumpDataFromHiperf(const std::unordered_map<std::string, uint32_t> &traceidToCallchainidMap,
1254 const std::unordered_set<uint32_t> &callchainIdSet,
1255 std::unordered_map<uint64_t, std::queue<SliceInfo>> &itidToCallstackIdsMap)
1256 {
1257 auto perfThread = traceDataCache_->GetConstPerfThreadData();
1258 std::unordered_map<uint32_t, uint32_t> tidToPidMap;
1259 for (size_t i = 0; i < perfThread.Size(); i++) {
1260 tidToPidMap.emplace(perfThread.Tids()[i], perfThread.Pids()[i]);
1261 }
1262 auto perfSample = traceDataCache_->GetConstPerfSampleData();
1263 auto callStack = traceDataCache_->GetConstInternalSlicesData();
1264 for (size_t i = 0; i < perfSample.Size(); i++) {
1265 // callchainid未命中, 即当前栈不包含NativeAsyncWork::AsyncWorkCallback
1266 if (callchainIdSet.find(perfSample.SampleIds()[i]) == callchainIdSet.end()) {
1267 continue;
1268 }
1269 // 根据tid和tsPerfSample查询对应的SliceInfo
1270 auto itid = streamFilters_->processFilter_->GetInternalTid(perfSample.Tids()[i]);
1271 if (itidToCallstackIdsMap.find(itid) == itidToCallstackIdsMap.end()) {
1272 continue;
1273 }
1274 auto tsPerfSample = perfSample.TimestampTraces()[i];
1275 auto queue = itidToCallstackIdsMap.at(itid);
1276 while (!queue.empty() && queue.front().tsEnd_ < tsPerfSample) {
1277 queue.pop();
1278 }
1279 if (queue.empty() || tsPerfSample < queue.front().tsBegin_) {
1280 continue;
1281 }
1282 // 根据traceid查询native侧的callchainid
1283 auto iterNative = traceidToCallchainidMap.find(queue.front().traceid_);
1284 if (iterNative == traceidToCallchainidMap.end()) {
1285 continue;
1286 }
1287 // 根据tid查询pid
1288 auto iterPid = tidToPidMap.find(perfSample.Tids()[i]);
1289 if (iterPid == tidToPidMap.end()) {
1290 continue;
1291 }
1292 PerfNapiAsyncRow perfNapiAsyncRow{
1293 .timeStamp = tsPerfSample,
1294 .traceid = traceDataCache_->GetDataIndex(queue.front().traceid_),
1295 .cpuId = static_cast<uint8_t>(perfSample.CpuIds()[i]),
1296 .threadId = perfSample.Tids()[i],
1297 .processId = iterPid->second,
1298 .callerCallchainid = iterNative->second,
1299 .calleeCallchainid = perfSample.SampleIds()[i],
1300 .perfSampleId = i,
1301 .eventCount = perfSample.EventCounts()[i],
1302 .eventTypeId = perfSample.EventTypeIds()[i],
1303 };
1304 traceDataCache_->GetPerfNapiAsyncData()->AppendNewPerfNapiAsync(perfNapiAsyncRow);
1305 }
1306 }
1307 #endif
1308 } // namespace TraceStreamer
1309 } // namespace SysTuning
1310