Skip to content

Commit 620e46c

Browse files
committed
src: refactor default trace writer out of agent
The agent code is supposed to manage multiple writers/clients. Adding the default writer into the mix breaks that encapsulation. Instead, manage default options through a separate "virtual" default client handle, and keep the file writer management all to the actual users. PR-URL: nodejs#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 3ac94dc commit 620e46c

10 files changed

Lines changed: 130 additions & 87 deletions

File tree

src/env-inl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,8 @@ inline v8::Isolate* Environment::isolate() const {
325325
return isolate_;
326326
}
327327

328-
inline tracing::Agent* Environment::tracing_agent() const {
329-
return tracing_agent_;
328+
inline tracing::AgentWriterHandle* Environment::tracing_agent_writer() const {
329+
return tracing_agent_writer_;
330330
}
331331

332332
inline Environment* Environment::from_timer_handle(uv_timer_t* handle) {

src/env.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ void InitThreadLocalOnce() {
105105

106106
Environment::Environment(IsolateData* isolate_data,
107107
Local<Context> context,
108-
tracing::Agent* tracing_agent)
108+
tracing::AgentWriterHandle* tracing_agent_writer)
109109
: isolate_(context->GetIsolate()),
110110
isolate_data_(isolate_data),
111-
tracing_agent_(tracing_agent),
111+
tracing_agent_writer_(tracing_agent_writer),
112112
immediate_info_(context->GetIsolate()),
113113
tick_info_(context->GetIsolate()),
114114
timer_base_(uv_now(isolate_data->event_loop())),

src/env.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class performance_state;
5555
}
5656

5757
namespace tracing {
58-
class Agent;
58+
class AgentWriterHandle;
5959
}
6060

6161
namespace worker {
@@ -587,7 +587,7 @@ class Environment {
587587

588588
Environment(IsolateData* isolate_data,
589589
v8::Local<v8::Context> context,
590-
tracing::Agent* tracing_agent);
590+
tracing::AgentWriterHandle* tracing_agent_writer);
591591
~Environment();
592592

593593
void Start(int argc,
@@ -625,7 +625,7 @@ class Environment {
625625
inline bool profiler_idle_notifier_started() const;
626626

627627
inline v8::Isolate* isolate() const;
628-
inline tracing::Agent* tracing_agent() const;
628+
inline tracing::AgentWriterHandle* tracing_agent_writer() const;
629629
inline uv_loop_t* event_loop() const;
630630
inline uint32_t watched_providers() const;
631631

@@ -879,7 +879,7 @@ class Environment {
879879

880880
v8::Isolate* const isolate_;
881881
IsolateData* const isolate_data_;
882-
tracing::Agent* const tracing_agent_;
882+
tracing::AgentWriterHandle* const tracing_agent_writer_;
883883
uv_timer_t timer_handle_;
884884
uv_check_t immediate_check_handle_;
885885
uv_idle_t immediate_idle_handle_;

src/inspector/tracing_agent.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ DispatchResponse TracingAgent::start(
7474
if (categories_set.empty())
7575
return DispatchResponse::Error("At least one category should be enabled");
7676

77-
trace_writer_ = env_->tracing_agent()->AddClient(
77+
trace_writer_ = env_->tracing_agent_writer()->agent()->AddClient(
7878
categories_set,
7979
std::unique_ptr<InspectorTraceWriter>(
80-
new InspectorTraceWriter(frontend_.get())));
80+
new InspectorTraceWriter(frontend_.get())),
81+
tracing::Agent::kIgnoreDefaultCategories);
8182
return DispatchResponse::OK();
8283
}
8384

src/node.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "req_wrap-inl.h"
6262
#include "string_bytes.h"
6363
#include "tracing/agent.h"
64+
#include "tracing/node_trace_writer.h"
6465
#include "util.h"
6566
#include "uv.h"
6667
#if NODE_USE_V8_PLATFORM
@@ -427,17 +428,24 @@ static struct {
427428
#endif // HAVE_INSPECTOR
428429

429430
void StartTracingAgent() {
430-
tracing_file_writer_ = tracing_agent_->AddClient(
431-
trace_enabled_categories,
432-
new tracing::NodeTraceWriter(trace_file_pattern));
431+
if (trace_enabled_categories.empty()) {
432+
tracing_file_writer_ = tracing_agent_->DefaultHandle();
433+
} else {
434+
tracing_file_writer_ = tracing_agent_->AddClient(
435+
ParseCommaSeparatedSet(trace_enabled_categories),
436+
std::unique_ptr<tracing::AsyncTraceWriter>(
437+
new tracing::NodeTraceWriter(trace_file_pattern,
438+
tracing_agent_->loop())),
439+
tracing::Agent::kUseDefaultCategories);
440+
}
433441
}
434442

435443
void StopTracingAgent() {
436444
tracing_file_writer_.reset();
437445
}
438446

439-
tracing::Agent* GetTracingAgent() const {
440-
return tracing_agent_.get();
447+
tracing::AgentWriterHandle* GetTracingAgentWriter() {
448+
return &tracing_file_writer_;
441449
}
442450

443451
NodePlatform* Platform() {
@@ -466,7 +474,9 @@ static struct {
466474
}
467475
void StopTracingAgent() {}
468476

469-
tracing::Agent* GetTracingAgent() const { return nullptr; }
477+
tracing::AgentWriterHandle* GetTracingAgentWriter() {
478+
return nullptr;
479+
}
470480

471481
NodePlatform* Platform() {
472482
return nullptr;
@@ -3590,7 +3600,7 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
35903600
HandleScope handle_scope(isolate);
35913601
Context::Scope context_scope(context);
35923602
auto env = new Environment(isolate_data, context,
3593-
v8_platform.GetTracingAgent());
3603+
v8_platform.GetTracingAgentWriter());
35943604
env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
35953605
return env;
35963606
}
@@ -3649,7 +3659,7 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
36493659
HandleScope handle_scope(isolate);
36503660
Local<Context> context = NewContext(isolate);
36513661
Context::Scope context_scope(context);
3652-
Environment env(isolate_data, context, v8_platform.GetTracingAgent());
3662+
Environment env(isolate_data, context, v8_platform.GetTracingAgentWriter());
36533663
env.Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
36543664

36553665
const char* path = argc > 1 ? argv[1] : nullptr;

src/node_trace_events.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void NodeCategorySet::New(const FunctionCallbackInfo<Value>& args) {
5858
if (!*val) return;
5959
categories.emplace(*val);
6060
}
61-
CHECK_NOT_NULL(env->tracing_agent());
61+
CHECK_NOT_NULL(env->tracing_agent_writer());
6262
new NodeCategorySet(env, args.This(), std::move(categories));
6363
}
6464

@@ -69,7 +69,7 @@ void NodeCategorySet::Enable(const FunctionCallbackInfo<Value>& args) {
6969
CHECK_NOT_NULL(category_set);
7070
const auto& categories = category_set->GetCategories();
7171
if (!category_set->enabled_ && !categories.empty()) {
72-
env->tracing_agent()->Enable(categories);
72+
env->tracing_agent_writer()->Enable(categories);
7373
category_set->enabled_ = true;
7474
}
7575
}
@@ -81,14 +81,15 @@ void NodeCategorySet::Disable(const FunctionCallbackInfo<Value>& args) {
8181
CHECK_NOT_NULL(category_set);
8282
const auto& categories = category_set->GetCategories();
8383
if (category_set->enabled_ && !categories.empty()) {
84-
env->tracing_agent()->Disable(categories);
84+
env->tracing_agent_writer()->Disable(categories);
8585
category_set->enabled_ = false;
8686
}
8787
}
8888

8989
void GetEnabledCategories(const FunctionCallbackInfo<Value>& args) {
9090
Environment* env = Environment::GetCurrent(args);
91-
std::string categories = env->tracing_agent()->GetEnabledCategories();
91+
std::string categories =
92+
env->tracing_agent_writer()->agent()->GetEnabledCategories();
9293
if (!categories.empty()) {
9394
args.GetReturnValue().Set(
9495
String::NewFromUtf8(env->isolate(),

src/tracing/agent.cc

Lines changed: 44 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
#include "tracing/agent.h"
22

3-
#include <sstream>
43
#include <string>
54
#include "tracing/node_trace_buffer.h"
6-
#include "tracing/node_trace_writer.h"
75

86
namespace node {
97
namespace tracing {
108

11-
namespace {
12-
13-
class ScopedSuspendTracing {
9+
class Agent::ScopedSuspendTracing {
1410
public:
15-
ScopedSuspendTracing(TracingController* controller, Agent* agent)
16-
: controller_(controller), agent_(agent) {
17-
controller->StopTracing();
11+
ScopedSuspendTracing(TracingController* controller, Agent* agent,
12+
bool do_suspend = true)
13+
: controller_(controller), agent_(do_suspend ? agent : nullptr) {
14+
if (do_suspend) {
15+
CHECK(agent_->started_);
16+
controller->StopTracing();
17+
}
1818
}
1919

2020
~ScopedSuspendTracing() {
21+
if (agent_ == nullptr) return;
2122
TraceConfig* config = agent_->CreateTraceConfig();
2223
if (config != nullptr) {
2324
controller_->StartTracing(config);
@@ -29,8 +30,10 @@ class ScopedSuspendTracing {
2930
Agent* agent_;
3031
};
3132

33+
namespace {
34+
3235
std::set<std::string> flatten(
33-
const std::unordered_map<int, std::set<std::string>>& map) {
36+
const std::unordered_map<int, std::multiset<std::string>>& map) {
3437
std::set<std::string> result;
3538
for (const auto& id_value : map)
3639
result.insert(id_value.second.begin(), id_value.second.end());
@@ -43,18 +46,17 @@ using v8::platform::tracing::TraceConfig;
4346
using v8::platform::tracing::TraceWriter;
4447
using std::string;
4548

46-
Agent::Agent(const std::string& log_file_pattern)
47-
: log_file_pattern_(log_file_pattern) {
49+
Agent::Agent() {
4850
tracing_controller_ = new TracingController();
4951
tracing_controller_->Initialize(nullptr);
52+
53+
CHECK_EQ(uv_loop_init(&tracing_loop_), 0);
5054
}
5155

5256
void Agent::Start() {
5357
if (started_)
5458
return;
5559

56-
CHECK_EQ(uv_loop_init(&tracing_loop_), 0);
57-
5860
NodeTraceBuffer* trace_buffer_ = new NodeTraceBuffer(
5961
NodeTraceBuffer::kBufferChunks, this, &tracing_loop_);
6062
tracing_controller_->Initialize(trace_buffer_);
@@ -71,18 +73,30 @@ void Agent::Start() {
7173

7274
AgentWriterHandle Agent::AddClient(
7375
const std::set<std::string>& categories,
74-
std::unique_ptr<AsyncTraceWriter> writer) {
76+
std::unique_ptr<AsyncTraceWriter> writer,
77+
enum UseDefaultCategoryMode mode) {
7578
Start();
79+
80+
const std::set<std::string>* use_categories = &categories;
81+
82+
std::set<std::string> categories_with_default;
83+
if (mode == kUseDefaultCategories) {
84+
categories_with_default.insert(categories.begin(), categories.end());
85+
categories_with_default.insert(categories_[kDefaultHandleId].begin(),
86+
categories_[kDefaultHandleId].end());
87+
use_categories = &categories_with_default;
88+
}
89+
7690
ScopedSuspendTracing suspend(tracing_controller_, this);
7791
int id = next_writer_id_++;
7892
writers_[id] = std::move(writer);
79-
categories_[id] = categories;
93+
categories_[id] = { use_categories->begin(), use_categories->end() };
8094

8195
return AgentWriterHandle(this, id);
8296
}
8397

84-
void Agent::Stop() {
85-
file_writer_.reset();
98+
AgentWriterHandle Agent::DefaultHandle() {
99+
return AgentWriterHandle(this, kDefaultHandleId);
86100
}
87101

88102
void Agent::StopTracing() {
@@ -99,54 +113,30 @@ void Agent::StopTracing() {
99113
}
100114

101115
void Agent::Disconnect(int client) {
116+
if (client == kDefaultHandleId) return;
102117
ScopedSuspendTracing suspend(tracing_controller_, this);
103118
writers_.erase(client);
104119
categories_.erase(client);
105120
}
106121

107-
void Agent::Enable(const std::string& categories) {
122+
void Agent::Enable(int id, const std::set<std::string>& categories) {
108123
if (categories.empty())
109124
return;
110-
std::set<std::string> categories_set;
111-
std::istringstream category_list(categories);
112-
while (category_list.good()) {
113-
std::string category;
114-
getline(category_list, category, ',');
115-
categories_set.emplace(std::move(category));
116-
}
117-
Enable(categories_set);
118-
}
119125

120-
void Agent::Enable(const std::set<std::string>& categories) {
121-
if (categories.empty())
122-
return;
123-
124-
file_writer_categories_.insert(categories.begin(), categories.end());
125-
std::set<std::string> full_list(file_writer_categories_.begin(),
126-
file_writer_categories_.end());
127-
if (file_writer_.empty()) {
128-
// Ensure background thread is running
129-
Start();
130-
std::unique_ptr<NodeTraceWriter> writer(
131-
new NodeTraceWriter(log_file_pattern_, &tracing_loop_));
132-
file_writer_ = AddClient(full_list, std::move(writer));
133-
} else {
134-
ScopedSuspendTracing suspend(tracing_controller_, this);
135-
categories_[file_writer_.id_] = full_list;
136-
}
126+
ScopedSuspendTracing suspend(tracing_controller_, this,
127+
id != kDefaultHandleId);
128+
categories_[id].insert(categories.begin(), categories.end());
137129
}
138130

139-
void Agent::Disable(const std::set<std::string>& categories) {
131+
void Agent::Disable(int id, const std::set<std::string>& categories) {
132+
ScopedSuspendTracing suspend(tracing_controller_, this,
133+
id != kDefaultHandleId);
134+
std::multiset<std::string>& writer_categories = categories_[id];
140135
for (const std::string& category : categories) {
141-
auto it = file_writer_categories_.find(category);
142-
if (it != file_writer_categories_.end())
143-
file_writer_categories_.erase(it);
136+
auto it = writer_categories.find(category);
137+
if (it != writer_categories.end())
138+
writer_categories.erase(it);
144139
}
145-
if (file_writer_.empty())
146-
return;
147-
ScopedSuspendTracing suspend(tracing_controller_, this);
148-
categories_[file_writer_.id_] = { file_writer_categories_.begin(),
149-
file_writer_categories_.end() };
150140
}
151141

152142
TraceConfig* Agent::CreateTraceConfig() const {
@@ -178,5 +168,6 @@ void Agent::Flush(bool blocking) {
178168
for (const auto& id_writer : writers_)
179169
id_writer.second->Flush(blocking);
180170
}
171+
181172
} // namespace tracing
182173
} // namespace node

0 commit comments

Comments
 (0)