• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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