1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <chrono>
16 #include <cinttypes>
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <fstream>
20 #include <iostream>
21 #include <memory>
22 #include <regex>
23 #include <cstdio>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include "codec_cov.h"
29 #include "file.h"
30 #include "filter/slice_filter.h"
31 #include "log.h"
32 #include "metrics.h"
33 #include "parser/bytrace_parser/bytrace_event_parser.h"
34 #include "parser/bytrace_parser/bytrace_parser.h"
35 #include "parting_string.h"
36 #include "rpc_server.h"
37 #include "string_help.h"
38
39 #include "thread_state_flag.h"
40 #include "trace_streamer/trace_streamer_selector.h"
41 #include "trace_streamer_filters.h"
42 #include "version.h"
43 using namespace SysTuning::TraceStreamer;
44 using namespace SysTuning;
45 namespace SysTuning {
46 namespace TraceStreamer {
47 using namespace SysTuning::TraceStreamer;
48 using namespace SysTuning::base;
49 constexpr int G_MIN_PARAM_NUM = 2;
50 constexpr size_t G_FILE_PERMISSION = 664;
51 constexpr uint8_t RAW_TRACE_PARSE_MAX = 2;
52 constexpr uint8_t PARSER_THREAD_MAX = 16;
53 constexpr uint8_t PARSER_THREAD_MIN = 1;
54 // set version info in meta.cpp please
ExportStatusToLog(const std::string & dbPath,TraceParserStatus status)55 void ExportStatusToLog(const std::string& dbPath, TraceParserStatus status)
56 {
57 std::string path = dbPath + ".ohos.ts";
58 std::ofstream out(path, std::ios_base::trunc);
59 out << (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
60 .count()
61 << ":" << status << std::endl;
62 using std::chrono::system_clock;
63
64 system_clock::time_point today = system_clock::now();
65
66 std::time_t tt = system_clock::to_time_t(today);
67 out << "last running time is: " << ctime(&tt);
68 out << "last running status is: " << status;
69 out.close();
70 }
ShowHelpInfo(const char * argv)71 void ShowHelpInfo(const char* argv)
72 {
73 printf(
74 "trace analyze tool, it can transfer a bytrace/htrace file into a "
75 "SQLite database and save result to a local file trace_streamer.log.\n"
76 "Usage: %s FILE -e sqlite_out.db\n"
77 " or %s FILE -c\n"
78 "Options:\n"
79 " -e transfer a trace file into a SQLiteBased DB. with -nm to except meta table\n"
80 " -c command line mode.\n"
81 " -D Specify the directory path with multiple long trace files"
82 " -d dump perf/hook/ebpf readable text.Default dump file path is src path name + `_ReadableText.txt`\n"
83 " -h start HTTP server.\n"
84 " -l <level>, --level=<level>\n"
85 " Show specific level/levels logs with format: level1,level2,level3\n"
86 " Long level string coule be: DEBUG/INFO/WARN/ERROR/FATAL/OFF.\n"
87 " Short level string coule be: D/I/W/E/F/O.\n"
88 " Default level is OFF.\n"
89 " -o set dump file path.\n"
90 " -s separate arkts-plugin data, and save it in current dir with default filename.\n"
91 " -p Specify the port of HTTP server, default is 9001.\n"
92 " -q select sql from file.\n"
93 " -m Perform operations that query metrics through linux,supports querying multiple metrics items.For "
94 "example:-m x,y,z.\n"
95 " -tn <num> set parser thread num, min is 1, max is 16.\n"
96 " -nt close muti thread.\n"
97 " -i show information.\n"
98 " -v show version.\n",
99 argv, argv);
100 }
PrintInformation()101 void PrintInformation()
102 {
103 TraceStreamerConfig cfg;
104 cfg.PrintInfo();
105 }
PrintVersion()106 void PrintVersion()
107 {
108 (void)fprintf(stderr, "version %s\n", g_traceStreamerVersion.c_str());
109 }
110
ReadAndParser(SysTuning::TraceStreamer::TraceStreamerSelector & ta,int fd)111 bool ReadAndParser(SysTuning::TraceStreamer::TraceStreamerSelector& ta, int fd)
112 {
113 auto startTime =
114 (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
115 .count();
116 auto isFinish = false;
117 g_loadSize = 0;
118 auto curParseCnt = 1;
119 while (true) {
120 // for rawtrace next parse.the first parse is for last comm data;
121 if (isFinish && ta.GetFileType() == TRACE_FILETYPE_RAW_TRACE && curParseCnt < RAW_TRACE_PARSE_MAX) {
122 ++curParseCnt;
123 isFinish = false;
124 g_loadSize = 0;
125 TS_CHECK_TRUE(lseek(fd, 0, SEEK_SET) != -1, false, "lseek error:%s", strerror(errno));
126 }
127 std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(G_CHUNK_SIZE);
128 auto rsize = Read(fd, buf.get(), G_CHUNK_SIZE);
129 if (rsize == 0) {
130 break;
131 }
132
133 if (rsize < 0) {
134 TS_LOGE("Reading trace file failed (errno: %d, %s)", errno, strerror(errno));
135 return false;
136 }
137 g_loadSize += rsize;
138 if (g_loadSize == g_fileSize) {
139 isFinish = true;
140 }
141 if (!ta.ParseTraceDataSegment(std::move(buf), static_cast<size_t>(rsize), false, isFinish)) {
142 return false;
143 };
144 printf("\rLoadingFile:\t%.2f MB\r", static_cast<double>(g_loadSize) / 1E6);
145 }
146 ta.WaitForParserEnd();
147 auto endTime =
148 (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
149 .count();
150 (void)fprintf(stdout, "\nParserDuration:\t%u ms\n", static_cast<unsigned int>(endTime - startTime));
151 (void)fprintf(stdout, "ParserSpeed:\t%.2f MB/s\n", (g_loadSize / (endTime - startTime) / 1E3));
152 return true;
153 }
SetFileSize(const std::string & traceFilePath)154 bool SetFileSize(const std::string& traceFilePath)
155 {
156 if (traceFilePath.empty()) {
157 g_fileSize = 0;
158 return false;
159 }
160 struct stat statBuff;
161 stat(traceFilePath.c_str(), &statBuff);
162 g_fileSize = statBuff.st_size;
163 return true;
164 }
OpenAndParserFile(TraceStreamerSelector & ts,const std::string & traceFilePath)165 int OpenAndParserFile(TraceStreamerSelector& ts, const std::string& traceFilePath)
166 {
167 if (!SetFileSize(traceFilePath)) {
168 return 0;
169 }
170 int fd(OpenFile(traceFilePath, O_RDONLY, G_FILE_PERMISSION));
171 if (fd < 0) {
172 TS_LOGE("%s does not exist", traceFilePath.c_str());
173 SetAnalysisResult(TRACE_PARSER_ABNORMAL);
174 return 1;
175 }
176 if (!ReadAndParser(ts, fd)) {
177 close(fd);
178 SetAnalysisResult(TRACE_PARSER_ABNORMAL);
179 return 1;
180 }
181 MetaData* metaData = ts.GetMetaData();
182
183 std::string fileNameTmp = traceFilePath;
184 #ifdef _WIN32
185 if (!base::GetCoding(reinterpret_cast<const uint8_t*>(fileNameTmp.c_str()), fileNameTmp.length())) {
186 fileNameTmp = base::GbkToUtf8(fileNameTmp.c_str());
187 }
188 #endif
189 metaData->SetSourceFileName(fileNameTmp);
190 metaData->SetTraceType((ts.DataType() == TRACE_FILETYPE_H_TRACE) ? "proto-based-trace" : "txt-based-trace");
191
192 close(fd);
193 return 0;
194 }
ExportDatabase(TraceStreamerSelector & ts,const std::string & sqliteFilePath)195 int ExportDatabase(TraceStreamerSelector& ts, const std::string& sqliteFilePath)
196 {
197 auto startTime =
198 (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
199 .count();
200 if (!sqliteFilePath.empty()) {
201 MetaData* metaData = ts.GetMetaData();
202 std::string fileNameTmp = sqliteFilePath;
203 #ifdef _WIN32
204 if (!base::GetCoding(reinterpret_cast<const uint8_t*>(fileNameTmp.c_str()), fileNameTmp.length())) {
205 fileNameTmp = base::GbkToUtf8(fileNameTmp.c_str());
206 }
207 #endif
208 metaData->SetOutputFileName(fileNameTmp);
209 metaData->SetParserToolVersion(g_traceStreamerVersion);
210 metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion);
211 metaData->SetTraceDataSize(g_loadSize);
212 if (ts.ExportDatabase(sqliteFilePath)) {
213 fprintf(stdout, "ExportDatabase failed\n");
214 ExportStatusToLog(sqliteFilePath, TRACE_PARSER_ABNORMAL);
215 return 1;
216 }
217 }
218 auto endTime =
219 (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()))
220 .count();
221 endTime += 1; // for any exception of endTime == startTime
222 (void)fprintf(stdout, "ExportDuration:\t%u ms\n", static_cast<unsigned int>(endTime - startTime));
223 (void)fprintf(stdout, "ExportSpeed:\t%.2f MB/s\n", (g_loadSize / (endTime - startTime)) / 1E3);
224 return 0;
225 }
LongTraceExportDatabase(TraceStreamerSelector & ts,const std::string & sqliteFilePath)226 bool LongTraceExportDatabase(TraceStreamerSelector& ts, const std::string& sqliteFilePath)
227 {
228 if (!sqliteFilePath.empty()) {
229 std::string fileNameTmp = sqliteFilePath;
230 #ifdef _WIN32
231 if (!base::GetCoding(reinterpret_cast<const uint8_t*>(fileNameTmp.c_str()), fileNameTmp.length())) {
232 fileNameTmp = base::GbkToUtf8(fileNameTmp.c_str());
233 }
234 #endif
235 if (ts.BatchExportDatabase(sqliteFilePath)) {
236 fprintf(stdout, "ExportDatabase failed\n");
237 ExportStatusToLog(sqliteFilePath, TRACE_PARSER_ABNORMAL);
238 return false;
239 }
240 }
241 return true;
242 }
243 enum DumpFileType { UNKONW_TYPE = 0, PERF_TYPE, NATIVE_HOOK_TYPE, EBPF_TYPE };
244 struct TraceExportOption {
245 std::string longTraceDir;
246 std::string traceFilePath;
247 std::string sqliteFilePath;
248 DumpFileType dumpFileType = DumpFileType::UNKONW_TYPE;
249 std::string outputFilePath;
250 std::string metricsIndex;
251 std::string sqlOperatorFilePath;
252 bool interactiveState = false;
253 bool exportMetaTable = true;
254 bool separateFile = false;
255 bool closeMutiThread = false;
256 uint8_t parserThreadNum = INVALID_UINT8;
257 };
CheckFinal(char ** argv,TraceExportOption & traceExportOption)258 bool CheckFinal(char** argv, TraceExportOption& traceExportOption)
259 {
260 if (((traceExportOption.traceFilePath.empty() && traceExportOption.longTraceDir.empty()) ||
261 (!traceExportOption.interactiveState && traceExportOption.sqliteFilePath.empty())) &&
262 !traceExportOption.separateFile && traceExportOption.metricsIndex.empty() &&
263 traceExportOption.sqlOperatorFilePath.empty() && traceExportOption.outputFilePath.empty() &&
264 traceExportOption.dumpFileType == DumpFileType::UNKONW_TYPE) {
265 ShowHelpInfo(argv[0]);
266 return false;
267 }
268 return true;
269 }
270
CheckArgc(int argc,char ** argv,int curArgNum)271 bool CheckArgc(int argc, char** argv, int curArgNum)
272 {
273 if (curArgNum == argc) {
274 ShowHelpInfo(argv[0]);
275 return false;
276 }
277 return true;
278 }
CheckAndSetLogLevel(int argc,char ** argv,int & index)279 bool CheckAndSetLogLevel(int argc, char** argv, int& index)
280 {
281 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
282 if (SetLogLevel(std::string(argv[index]))) {
283 return true;
284 }
285 ShowHelpInfo(argv[0]);
286 return false;
287 }
CheckAndSetMetrics(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)288 bool CheckAndSetMetrics(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
289 {
290 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
291 traceExportOption.metricsIndex = std::string(argv[index]);
292 return true;
293 }
CheckAndSetThreadNum(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)294 bool CheckAndSetThreadNum(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
295 {
296 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
297 traceExportOption.parserThreadNum = std::stoi(argv[index]);
298 return true;
299 }
300
CheckAndSetSqlitePath(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)301 bool CheckAndSetSqlitePath(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
302 {
303 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
304 traceExportOption.sqliteFilePath = std::string(argv[index]);
305 return true;
306 }
CheckAndSetOutputFilePath(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)307 bool CheckAndSetOutputFilePath(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
308 {
309 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
310 traceExportOption.outputFilePath = std::string(argv[index]);
311 return true;
312 }
CheckAndSetSqlQueryFilePath(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)313 bool CheckAndSetSqlQueryFilePath(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
314 {
315 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
316 traceExportOption.sqlOperatorFilePath = std::string(argv[index]);
317 return true;
318 }
CheckAndSetDumpFileType(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)319 bool CheckAndSetDumpFileType(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
320 {
321 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
322 auto dumpFileType = std::string(argv[index]);
323 if (dumpFileType == "perf") {
324 traceExportOption.dumpFileType = DumpFileType::PERF_TYPE;
325 } else if (dumpFileType == "hook") {
326 traceExportOption.dumpFileType = DumpFileType::NATIVE_HOOK_TYPE;
327 } else if (dumpFileType == "ebpf") {
328 traceExportOption.dumpFileType = DumpFileType::EBPF_TYPE;
329 } else {
330 ShowHelpInfo(argv[0]);
331 return false;
332 }
333 if (!traceExportOption.outputFilePath.empty()) {
334 auto strVec = SplitStringToVec(traceExportOption.traceFilePath, ".");
335 traceExportOption.outputFilePath = strVec.front() + "_ReadableText.txt";
336 }
337 return true;
338 }
CheckAndSetLongTraceDir(TraceExportOption & traceExportOption,int argc,char ** argv,int & index)339 bool CheckAndSetLongTraceDir(TraceExportOption& traceExportOption, int argc, char** argv, int& index)
340 {
341 TS_CHECK_TRUE_RET(CheckArgc(argc, argv, ++index), false);
342 traceExportOption.longTraceDir = std::string(argv[index]);
343 return true;
344 }
ParseOtherArgs(int argc,char ** argv,TraceExportOption & traceExportOption,int i)345 bool ParseOtherArgs(int argc, char** argv, TraceExportOption& traceExportOption, int i)
346 {
347 if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) {
348 PrintInformation();
349 } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--level")) {
350 TS_CHECK_TRUE_RET(CheckAndSetLogLevel(argc, argv, i), false);
351 return true;
352 } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--s")) {
353 traceExportOption.separateFile = true;
354 return true;
355 } else if (!strcmp(argv[i], "-tn") || !strcmp(argv[i], "--threadnum")) {
356 TS_CHECK_TRUE_RET(CheckAndSetThreadNum(traceExportOption, argc, argv, i), false);
357 return true;
358 } else if (!strcmp(argv[i], "-nt") || !strcmp(argv[i], "--nothreads")) {
359 traceExportOption.closeMutiThread = true;
360 return true;
361 } else if (!strcmp(argv[i], "-nm") || !strcmp(argv[i], "--nometa")) {
362 traceExportOption.exportMetaTable = false;
363 return true;
364 } else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--run-metrics")) {
365 TS_CHECK_TRUE_RET(CheckAndSetMetrics(traceExportOption, argc, argv, i), false);
366 return true;
367 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
368 PrintVersion();
369 return false;
370 }
371 traceExportOption.traceFilePath = std::string(argv[i]);
372 return true;
373 }
ParseArgs(int argc,char ** argv,TraceExportOption & traceExportOption)374 bool ParseArgs(int argc, char** argv, TraceExportOption& traceExportOption)
375 {
376 for (int i = 1; i < argc; i++) {
377 if (!strcmp(argv[i], "-e")) {
378 TS_CHECK_TRUE_RET(CheckAndSetSqlitePath(traceExportOption, argc, argv, i), false);
379 continue;
380 } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) {
381 traceExportOption.interactiveState = true;
382 continue;
383 } else if (!strcmp(argv[i], "-D") || !strcmp(argv[i], "--directory")) {
384 TS_CHECK_TRUE_RET(CheckAndSetLongTraceDir(traceExportOption, argc, argv, i), false);
385 continue;
386 } else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--dump")) {
387 TS_CHECK_TRUE_RET(CheckAndSetDumpFileType(traceExportOption, argc, argv, i), false);
388 continue;
389 } else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--query-file")) {
390 TS_CHECK_TRUE_RET(CheckAndSetSqlQueryFilePath(traceExportOption, argc, argv, i), false);
391 continue;
392 } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--out")) {
393 TS_CHECK_TRUE_RET(CheckAndSetOutputFilePath(traceExportOption, argc, argv, i), false);
394 continue;
395 } else if (!ParseOtherArgs(argc, argv, traceExportOption, i)) {
396 return false;
397 }
398 }
399 return CheckFinal(argv, traceExportOption);
400 }
401
GetLongTraceFilePaths(const TraceExportOption & traceExportOption,std::map<int,std::string> & seqToFilePathMap)402 bool GetLongTraceFilePaths(const TraceExportOption& traceExportOption, std::map<int, std::string>& seqToFilePathMap)
403 {
404 std::regex traceInvalidStr("\\\\");
405 auto strEscape = std::regex_replace(traceExportOption.longTraceDir, traceInvalidStr, "\\\\\\\\");
406 DIR* dir = opendir(strEscape.c_str());
407 if (dir == nullptr) {
408 TS_LOGE("long trace dir is not exist or not dir");
409 return false;
410 }
411 dirent* entry;
412 while ((entry = readdir(dir)) != nullptr) {
413 std::regex pattern("^hiprofiler_data_(\\d{8})_(\\d{6})_(\\d+)\\.htrace$");
414 std::smatch matches;
415 std::string name = entry->d_name;
416 if (std::regex_match(name, matches, pattern)) {
417 std::string seqStr = matches[3].str();
418 int seq = std::stoi(seqStr);
419 std::string path = std::string(strEscape) + "/" + name;
420 seqToFilePathMap.insert({seq, path});
421 }
422 }
423 closedir(dir);
424 if (!seqToFilePathMap.size()) {
425 TS_LOGE("%s has no matched file!", strEscape.c_str());
426 return false;
427 }
428 auto seq = seqToFilePathMap.begin()->first;
429 for (auto itor = seqToFilePathMap.begin(); itor != seqToFilePathMap.end(); itor++) {
430 if (itor->first != seq++) {
431 seqToFilePathMap.erase(itor, seqToFilePathMap.end());
432 break;
433 }
434 }
435 return true;
436 }
437
ReadAndParserLongTrace(SysTuning::TraceStreamer::TraceStreamerSelector & ta,int fd,const std::string & traceFilePath)438 bool ReadAndParserLongTrace(SysTuning::TraceStreamer::TraceStreamerSelector& ta,
439 int fd,
440 const std::string& traceFilePath)
441 {
442 printf("Start Parse %s ...\n", traceFilePath.c_str());
443 g_loadSize = 0;
444 while (true) {
445 std::unique_ptr<uint8_t[]> buf = std::make_unique<uint8_t[]>(G_CHUNK_SIZE);
446 auto rSize = Read(fd, buf.get(), G_CHUNK_SIZE);
447 if (rSize == 0) {
448 break;
449 }
450 if (rSize < 0) {
451 TS_LOGE("Reading trace file failed (errno: %d, %s)", errno, strerror(errno));
452 return false;
453 }
454 g_loadSize += rSize;
455 if (!ta.BatchParseTraceDataSegment(std::move(buf), static_cast<size_t>(rSize))) {
456 return false;
457 }
458 printf("\rLoadingFile:\t%.2f MB\r", static_cast<double>(g_loadSize) / 1E6);
459 }
460 return true;
461 }
OpenAndParserLongTraceFile(TraceStreamerSelector & ts,const std::string & traceFilePath)462 bool OpenAndParserLongTraceFile(TraceStreamerSelector& ts, const std::string& traceFilePath)
463 {
464 if (!SetFileSize(traceFilePath)) {
465 return false;
466 }
467 int fd(OpenFile(traceFilePath, O_RDONLY, G_FILE_PERMISSION));
468 if (fd < 0) {
469 TS_LOGE("%s does not exist", traceFilePath.c_str());
470 SetAnalysisResult(TRACE_PARSER_ABNORMAL);
471 return false;
472 }
473 if (!ReadAndParserLongTrace(ts, fd, traceFilePath)) {
474 close(fd);
475 SetAnalysisResult(TRACE_PARSER_ABNORMAL);
476 return false;
477 }
478 close(fd);
479 return true;
480 }
ParseLongTrace(TraceStreamerSelector & ts,const TraceExportOption & traceExportOption)481 void ParseLongTrace(TraceStreamerSelector& ts, const TraceExportOption& traceExportOption)
482 {
483 std::map<int, std::string> seqToFilePathMap;
484 if (traceExportOption.sqliteFilePath.empty()) {
485 return;
486 }
487 if (!GetLongTraceFilePaths(traceExportOption, seqToFilePathMap)) {
488 return;
489 }
490 ts.CreatEmptyBatchDB(traceExportOption.sqliteFilePath);
491 for (auto itor = seqToFilePathMap.begin(); itor != seqToFilePathMap.end(); itor++) {
492 ts.GetTraceDataCache()->UpdateAllPrevSize();
493 if (!OpenAndParserLongTraceFile(ts, itor->second)) {
494 break;
495 }
496 if (std::distance(itor, seqToFilePathMap.end()) == 1) {
497 ts.WaitForParserEnd();
498 }
499 ts.GetTraceDataCache()->ClearAllPrevCacheData();
500 ts.GetStreamFilter()->FilterClear();
501 if (!LongTraceExportDatabase(ts, traceExportOption.sqliteFilePath)) {
502 return;
503 }
504 if (std::distance(itor, seqToFilePathMap.end()) == 1) {
505 ts.RevertTableName(traceExportOption.sqliteFilePath);
506 }
507 }
508 if (!traceExportOption.sqliteFilePath.empty()) {
509 ExportStatusToLog(traceExportOption.sqliteFilePath, GetAnalysisResult());
510 }
511 }
ExportReadableText(TraceStreamerSelector & ts,const TraceExportOption & traceExportOption)512 void ExportReadableText(TraceStreamerSelector& ts, const TraceExportOption& traceExportOption)
513 {
514 if (traceExportOption.dumpFileType == DumpFileType::PERF_TYPE) {
515 ts.ExportPerfReadableText(traceExportOption.outputFilePath);
516 } else if (traceExportOption.dumpFileType == DumpFileType::NATIVE_HOOK_TYPE) {
517 ts.ExportHookReadableText(traceExportOption.outputFilePath);
518 } else if (traceExportOption.dumpFileType == DumpFileType::EBPF_TYPE) {
519 ts.ExportEbpfReadableText(traceExportOption.outputFilePath);
520 }
521 }
CheckAndParseArgs(int argc,char ** argv,TraceExportOption & traceExportOption)522 bool CheckAndParseArgs(int argc, char** argv, TraceExportOption& traceExportOption)
523 {
524 if (argc < G_MIN_PARAM_NUM) {
525 ShowHelpInfo(argv[0]);
526 return false;
527 }
528 int ret = ParseArgs(argc, argv, traceExportOption);
529 if (ret) {
530 if (!traceExportOption.sqliteFilePath.empty()) {
531 ExportStatusToLog(traceExportOption.sqliteFilePath, GetAnalysisResult());
532 }
533 return true;
534 }
535 return false;
536 }
EnterInteractiveState(TraceStreamerSelector & ts)537 bool EnterInteractiveState(TraceStreamerSelector& ts)
538 {
539 MetaData* metaData = ts.GetMetaData();
540 metaData->SetOutputFileName("command line mode");
541 metaData->SetParserToolVersion(g_traceStreamerVersion.c_str());
542 metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion.c_str());
543 metaData->SetTraceDataSize(g_loadSize);
544 while (true) {
545 auto values = ts.SearchData();
546 if (!values.empty()) {
547 std::string symbolsPath = "default";
548 ts.ReloadSymbolFiles(symbolsPath, values);
549 } else {
550 return false;
551 }
552 }
553 }
Init(TraceStreamerSelector & ts,const TraceExportOption & traceExportOption)554 void Init(TraceStreamerSelector& ts, const TraceExportOption& traceExportOption)
555 {
556 ts.EnableMetaTable(traceExportOption.exportMetaTable);
557 ts.EnableFileSave(traceExportOption.separateFile);
558 if (traceExportOption.closeMutiThread) {
559 ts.GetTraceDataCache()->supportThread_ = false;
560 }
561 if (traceExportOption.parserThreadNum != INVALID_UINT8 && traceExportOption.parserThreadNum > PARSER_THREAD_MIN &&
562 traceExportOption.parserThreadNum <= PARSER_THREAD_MAX) {
563 ts.GetTraceDataCache()->parserThreadNum_ = traceExportOption.parserThreadNum;
564 }
565 }
566
567 } // namespace TraceStreamer
568 } // namespace SysTuning
main(int argc,char ** argv)569 int main(int argc, char** argv)
570 {
571 TraceExportOption traceExportOption;
572 TS_CHECK_TRUE_RET(CheckAndParseArgs(argc, argv, traceExportOption), 1);
573 TraceStreamerSelector ts;
574 Init(ts, traceExportOption);
575 #ifndef IS_WASM
576 if (!traceExportOption.longTraceDir.empty()) {
577 ParseLongTrace(ts, traceExportOption);
578 return 0;
579 }
580 #endif
581 std::regex traceInvalidStr("\\\\");
582 auto strEscape = std::regex_replace(traceExportOption.traceFilePath, traceInvalidStr, "\\\\\\\\");
583 if (OpenAndParserFile(ts, strEscape)) {
584 if (!traceExportOption.sqliteFilePath.empty()) {
585 ExportStatusToLog(traceExportOption.sqliteFilePath, GetAnalysisResult());
586 }
587 return 1;
588 }
589 if (traceExportOption.interactiveState) {
590 TS_CHECK_TRUE_RET(EnterInteractiveState(ts), 1);
591 }
592 if (traceExportOption.dumpFileType != DumpFileType::UNKONW_TYPE) {
593 ExportReadableText(ts, traceExportOption);
594 }
595 if (!traceExportOption.sqliteFilePath.empty()) {
596 if (ExportDatabase(ts, traceExportOption.sqliteFilePath)) {
597 ExportStatusToLog(traceExportOption.sqliteFilePath, GetAnalysisResult());
598 return 1;
599 }
600 if (!traceExportOption.sqliteFilePath.empty()) {
601 ExportStatusToLog(traceExportOption.sqliteFilePath, GetAnalysisResult());
602 }
603 }
604 if (!traceExportOption.metricsIndex.empty()) {
605 MetaData* metaData = ts.GetMetaData();
606 metaData->SetOutputFileName("command line mode");
607 metaData->SetParserToolVersion(g_traceStreamerVersion.c_str());
608 metaData->SetParserToolPublishDateTime(g_traceStreamerPublishVersion.c_str());
609 metaData->SetTraceDataSize(g_loadSize);
610 ts.ParserAndPrintMetrics(traceExportOption.metricsIndex);
611 }
612 if (!traceExportOption.sqlOperatorFilePath.empty()) {
613 ts.ReadSqlFileAndPrintResult(traceExportOption.sqlOperatorFilePath);
614 }
615 return 0;
616 }
617