Skip to content

Commit daafe6c

Browse files
addaleaxtargos
authored andcommitted
src: refactor tracing agent code
Avoid unnecessary operations, add a bit of documentation, and turn the `ClientHandle` smart pointer alias into a real class. This should allow de-coupling the unnecessary combination of a single specific `file_writer` from `Agent`. PR-URL: #21867 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
1 parent 4379140 commit daafe6c

File tree

5 files changed

+87
-58
lines changed

5 files changed

+87
-58
lines changed

src/inspector/tracing_agent.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ class InspectorTraceWriter : public node::tracing::AsyncTraceWriter {
4646
} // namespace
4747

4848
TracingAgent::TracingAgent(Environment* env)
49-
: env_(env),
50-
trace_writer_(
51-
tracing::Agent::EmptyClientHandle()) {
49+
: env_(env) {
5250
}
5351

5452
TracingAgent::~TracingAgent() {
@@ -62,7 +60,7 @@ void TracingAgent::Wire(UberDispatcher* dispatcher) {
6260

6361
DispatchResponse TracingAgent::start(
6462
std::unique_ptr<protocol::NodeTracing::TraceConfig> traceConfig) {
65-
if (trace_writer_ != nullptr) {
63+
if (!trace_writer_.empty()) {
6664
return DispatchResponse::Error(
6765
"Call NodeTracing::end to stop tracing before updating the config");
6866
}

src/inspector/tracing_agent.h

+2-6
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22
#define SRC_INSPECTOR_TRACING_AGENT_H_
33

44
#include "node/inspector/protocol/NodeTracing.h"
5+
#include "tracing/agent.h"
56
#include "v8.h"
67

78

89
namespace node {
910
class Environment;
1011

11-
namespace tracing {
12-
class Agent;
13-
} // namespace tracing
14-
1512
namespace inspector {
1613
namespace protocol {
1714

@@ -32,8 +29,7 @@ class TracingAgent : public NodeTracing::Backend {
3229
void DisconnectTraceClient();
3330

3431
Environment* env_;
35-
std::unique_ptr<std::pair<tracing::Agent*, int>,
36-
void (*)(std::pair<tracing::Agent*, int>*)> trace_writer_;
32+
tracing::AgentWriterHandle trace_writer_;
3733
std::unique_ptr<NodeTracing::Frontend> frontend_;
3834
};
3935

src/node.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ class NodeTraceStateObserver :
387387
static struct {
388388
#if NODE_USE_V8_PLATFORM
389389
void Initialize(int thread_pool_size) {
390-
tracing_agent_.reset(new tracing::Agent(trace_file_pattern));
390+
tracing_agent_.reset(new tracing::Agent());
391391
auto controller = tracing_agent_->GetTracingController();
392392
controller->AddTraceStateObserver(new NodeTraceStateObserver(controller));
393393
tracing::TraceEventHelper::SetTracingController(controller);
@@ -427,12 +427,13 @@ static struct {
427427
#endif // HAVE_INSPECTOR
428428

429429
void StartTracingAgent() {
430-
tracing_agent_->Enable(trace_enabled_categories);
430+
tracing_file_writer_ = tracing_agent_->AddClient(
431+
trace_enabled_categories,
432+
new tracing::NodeTraceWriter(trace_file_pattern));
431433
}
432434

433435
void StopTracingAgent() {
434-
if (tracing_agent_)
435-
tracing_agent_->Stop();
436+
tracing_file_writer_.reset();
436437
}
437438

438439
tracing::Agent* GetTracingAgent() const {
@@ -444,6 +445,7 @@ static struct {
444445
}
445446

446447
std::unique_ptr<tracing::Agent> tracing_agent_;
448+
tracing::AgentWriterHandle tracing_file_writer_;
447449
NodePlatform* platform_;
448450
#else // !NODE_USE_V8_PLATFORM
449451
void Initialize(int thread_pool_size) {}

src/tracing/agent.cc

+20-26
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ using v8::platform::tracing::TraceWriter;
4444
using std::string;
4545

4646
Agent::Agent(const std::string& log_file_pattern)
47-
: log_file_pattern_(log_file_pattern), file_writer_(EmptyClientHandle()) {
47+
: log_file_pattern_(log_file_pattern) {
4848
tracing_controller_ = new TracingController();
4949
tracing_controller_->Initialize(nullptr);
5050
}
@@ -62,20 +62,23 @@ void Agent::Start() {
6262
// This thread should be created *after* async handles are created
6363
// (within NodeTraceWriter and NodeTraceBuffer constructors).
6464
// Otherwise the thread could shut down prematurely.
65-
CHECK_EQ(0, uv_thread_create(&thread_, ThreadCb, this));
65+
CHECK_EQ(0, uv_thread_create(&thread_, [](void* arg) {
66+
Agent* agent = static_cast<Agent*>(arg);
67+
uv_run(&agent->tracing_loop_, UV_RUN_DEFAULT);
68+
}, this));
6669
started_ = true;
6770
}
6871

69-
Agent::ClientHandle Agent::AddClient(const std::set<std::string>& categories,
70-
std::unique_ptr<AsyncTraceWriter> writer) {
72+
AgentWriterHandle Agent::AddClient(
73+
const std::set<std::string>& categories,
74+
std::unique_ptr<AsyncTraceWriter> writer) {
7175
Start();
7276
ScopedSuspendTracing suspend(tracing_controller_, this);
7377
int id = next_writer_id_++;
7478
writers_[id] = std::move(writer);
7579
categories_[id] = categories;
7680

77-
auto client_id = new std::pair<Agent*, int>(this, id);
78-
return ClientHandle(client_id, &DisconnectClient);
81+
return AgentWriterHandle(this, id);
7982
}
8083

8184
void Agent::Stop() {
@@ -101,61 +104,52 @@ void Agent::Disconnect(int client) {
101104
categories_.erase(client);
102105
}
103106

104-
// static
105-
void Agent::ThreadCb(void* arg) {
106-
Agent* agent = static_cast<Agent*>(arg);
107-
uv_run(&agent->tracing_loop_, UV_RUN_DEFAULT);
108-
}
109-
110107
void Agent::Enable(const std::string& categories) {
111108
if (categories.empty())
112109
return;
113110
std::set<std::string> categories_set;
114-
std::stringstream category_list(categories);
111+
std::istringstream category_list(categories);
115112
while (category_list.good()) {
116113
std::string category;
117114
getline(category_list, category, ',');
118-
categories_set.insert(category);
115+
categories_set.emplace(std::move(category));
119116
}
120117
Enable(categories_set);
121118
}
122119

123120
void Agent::Enable(const std::set<std::string>& categories) {
124-
std::string cats;
125-
for (const std::string cat : categories)
126-
cats += cat + ", ";
127121
if (categories.empty())
128122
return;
129123

130124
file_writer_categories_.insert(categories.begin(), categories.end());
131125
std::set<std::string> full_list(file_writer_categories_.begin(),
132126
file_writer_categories_.end());
133-
if (!file_writer_) {
127+
if (file_writer_.empty()) {
134128
// Ensure background thread is running
135129
Start();
136130
std::unique_ptr<NodeTraceWriter> writer(
137131
new NodeTraceWriter(log_file_pattern_, &tracing_loop_));
138132
file_writer_ = AddClient(full_list, std::move(writer));
139133
} else {
140134
ScopedSuspendTracing suspend(tracing_controller_, this);
141-
categories_[file_writer_->second] = full_list;
135+
categories_[file_writer_.id_] = full_list;
142136
}
143137
}
144138

145139
void Agent::Disable(const std::set<std::string>& categories) {
146-
for (auto category : categories) {
140+
for (const std::string& category : categories) {
147141
auto it = file_writer_categories_.find(category);
148142
if (it != file_writer_categories_.end())
149143
file_writer_categories_.erase(it);
150144
}
151-
if (!file_writer_)
145+
if (file_writer_.empty())
152146
return;
153147
ScopedSuspendTracing suspend(tracing_controller_, this);
154-
categories_[file_writer_->second] = { file_writer_categories_.begin(),
155-
file_writer_categories_.end() };
148+
categories_[file_writer_.id_] = { file_writer_categories_.begin(),
149+
file_writer_categories_.end() };
156150
}
157151

158-
TraceConfig* Agent::CreateTraceConfig() {
152+
TraceConfig* Agent::CreateTraceConfig() const {
159153
if (categories_.empty())
160154
return nullptr;
161155
TraceConfig* trace_config = new TraceConfig();
@@ -165,9 +159,9 @@ TraceConfig* Agent::CreateTraceConfig() {
165159
return trace_config;
166160
}
167161

168-
std::string Agent::GetEnabledCategories() {
162+
std::string Agent::GetEnabledCategories() const {
169163
std::string categories;
170-
for (const auto& category : flatten(categories_)) {
164+
for (const std::string& category : flatten(categories_)) {
171165
if (!categories.empty())
172166
categories += ',';
173167
categories += category;

src/tracing/agent.h

+57-18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "libplatform/v8-tracing.h"
55
#include "uv.h"
66
#include "v8.h"
7+
#include "util.h"
78

89
#include <set>
910
#include <string>
@@ -15,6 +16,8 @@ namespace tracing {
1516
using v8::platform::tracing::TraceConfig;
1617
using v8::platform::tracing::TraceObject;
1718

19+
class Agent;
20+
1821
class AsyncTraceWriter {
1922
public:
2023
virtual ~AsyncTraceWriter() {}
@@ -31,42 +34,58 @@ class TracingController : public v8::platform::tracing::TracingController {
3134
}
3235
};
3336

37+
class AgentWriterHandle {
38+
public:
39+
inline AgentWriterHandle() {}
40+
inline ~AgentWriterHandle() { reset(); }
41+
42+
inline AgentWriterHandle(AgentWriterHandle&& other);
43+
inline AgentWriterHandle& operator=(AgentWriterHandle&& other);
44+
inline bool empty() const { return agent_ == nullptr; }
45+
inline void reset();
46+
47+
private:
48+
inline AgentWriterHandle(Agent* agent, int id) : agent_(agent), id_(id) {}
49+
50+
AgentWriterHandle(const AgentWriterHandle& other) = delete;
51+
AgentWriterHandle& operator=(const AgentWriterHandle& other) = delete;
52+
53+
Agent* agent_ = nullptr;
54+
int id_;
55+
56+
friend class Agent;
57+
};
3458

3559
class Agent {
3660
public:
37-
// Resetting the pointer disconnects client
38-
using ClientHandle = std::unique_ptr<std::pair<Agent*, int>,
39-
void (*)(std::pair<Agent*, int>*)>;
40-
41-
static ClientHandle EmptyClientHandle() {
42-
return ClientHandle(nullptr, DisconnectClient);
43-
}
4461
explicit Agent(const std::string& log_file_pattern);
4562
void Stop();
4663

4764
TracingController* GetTracingController() { return tracing_controller_; }
4865

4966
// Destroying the handle disconnects the client
50-
ClientHandle AddClient(const std::set<std::string>& categories,
51-
std::unique_ptr<AsyncTraceWriter> writer);
67+
AgentWriterHandle AddClient(const std::set<std::string>& categories,
68+
std::unique_ptr<AsyncTraceWriter> writer);
5269

5370
// These 3 methods operate on a "default" client, e.g. the file writer
5471
void Enable(const std::string& categories);
5572
void Enable(const std::set<std::string>& categories);
5673
void Disable(const std::set<std::string>& categories);
57-
std::string GetEnabledCategories();
5874

75+
// Returns a comma-separated list of enabled categories.
76+
std::string GetEnabledCategories() const;
77+
78+
// Writes to all writers registered through AddClient().
5979
void AppendTraceEvent(TraceObject* trace_event);
80+
// Flushes all writers registered through AddClient().
6081
void Flush(bool blocking);
6182

62-
TraceConfig* CreateTraceConfig();
83+
TraceConfig* CreateTraceConfig() const;
6384

6485
private:
86+
friend class AgentWriterHandle;
87+
6588
static void ThreadCb(void* arg);
66-
static void DisconnectClient(std::pair<Agent*, int>* id_agent) {
67-
id_agent->first->Disconnect(id_agent->second);
68-
delete id_agent;
69-
}
7089

7190
void Start();
7291
void StopTracing();
@@ -77,14 +96,34 @@ class Agent {
7796
uv_loop_t tracing_loop_;
7897
bool started_ = false;
7998

80-
std::unordered_map<int, std::set<std::string>> categories_;
81-
TracingController* tracing_controller_ = nullptr;
82-
ClientHandle file_writer_;
99+
// Each individual Writer has one id.
83100
int next_writer_id_ = 1;
101+
// These maps store the original arguments to AddClient(), by id.
102+
std::unordered_map<int, std::set<std::string>> categories_;
84103
std::unordered_map<int, std::unique_ptr<AsyncTraceWriter>> writers_;
104+
TracingController* tracing_controller_ = nullptr;
105+
AgentWriterHandle file_writer_;
85106
std::multiset<std::string> file_writer_categories_;
86107
};
87108

109+
void AgentWriterHandle::reset() {
110+
if (agent_ != nullptr)
111+
agent_->Disconnect(id_);
112+
agent_ = nullptr;
113+
}
114+
115+
AgentWriterHandle& AgentWriterHandle::operator=(AgentWriterHandle&& other) {
116+
reset();
117+
agent_ = other.agent_;
118+
id_ = other.id_;
119+
other.agent_ = nullptr;
120+
return *this;
121+
}
122+
123+
AgentWriterHandle::AgentWriterHandle(AgentWriterHandle&& other) {
124+
*this = std::move(other);
125+
}
126+
88127
} // namespace tracing
89128
} // namespace node
90129

0 commit comments

Comments
 (0)