feat(trace): 实现部分parser功能 · cpp-main/cpp-tbox@06a30a6 · GitHub
Skip to content

Commit 06a30a6

Browse files
committed
feat(trace): 实现部分parser功能
1 parent 2d3ec45 commit 06a30a6

10 files changed

Lines changed: 289 additions & 87 deletions

File tree

modules/trace/lib/sink.cpp

Lines changed: 2 additions & 3 deletions

modules/trace/lib/sink.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ class Sink {
4343
* 其名称中 "20240525_123300" 为时间戳,"7723" 为进程号。
4444
* 目录结构:
4545
* .
46-
* |-- name_list.txt # 函数名列表
47-
* |-- thread_list.txt # 线程名列表
48-
* `-- records # 记录文件目录,其下存在一个或多个记录文件
46+
* |-- names.txt # 函数名列表
47+
* |-- threads.txt # 线程名列表
48+
* `-- records # 记录文件目录,其下存在一个或多个记录文件
4949
* `-- 20240530_041046.bin
5050
*/
5151
void setPathPrefix(const std::string &path_prefix);

modules/trace/tools/parser/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ EXE_NAME := parser
2323

2424
CPP_SRC_FILES := \
2525
main.cpp \
26-
json_writer.cpp \
26+
writer.cpp \
2727

2828
CXXFLAGS := -DLOG_MODULE_ID='"$(EXE_NAME)"' $(CXXFLAGS)
2929
LDFLAGS += \

modules/trace/tools/parser/json_writer.cpp

Lines changed: 0 additions & 46 deletions
This file was deleted.

modules/trace/tools/parser/json_writer.h

Lines changed: 0 additions & 26 deletions
This file was deleted.

modules/trace/tools/parser/main.cpp

Lines changed: 128 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,145 @@
99
* \\ \ \ /
1010
* -============'
1111
*
12-
* Copyright (c) 2018 Hevake and contributors, all rights reserved.
12+
* Copyright (c) 2024 Hevake and contributors, all rights reserved.
1313
*
1414
* This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
1515
* Use of this source code is governed by MIT license that can be found
1616
* in the LICENSE file in the root of the source tree. All contributing
1717
* project authors may be found in the CONTRIBUTORS.md file in the root
1818
* of the source tree.
1919
*/
20-
#include <tbox/base/log.h>
21-
#include <tbox/base/log_output.h>
22-
#include <tbox/base/scope_exit.hpp>
20+
#include <iostream>
21+
22+
#include <tbox/util/fs.h>
23+
#include <tbox/util/buffer.h>
24+
#include <tbox/util/scalable_integer.h>
25+
26+
#include "writer.h"
2327

2428
using namespace std;
29+
using namespace tbox;
30+
31+
using StringVec = std::vector<std::string>;
32+
33+
void PrintUsage(const char *proc_name)
34+
{
35+
std::cout
36+
<< "Usage: " << proc_name << " <dir_path> [output_filename]" << std::endl
37+
<< "Exp : " << proc_name << " /some/where/my_proc.20240531_032237.114" << std::endl
38+
<< " " << proc_name << " /some/where/my_proc.20240531_032237.114 records.json" << std::endl;
39+
}
40+
41+
bool PickRecord(util::Buffer &buffer, uint64_t &end_diff_us, uint64_t &duration_us, uint64_t &thread_index, uint64_t &name_index)
42+
{
43+
uint8_t *buffer_begin = buffer.readableBegin();
44+
size_t buffer_size = buffer.readableSize();
45+
46+
size_t parse_size = 0;
47+
size_t data_size = 0;
48+
49+
parse_size = util::ParseScalableInteger((buffer_begin + data_size), (buffer_size - data_size), end_diff_us);
50+
if (parse_size == 0)
51+
return false;
52+
data_size += parse_size;
53+
54+
parse_size += util::ParseScalableInteger((buffer_begin + data_size), (buffer_size - data_size), duration_us);
55+
if (parse_size == 0)
56+
return false;
57+
data_size += parse_size;
58+
59+
parse_size += util::ParseScalableInteger((buffer_begin + data_size), (buffer_size - data_size), thread_index);
60+
if (parse_size == 0)
61+
return false;
62+
data_size += parse_size;
63+
64+
parse_size += util::ParseScalableInteger((buffer_begin + data_size), (buffer_size - data_size), name_index);
65+
if (parse_size == 0)
66+
return false;
67+
data_size += parse_size;
68+
69+
buffer.hasRead(data_size);
70+
return true;
71+
}
72+
73+
void ParseRecordFile(const std::string &filename, const StringVec &names, const StringVec &threads, trace::Writer &writer)
74+
{
75+
std::ifstream ifs(filename, std::ifstream::binary);
76+
if (!ifs) {
77+
std::cerr << "read '" << filename << "' fail!" << std::endl;
78+
return;
79+
}
80+
81+
uint64_t last_end_ts_us = 0;
82+
util::Buffer buffer;
83+
84+
while (true) {
85+
char tmp[1024];
86+
auto rsize = ifs.readsome(tmp, sizeof(tmp));
87+
if (rsize == 0)
88+
break;
89+
90+
buffer.append(tmp, rsize);
91+
92+
while (buffer.readableSize() >= 4) {
93+
uint64_t end_diff_us, duration_us, thread_index, name_index;
94+
if (!PickRecord(buffer, end_diff_us, duration_us, thread_index, name_index))
95+
break;
96+
97+
uint64_t end_ts_us = last_end_ts_us + end_diff_us;
98+
uint64_t start_ts_us = end_ts_us - duration_us;
99+
last_end_ts_us = end_ts_us;
100+
101+
std::string name = "unknown-name", thread = "unknown-thread";
102+
if (!names.empty() && name_index < names.size())
103+
name = names[name_index];
104+
if (!threads.empty() && thread_index < threads.size())
105+
thread = threads[thread_index];
106+
107+
writer.writeRecorder(name, thread, start_ts_us, duration_us);
108+
}
109+
}
110+
}
25111

26112
int main(int argc, char **argv)
27113
{
28-
LogOutput_Enable();
29-
LogInfo("hello");
30-
LogOutput_Disable();
114+
if (argc < 2) {
115+
PrintUsage(argv[0]);
116+
return 0;
117+
}
118+
119+
std::string dir_path = argv[1];
120+
if (!util::fs::IsDirectoryExist(dir_path)) {
121+
std::cout << "Error: dir_path '" << dir_path << "' not exist!" << std::endl;
122+
return 0;
123+
}
124+
125+
std::string output_filename = dir_path + "/output.json";
126+
if (argc > 2)
127+
output_filename = argv[2];
128+
129+
trace::Writer writer;
130+
if (!writer.open(output_filename)) {
131+
std::cout << "Error: output_filename '" << output_filename << "' can't be create!" << std::endl;
132+
return 0;
133+
}
134+
135+
//! 从 threads.txt 与 names.txt 导入数据
136+
std::string names_filename = dir_path + "/names.txt";
137+
std::string threads_filename = dir_path + "/threads.txt";
138+
StringVec name_vec, thread_vec;
139+
if (!util::fs::ReadAllLinesFromTextFile(names_filename, name_vec))
140+
std::cerr << "Warn: load names.txt fail!" << std::endl;
141+
if (!util::fs::ReadAllLinesFromTextFile(threads_filename, thread_vec))
142+
std::cerr << "Warn: load threads.txt fail!" << std::endl;
143+
144+
writer.writeHeader();
145+
146+
writer.writeRecorder("hello()", "12", 1000, 15);
147+
writer.writeRecorder("event()", "12", 1005, 0);
148+
writer.writeRecorder("world()", "13", 1010, 3);
149+
150+
writer.writeFooter();
31151
return 0;
32152
}
153+
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* .============.
3+
* // M A K E / \
4+
* // C++ DEV / \
5+
* // E A S Y / \/ \
6+
* ++ ----------. \/\ .
7+
* \\ \ \ /\ /
8+
* \\ \ \ /
9+
* \\ \ \ /
10+
* -============'
11+
*
12+
* Copyright (c) 2024 Hevake and contributors, all rights reserved.
13+
*
14+
* This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
15+
* Use of this source code is governed by MIT license that can be found
16+
* in the LICENSE file in the root of the source tree. All contributing
17+
* project authors may be found in the CONTRIBUTORS.md file in the root
18+
* of the source tree.
19+
*/
20+
#include "writer.h"
21+
22+
namespace tbox {
23+
namespace trace {
24+
25+
bool Writer::open(const std::string &filename)
26+
{
27+
ofs_.open(filename);
28+
return ofs_.is_open();
29+
}
30+
31+
bool Writer::writeHeader()
32+
{
33+
if (!ofs_.is_open())
34+
return false;
35+
36+
ofs_ << R"({"otherData":{},"traceEvents":[)" << std::endl;
37+
ofs_.flush();
38+
39+
is_first_record_ = true;
40+
return true;
41+
}
42+
43+
bool Writer::writeRecorder(const std::string &name, const std::string &tid, uint64_t start_ts_us, uint64_t duration_us)
44+
{
45+
if (!ofs_.is_open())
46+
return false;
47+
48+
if (!is_first_record_)
49+
ofs_ << ',' << std::endl;
50+
is_first_record_ = false;
51+
52+
ofs_ << R"({"name":")" << name << R"(","cat":"function","pid":"","tid":")"
53+
<< tid << R"(","ts":)" << start_ts_us << ',';
54+
55+
if (duration_us != 0)
56+
ofs_ << R"("ph":"X","dur":)" << duration_us;
57+
else
58+
ofs_ << R"("ph":"I")";
59+
60+
ofs_ << "}";
61+
ofs_.flush();
62+
63+
return true;
64+
}
65+
66+
bool Writer::writeFooter()
67+
{
68+
if (!ofs_.is_open())
69+
return false;
70+
71+
ofs_ << std::endl << R"(]})" << std::endl;
72+
ofs_.flush();
73+
74+
return true;
75+
}
76+
77+
}
78+
}
Lines changed: 46 additions & 0 deletions

0 commit comments

Comments
 (0)