diff --git a/node.gyp b/node.gyp index 546b24cfc2a694..a4575e3ee2f8b4 100644 --- a/node.gyp +++ b/node.gyp @@ -200,6 +200,7 @@ 'src/timers.cc', 'src/timer_wrap.cc', 'src/tracing/agent.cc', + 'src/tracing/agent_legacy.cc', 'src/tracing/node_trace_buffer.cc', 'src/tracing/node_trace_writer.cc', 'src/tracing/trace_event.cc', @@ -338,6 +339,7 @@ 'src/tcp_wrap.h', 'src/timers.h', 'src/tracing/agent.h', + 'src/tracing/agent_legacy.h', 'src/tracing/node_trace_buffer.h', 'src/tracing/node_trace_writer.h', 'src/tracing/trace_event.h', diff --git a/src/env.cc b/src/env.cc index 08f5f8807ca054..d6a859e7a35452 100644 --- a/src/env.cc +++ b/src/env.cc @@ -71,7 +71,6 @@ using v8::SnapshotCreator; using v8::StackTrace; using v8::String; using v8::Symbol; -using v8::TracingController; using v8::TryCatch; using v8::Uint32; using v8::Undefined; @@ -894,10 +893,9 @@ Environment::Environment(IsolateData* isolate_data, inspector_agent_ = std::make_unique(this); #endif - if (tracing::AgentWriterHandle* writer = GetTracingAgentWriter()) { + if (tracing::Agent* agent = tracing::Agent::GetInstance()) { trace_state_observer_ = std::make_unique(this); - if (TracingController* tracing_controller = writer->GetTracingController()) - tracing_controller->AddTraceStateObserver(trace_state_observer_.get()); + agent->AddTraceStateObserver(trace_state_observer_.get()); } destroy_async_id_list_.reserve(512); @@ -1064,10 +1062,8 @@ Environment::~Environment() { principal_realm_.reset(); if (trace_state_observer_) { - tracing::AgentWriterHandle* writer = GetTracingAgentWriter(); - CHECK_NOT_NULL(writer); - if (TracingController* tracing_controller = writer->GetTracingController()) - tracing_controller->RemoveTraceStateObserver(trace_state_observer_.get()); + if (tracing::Agent* agent = tracing::Agent::GetInstance()) + agent->RemoveTraceStateObserver(trace_state_observer_.get()); } TRACE_EVENT_NESTABLE_ASYNC_END0( diff --git a/src/inspector/tracing_agent.cc b/src/inspector/tracing_agent.cc index 40c8aea35c931c..cf1c1a52af4dcc 100644 --- a/src/inspector/tracing_agent.cc +++ b/src/inspector/tracing_agent.cc @@ -3,6 +3,7 @@ #include "main_thread_interface.h" #include "node_internals.h" #include "node_v8_platform-inl.h" +#include "tracing/agent_legacy.h" #include "v8.h" #include @@ -162,13 +163,14 @@ DispatchResponse TracingAgent::start( return DispatchResponse::InvalidRequest( "At least one category should be enabled"); - tracing::AgentWriterHandle* writer = GetTracingAgentWriter(); - if (writer != nullptr) { + auto* agent = + static_cast(tracing::Agent::GetInstance()); + if (agent != nullptr) { trace_writer_ = - writer->agent()->AddClient(categories_set, - std::make_unique( - frontend_object_id_, main_thread_), - tracing::Agent::kIgnoreDefaultCategories); + agent->AddClient(categories_set, + std::make_unique( + frontend_object_id_, main_thread_), + tracing::LegacyTracingAgent::kIgnoreDefaultCategories); } return DispatchResponse::Success(); } diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index ef659f1c39f7ee..bb0be77cce78e6 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -73,7 +73,7 @@ void NodeCategorySet::New(const FunctionCallbackInfo& args) { if (!*val) return; categories.emplace(*val); } - CHECK_NOT_NULL(GetTracingAgentWriter()); + CHECK_NOT_NULL(tracing::Agent::GetInstance()); new NodeCategorySet(env, args.This(), std::move(categories)); } @@ -85,8 +85,10 @@ void NodeCategorySet::Enable(const FunctionCallbackInfo& args) { if (!category_set->enabled_ && !categories.empty()) { // Starts the Tracing Agent if it wasn't started already (e.g. through // a command line flag.) - StartTracingAgent(); - GetTracingAgentWriter()->Enable(categories); + auto* agent = tracing::Agent::GetInstance(); + agent->StartTracing(per_process::cli_options->trace_event_categories); + tracing::AgentWriterHandle* writer = agent->GetDefaultWriterHandle(); + writer->Enable(categories); category_set->enabled_ = true; } } @@ -97,7 +99,9 @@ void NodeCategorySet::Disable(const FunctionCallbackInfo& args) { CHECK_NOT_NULL(category_set); const auto& categories = category_set->GetCategories(); if (category_set->enabled_ && !categories.empty()) { - GetTracingAgentWriter()->Disable(categories); + auto* agent = tracing::Agent::GetInstance(); + tracing::AgentWriterHandle* writer = agent->GetDefaultWriterHandle(); + writer->Disable(categories); category_set->enabled_ = false; } } @@ -105,7 +109,7 @@ void NodeCategorySet::Disable(const FunctionCallbackInfo& args) { void GetEnabledCategories(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); std::string categories = - GetTracingAgentWriter()->agent()->GetEnabledCategories(); + tracing::Agent::GetInstance()->GetEnabledCategories(); Local ret; if (!categories.empty() && ToV8Value(env->context(), categories, env->isolate()).ToLocal(&ret)) { diff --git a/src/node_v8_platform-inl.h b/src/node_v8_platform-inl.h index 57a725a988f445..9e05928e2a5755 100644 --- a/src/node_v8_platform-inl.h +++ b/src/node_v8_platform-inl.h @@ -4,63 +4,15 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include -#include #include "env-inl.h" #include "node.h" -#include "node_metadata.h" -#include "node_platform.h" #include "node_options.h" -#include "tracing/node_trace_writer.h" -#include "tracing/trace_event.h" -#include "tracing/traced_value.h" -#include "util.h" +#include "node_platform.h" +#include "tracing/agent.h" namespace node { -// Ensures that __metadata trace events are only emitted -// when tracing is enabled. -class NodeTraceStateObserver - : public v8::TracingController::TraceStateObserver { - public: - inline void OnTraceEnabled() override { - std::string title = GetProcessTitle(""); - if (!title.empty()) { - // Only emit the metadata event if the title can be retrieved - // successfully. Ignore it otherwise. - TRACE_EVENT_METADATA1( - "__metadata", "process_name", "name", TRACE_STR_COPY(title.c_str())); - } - TRACE_EVENT_METADATA1("__metadata", - "version", - "node", - per_process::metadata.versions.node.c_str()); - TRACE_EVENT_METADATA1( - "__metadata", "thread_name", "name", "JavaScriptMainThread"); - - tracing::ProcessMeta trace_process; - TRACE_EVENT_METADATA1("__metadata", - "node", - "process", - tracing::CastTracedValue(trace_process)); - // This only runs the first time tracing is enabled - controller_->RemoveTraceStateObserver(this); - } - - inline void OnTraceDisabled() override { - // Do nothing here. This should never be called because the - // observer removes itself when OnTraceEnabled() is called. - UNREACHABLE(); - } - - explicit NodeTraceStateObserver(v8::TracingController* controller) - : controller_(controller) {} - ~NodeTraceStateObserver() override = default; - - private: - v8::TracingController* controller_; -}; - struct V8Platform { bool initialized_ = false; @@ -68,20 +20,14 @@ struct V8Platform { inline void Initialize(int thread_pool_size) { CHECK(!initialized_); initialized_ = true; - tracing_agent_ = std::make_unique(); - node::tracing::TraceEventHelper::SetAgent(tracing_agent_.get()); - node::tracing::TracingController* controller = - tracing_agent_->GetTracingController(); - trace_state_observer_ = - std::make_unique(controller); - controller->AddTraceStateObserver(trace_state_observer_.get()); - tracing_file_writer_ = tracing_agent_->DefaultHandle(); + tracing_agent_ = tracing::Agent::CreateDefault(); // Only start the tracing agent if we enabled any tracing categories. if (!per_process::cli_options->trace_event_categories.empty()) { StartTracingAgent(); } // Tracing must be initialized before platform threads are created. - platform_ = new NodePlatform(thread_pool_size, controller); + platform_ = new NodePlatform(thread_pool_size, + tracing_agent_->GetTracingController()); v8::V8::InitializePlatform(platform_); } // Make sure V8Platform don not call into Libuv threadpool, @@ -90,7 +36,6 @@ struct V8Platform { if (!initialized_) return; initialized_ = false; - node::tracing::TraceEventHelper::SetAgent(nullptr); StopTracingAgent(); platform_->Shutdown(); delete platform_; @@ -98,8 +43,6 @@ struct V8Platform { // Destroy tracing after the platform (and platform threads) have been // stopped. tracing_agent_.reset(nullptr); - // The observer remove itself in OnTraceEnabled - trace_state_observer_.reset(nullptr); } inline void DrainVMTasks(v8::Isolate* isolate) { @@ -107,41 +50,19 @@ struct V8Platform { } inline void StartTracingAgent() { - constexpr auto convert_to_set = - [](auto& categories) -> std::set { - std::set out; - for (const auto& s : categories) { - out.emplace(std::string(s.data(), s.size())); - } - return out; - }; - // Attach a new NodeTraceWriter only if this function hasn't been called - // before. - if (tracing_file_writer_.IsDefaultHandle()) { - using std::operator""sv; - auto categories = std::views::split( - per_process::cli_options->trace_event_categories, ","sv); - - tracing_file_writer_ = tracing_agent_->AddClient( - convert_to_set(categories), - std::unique_ptr( - new tracing::NodeTraceWriter( - per_process::cli_options->trace_event_file_pattern)), - tracing::Agent::kUseDefaultCategories); - } + if (!initialized_) return; + tracing_agent_->StartTracing( + per_process::cli_options->trace_event_categories); } - inline void StopTracingAgent() { tracing_file_writer_.reset(); } - - inline tracing::AgentWriterHandle* GetTracingAgentWriter() { - return &tracing_file_writer_; + inline void StopTracingAgent() { + if (!initialized_) return; + tracing_agent_->StopTracing(); } inline NodePlatform* Platform() { return platform_; } - std::unique_ptr trace_state_observer_; - std::unique_ptr tracing_agent_; - tracing::AgentWriterHandle tracing_file_writer_; + std::unique_ptr tracing_agent_; NodePlatform* platform_; #else // !NODE_USE_V8_PLATFORM inline void Initialize(int thread_pool_size) {} @@ -156,8 +77,6 @@ struct V8Platform { } inline void StopTracingAgent() {} - inline tracing::AgentWriterHandle* GetTracingAgentWriter() { return nullptr; } - inline NodePlatform* Platform() { return nullptr; } #endif // !NODE_USE_V8_PLATFORM }; @@ -166,14 +85,6 @@ namespace per_process { extern struct V8Platform v8_platform; } -inline void StartTracingAgent() { - return per_process::v8_platform.StartTracingAgent(); -} - -inline tracing::AgentWriterHandle* GetTracingAgentWriter() { - return per_process::v8_platform.GetTracingAgentWriter(); -} - inline void DisposePlatform() { per_process::v8_platform.Dispose(); } diff --git a/src/tracing/agent.cc b/src/tracing/agent.cc index eddcf6c3bf91b7..69b956e9bc9d68 100644 --- a/src/tracing/agent.cc +++ b/src/tracing/agent.cc @@ -1,255 +1,33 @@ #include "tracing/agent.h" - -#include -#include "trace_event.h" -#include "tracing/node_trace_buffer.h" -#include "debug_utils-inl.h" -#include "env-inl.h" +#include "tracing/agent_legacy.h" +#include "tracing/trace_event.h" namespace node { namespace tracing { -class Agent::ScopedSuspendTracing { - public: - ScopedSuspendTracing(TracingController* controller, Agent* agent, - bool do_suspend = true) - : controller_(controller), agent_(do_suspend ? agent : nullptr) { - if (do_suspend) { - CHECK(agent_->started_); - controller->StopTracing(); - } - } - - ~ScopedSuspendTracing() { - if (agent_ == nullptr) return; - TraceConfig* config = agent_->CreateTraceConfig(); - if (config != nullptr) { - controller_->StartTracing(config); - } - } - - private: - TracingController* controller_; - Agent* agent_; -}; - namespace { - -std::set flatten( - const std::unordered_map>& map) { - std::set result; - for (const auto& id_value : map) - result.insert(id_value.second.begin(), id_value.second.end()); - return result; -} - +Agent* g_agent = nullptr; } // namespace -using v8::platform::tracing::TraceConfig; -using v8::platform::tracing::TraceWriter; -using std::string; - -Agent::Agent() : tracing_controller_(new TracingController()) { - tracing_controller_->Initialize(nullptr); - - CHECK_EQ(uv_loop_init(&tracing_loop_), 0); - CHECK_EQ(uv_async_init(&tracing_loop_, - &initialize_writer_async_, - [](uv_async_t* async) { - Agent* agent = ContainerOf(&Agent::initialize_writer_async_, async); - agent->InitializeWritersOnThread(); - }), 0); - uv_unref(reinterpret_cast(&initialize_writer_async_)); +Agent* Agent::GetInstance() { + return g_agent; } -void Agent::InitializeWritersOnThread() { - Mutex::ScopedLock lock(initialize_writer_mutex_); - while (!to_be_initialized_.empty()) { - AsyncTraceWriter* head = *to_be_initialized_.begin(); - head->InitializeOnThread(&tracing_loop_); - to_be_initialized_.erase(head); - } - initialize_writer_condvar_.Broadcast(lock); +void Agent::Deleter::operator()(Agent* agent) { + CHECK_EQ(agent, g_agent); + g_agent = nullptr; + TraceEventHelper::SetTracingController(nullptr); + delete agent; } -Agent::~Agent() { - categories_.clear(); - writers_.clear(); - - StopTracing(); - - uv_close(reinterpret_cast(&initialize_writer_async_), nullptr); - uv_run(&tracing_loop_, UV_RUN_ONCE); - CheckedUvLoopClose(&tracing_loop_); -} - -void Agent::Start() { - if (started_) - return; - - NodeTraceBuffer* trace_buffer_ = new NodeTraceBuffer( - NodeTraceBuffer::kBufferChunks, this, &tracing_loop_); - tracing_controller_->Initialize(trace_buffer_); - - // This thread should be created *after* async handles are created - // (within NodeTraceWriter and NodeTraceBuffer constructors). - // Otherwise the thread could shut down prematurely. - CHECK_EQ(0, - uv_thread_create( - &thread_, - [](void* arg) { - uv_thread_setname("TraceEventWorker"); - Agent* agent = static_cast(arg); - uv_run(&agent->tracing_loop_, UV_RUN_DEFAULT); - }, - this)); - started_ = true; -} - -AgentWriterHandle Agent::AddClient( - const std::set& categories, - std::unique_ptr writer, - enum UseDefaultCategoryMode mode) { - Start(); - - const std::set* use_categories = &categories; - - std::set categories_with_default; - if (mode == kUseDefaultCategories) { - categories_with_default.insert(categories.begin(), categories.end()); - categories_with_default.insert(categories_[kDefaultHandleId].begin(), - categories_[kDefaultHandleId].end()); - use_categories = &categories_with_default; - } - - ScopedSuspendTracing suspend(tracing_controller_.get(), this); - int id = next_writer_id_++; - AsyncTraceWriter* raw = writer.get(); - writers_[id] = std::move(writer); - categories_[id] = { use_categories->begin(), use_categories->end() }; - - { - Mutex::ScopedLock lock(initialize_writer_mutex_); - to_be_initialized_.insert(raw); - uv_async_send(&initialize_writer_async_); - while (to_be_initialized_.count(raw) > 0) - initialize_writer_condvar_.Wait(lock); - } - - return AgentWriterHandle(this, id); -} +std::unique_ptr Agent::CreateDefault() { + CHECK_NULL(g_agent); -AgentWriterHandle Agent::DefaultHandle() { - return AgentWriterHandle(this, kDefaultHandleId); -} - -void Agent::StopTracing() { - if (!started_) - return; - // Perform final Flush on TraceBuffer. We don't want the tracing controller - // to flush the buffer again on destruction of the V8::Platform. - tracing_controller_->StopTracing(); - tracing_controller_->Initialize(nullptr); - started_ = false; - - // Thread should finish when the tracing loop is stopped. - uv_thread_join(&thread_); -} - -void Agent::Disconnect(int client) { - if (client == kDefaultHandleId) return; - { - Mutex::ScopedLock lock(initialize_writer_mutex_); - to_be_initialized_.erase(writers_[client].get()); - } - ScopedSuspendTracing suspend(tracing_controller_.get(), this); - writers_.erase(client); - categories_.erase(client); -} - -void Agent::Enable(int id, const std::set& categories) { - if (categories.empty()) - return; - - ScopedSuspendTracing suspend(tracing_controller_.get(), this, - id != kDefaultHandleId); - categories_[id].insert(categories.begin(), categories.end()); -} - -void Agent::Disable(int id, const std::set& categories) { - ScopedSuspendTracing suspend(tracing_controller_.get(), this, - id != kDefaultHandleId); - std::multiset& writer_categories = categories_[id]; - for (const std::string& category : categories) { - auto it = writer_categories.find(category); - if (it != writer_categories.end()) - writer_categories.erase(it); - } -} - -TraceConfig* Agent::CreateTraceConfig() const { - if (categories_.empty()) - return nullptr; - TraceConfig* trace_config = new TraceConfig(); - for (const auto& category : flatten(categories_)) { - trace_config->AddIncludedCategory(category.c_str()); - } - return trace_config; -} - -std::string Agent::GetEnabledCategories() const { - std::string categories; - for (const std::string& category : flatten(categories_)) { - if (!categories.empty()) - categories += ','; - categories += category; - } - return categories; -} - -void Agent::AppendTraceEvent(TraceObject* trace_event) { - for (const auto& id_writer : writers_) - id_writer.second->AppendTraceEvent(trace_event); -} - -void Agent::AddMetadataEvent(std::unique_ptr event) { - Mutex::ScopedLock lock(metadata_events_mutex_); - metadata_events_.push_back(std::move(event)); -} - -void Agent::Flush(bool blocking) { - { - Mutex::ScopedLock lock(metadata_events_mutex_); - for (const auto& event : metadata_events_) - AppendTraceEvent(event.get()); - } - - for (const auto& id_writer : writers_) - id_writer.second->Flush(blocking); -} + auto agent = new LegacyTracingAgent(); -void TracingController::AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* name, - int num_args, - const char** arg_names, - const unsigned char* arg_types, - const uint64_t* arg_values, - std::unique_ptr* convertable_values, - unsigned int flags) { - std::unique_ptr trace_event(new TraceObject); - trace_event->Initialize( - TRACE_EVENT_PHASE_METADATA, category_group_enabled, name, - node::tracing::kGlobalScope, // scope - node::tracing::kNoId, // id - node::tracing::kNoId, // bind_id - num_args, arg_names, arg_types, arg_values, convertable_values, - TRACE_EVENT_FLAG_NONE, - CurrentTimestampMicroseconds(), - CurrentCpuTimestampMicroseconds()); - Agent* node_agent = node::tracing::TraceEventHelper::GetAgent(); - if (node_agent != nullptr) - node_agent->AddMetadataEvent(std::move(trace_event)); + g_agent = agent; + TraceEventHelper::SetTracingController(agent->GetTracingController()); + return std::unique_ptr(agent); } } // namespace tracing diff --git a/src/tracing/agent.h b/src/tracing/agent.h index b542a849fe8da7..78203154c099a5 100644 --- a/src/tracing/agent.h +++ b/src/tracing/agent.h @@ -1,53 +1,65 @@ #ifndef SRC_TRACING_AGENT_H_ #define SRC_TRACING_AGENT_H_ -#include "libplatform/v8-tracing.h" -#include "uv.h" -#include "util.h" -#include "node_mutex.h" - -#include +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +// This defines a compatible agent interface for both the legacy V8 +// tracing and the Perfetto tracing. The interface is designed to be +// used by the rest of the Node.js codebase that only generates +// trace events with the trace macros, or interacts with the tracing +// system. +// +// To generate trace events by API, or consume the tracing data, the +// caller should directly refer to the derived trace agent interfaces. +// +// This file should not include either `libplatform/v8-tracing.h` or +// `perfetto.h`. + +#include "v8-platform.h" + +#include #include #include -#include - -namespace v8 { -class ConvertableToTraceFormat; -class TracingController; -} // namespace v8 namespace node { namespace tracing { -using v8::platform::tracing::TraceConfig; -using v8::platform::tracing::TraceObject; - class Agent; +class AgentWriterHandle; -class AsyncTraceWriter { +class Agent { public: - virtual ~AsyncTraceWriter() = default; - virtual void AppendTraceEvent(TraceObject* trace_event) = 0; - virtual void Flush(bool blocking) = 0; - virtual void InitializeOnThread(uv_loop_t* loop) {} -}; + virtual ~Agent() = default; -class TracingController : public v8::platform::tracing::TracingController { - public: - TracingController() : v8::platform::tracing::TracingController() {} - - int64_t CurrentTimestampMicroseconds() override { - return uv_hrtime() / 1000; - } - void AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* name, - int num_args, - const char** arg_names, - const unsigned char* arg_types, - const uint64_t* arg_values, - std::unique_ptr* convertable_values, - unsigned int flags); + virtual v8::TracingController* GetTracingController() = 0; + + // Returns a comma-separated list of enabled categories. + virtual std::string GetEnabledCategories() const = 0; + + // Called by V8Platform to start/stop file-based tracing. + virtual void StartTracing(const std::string& categories) = 0; + virtual void StopTracing() = 0; + + virtual AgentWriterHandle* GetDefaultWriterHandle() = 0; + + virtual void AddTraceStateObserver( + v8::TracingController::TraceStateObserver* observer) = 0; + virtual void RemoveTraceStateObserver( + v8::TracingController::TraceStateObserver* observer) = 0; + + struct Deleter { + void operator()(Agent* agent); + }; + static std::unique_ptr CreateDefault(); + static Agent* GetInstance(); + + private: + virtual void Disconnect(int client) = 0; + + virtual void Enable(int id, const std::set& categories) = 0; + virtual void Disable(int id, const std::set& categories) = 0; + + friend class AgentWriterHandle; }; class AgentWriterHandle { @@ -63,12 +75,8 @@ class AgentWriterHandle { inline void Enable(const std::set& categories); inline void Disable(const std::set& categories); - inline bool IsDefaultHandle(); - inline Agent* agent() { return agent_; } - inline v8::TracingController* GetTracingController(); - AgentWriterHandle(const AgentWriterHandle& other) = delete; AgentWriterHandle& operator=(const AgentWriterHandle& other) = delete; @@ -79,80 +87,7 @@ class AgentWriterHandle { int id_ = 0; friend class Agent; -}; - -class Agent { - public: - Agent(); - ~Agent(); - - TracingController* GetTracingController() { - TracingController* controller = tracing_controller_.get(); - CHECK_NOT_NULL(controller); - return controller; - } - - enum UseDefaultCategoryMode { - kUseDefaultCategories, - kIgnoreDefaultCategories - }; - - // Destroying the handle disconnects the client - AgentWriterHandle AddClient(const std::set& categories, - std::unique_ptr writer, - enum UseDefaultCategoryMode mode); - // A handle that is only used for managing the default categories - // (which can then implicitly be used through using `USE_DEFAULT_CATEGORIES` - // when adding a client later). - AgentWriterHandle DefaultHandle(); - - // Returns a comma-separated list of enabled categories. - std::string GetEnabledCategories() const; - - // Writes to all writers registered through AddClient(). - void AppendTraceEvent(TraceObject* trace_event); - - void AddMetadataEvent(std::unique_ptr event); - // Flushes all writers registered through AddClient(). - void Flush(bool blocking); - - TraceConfig* CreateTraceConfig() const; - - private: - friend class AgentWriterHandle; - - void InitializeWritersOnThread(); - - void Start(); - void StopTracing(); - void Disconnect(int client); - - void Enable(int id, const std::set& categories); - void Disable(int id, const std::set& categories); - - uv_thread_t thread_; - uv_loop_t tracing_loop_; - - bool started_ = false; - class ScopedSuspendTracing; - - // Each individual Writer has one id. - int next_writer_id_ = 1; - enum { kDefaultHandleId = -1 }; - // These maps store the original arguments to AddClient(), by id. - std::unordered_map> categories_; - std::unordered_map> writers_; - std::unique_ptr tracing_controller_; - - // Variables related to initializing per-event-loop properties of individual - // writers, such as libuv handles. - Mutex initialize_writer_mutex_; - ConditionVariable initialize_writer_condvar_; - uv_async_t initialize_writer_async_; - std::set to_be_initialized_; - - Mutex metadata_events_mutex_; - std::list> metadata_events_; + friend class LegacyTracingAgent; }; void AgentWriterHandle::reset() { @@ -181,15 +116,9 @@ void AgentWriterHandle::Disable(const std::set& categories) { if (agent_ != nullptr) agent_->Disable(id_, categories); } -bool AgentWriterHandle::IsDefaultHandle() { - return agent_ != nullptr && id_ == Agent::kDefaultHandleId; -} - -inline v8::TracingController* AgentWriterHandle::GetTracingController() { - return agent_ != nullptr ? agent_->GetTracingController() : nullptr; -} - } // namespace tracing } // namespace node +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + #endif // SRC_TRACING_AGENT_H_ diff --git a/src/tracing/agent_legacy.cc b/src/tracing/agent_legacy.cc new file mode 100644 index 00000000000000..c6c4a1e1ada42f --- /dev/null +++ b/src/tracing/agent_legacy.cc @@ -0,0 +1,320 @@ +#include "tracing/agent_legacy.h" + +#include +#include +#include +#include "debug_utils-inl.h" +#include "env-inl.h" +#include "node_metadata.h" +#include "node_options.h" +#include "trace_event.h" +#include "tracing/node_trace_buffer.h" +#include "tracing/node_trace_writer.h" +#include "tracing/traced_value.h" + +namespace node { +namespace tracing { + +class LegacyTracingAgent::ScopedSuspendTracing { + public: + ScopedSuspendTracing(TracingController* controller, + LegacyTracingAgent* agent, + bool do_suspend = true) + : controller_(controller), agent_(do_suspend ? agent : nullptr) { + if (do_suspend) { + CHECK(agent_->started_); + controller->StopTracing(); + } + } + + ~ScopedSuspendTracing() { + if (agent_ == nullptr) return; + TraceConfig* config = agent_->CreateTraceConfig(); + if (config != nullptr) { + controller_->StartTracing(config); + } + } + + private: + TracingController* controller_; + LegacyTracingAgent* agent_; +}; + +namespace { + +std::set flatten( + const std::unordered_map>& map) { + std::set result; + for (const auto& id_value : map) + result.insert(id_value.second.begin(), id_value.second.end()); + return result; +} + +} // namespace + +using std::string; +using v8::platform::tracing::TraceConfig; +using v8::platform::tracing::TraceWriter; + +void NodeTraceStateObserver::OnTraceEnabled() { + std::string title = GetProcessTitle(""); + if (!title.empty()) { + TRACE_EVENT_METADATA1( + "__metadata", "process_name", "name", TRACE_STR_COPY(title.c_str())); + } + TRACE_EVENT_METADATA1("__metadata", + "version", + "node", + per_process::metadata.versions.node.c_str()); + TRACE_EVENT_METADATA1( + "__metadata", "thread_name", "name", "JavaScriptMainThread"); + + ProcessMeta trace_process; + TRACE_EVENT_METADATA1( + "__metadata", "node", "process", CastTracedValue(trace_process)); + // This only runs the first time tracing is enabled + controller_->RemoveTraceStateObserver(this); +} + +LegacyTracingAgent::LegacyTracingAgent() + : tracing_controller_(new TracingController()) { + tracing_controller_->Initialize(nullptr); + + trace_state_observer_ = + std::make_unique(tracing_controller_.get()); + tracing_controller_->AddTraceStateObserver(trace_state_observer_.get()); + tracing_file_writer_ = AgentWriterHandle(this, kDefaultHandleId); + + CHECK_EQ(uv_loop_init(&tracing_loop_), 0); + CHECK_EQ(uv_async_init(&tracing_loop_, + &initialize_writer_async_, + [](uv_async_t* async) { + LegacyTracingAgent* agent = ContainerOf( + &LegacyTracingAgent::initialize_writer_async_, + async); + agent->InitializeWritersOnThread(); + }), + 0); + uv_unref(reinterpret_cast(&initialize_writer_async_)); +} + +void LegacyTracingAgent::InitializeWritersOnThread() { + Mutex::ScopedLock lock(initialize_writer_mutex_); + while (!to_be_initialized_.empty()) { + AsyncTraceWriter* head = *to_be_initialized_.begin(); + head->InitializeOnThread(&tracing_loop_); + to_be_initialized_.erase(head); + } + initialize_writer_condvar_.Broadcast(lock); +} + +LegacyTracingAgent::~LegacyTracingAgent() { + StopTracing(); + + categories_.clear(); + writers_.clear(); + + Stop(); + + uv_close(reinterpret_cast(&initialize_writer_async_), nullptr); + uv_run(&tracing_loop_, UV_RUN_ONCE); + CheckedUvLoopClose(&tracing_loop_); +} + +void LegacyTracingAgent::Start() { + if (started_) return; + + NodeTraceBuffer* trace_buffer_ = + new NodeTraceBuffer(NodeTraceBuffer::kBufferChunks, this, &tracing_loop_); + tracing_controller_->Initialize(trace_buffer_); + + // This thread should be created *after* async handles are created + // (within NodeTraceWriter and NodeTraceBuffer constructors). + // Otherwise the thread could shut down prematurely. + CHECK_EQ(0, + uv_thread_create( + &thread_, + [](void* arg) { + uv_thread_setname("TraceEventWorker"); + LegacyTracingAgent* agent = + static_cast(arg); + uv_run(&agent->tracing_loop_, UV_RUN_DEFAULT); + }, + this)); + started_ = true; +} + +AgentWriterHandle LegacyTracingAgent::AddClient( + const std::set& categories, + std::unique_ptr writer, + enum UseDefaultCategoryMode mode) { + Start(); + + const std::set* use_categories = &categories; + + std::set categories_with_default; + if (mode == kUseDefaultCategories) { + categories_with_default.insert(categories.begin(), categories.end()); + categories_with_default.insert(categories_[kDefaultHandleId].begin(), + categories_[kDefaultHandleId].end()); + use_categories = &categories_with_default; + } + + ScopedSuspendTracing suspend(tracing_controller_.get(), this); + int id = next_writer_id_++; + AsyncTraceWriter* raw = writer.get(); + writers_[id] = std::move(writer); + categories_[id] = {use_categories->begin(), use_categories->end()}; + + { + Mutex::ScopedLock lock(initialize_writer_mutex_); + to_be_initialized_.insert(raw); + uv_async_send(&initialize_writer_async_); + while (to_be_initialized_.count(raw) > 0) + initialize_writer_condvar_.Wait(lock); + } + + return AgentWriterHandle(this, id); +} + +void LegacyTracingAgent::Stop() { + if (!started_) return; + // Perform final Flush on TraceBuffer. We don't want the tracing controller + // to flush the buffer again on destruction of the V8::Platform. + tracing_controller_->StopTracing(); + tracing_controller_->Initialize(nullptr); + started_ = false; + + // Thread should finish when the tracing loop is stopped. + uv_thread_join(&thread_); +} + +void LegacyTracingAgent::Disconnect(int client) { + if (client == kDefaultHandleId) return; + { + Mutex::ScopedLock lock(initialize_writer_mutex_); + to_be_initialized_.erase(writers_[client].get()); + } + ScopedSuspendTracing suspend(tracing_controller_.get(), this); + writers_.erase(client); + categories_.erase(client); +} + +void LegacyTracingAgent::Enable(int id, + const std::set& categories) { + if (categories.empty()) return; + + ScopedSuspendTracing suspend( + tracing_controller_.get(), this, id != kDefaultHandleId); + categories_[id].insert(categories.begin(), categories.end()); +} + +void LegacyTracingAgent::Disable(int id, + const std::set& categories) { + ScopedSuspendTracing suspend( + tracing_controller_.get(), this, id != kDefaultHandleId); + std::multiset& writer_categories = categories_[id]; + for (const std::string& category : categories) { + auto it = writer_categories.find(category); + if (it != writer_categories.end()) writer_categories.erase(it); + } +} + +TraceConfig* LegacyTracingAgent::CreateTraceConfig() const { + if (categories_.empty()) return nullptr; + TraceConfig* trace_config = new TraceConfig(); + for (const auto& category : flatten(categories_)) { + trace_config->AddIncludedCategory(category.c_str()); + } + return trace_config; +} + +std::string LegacyTracingAgent::GetEnabledCategories() const { + std::string categories; + for (const std::string& category : flatten(categories_)) { + if (!categories.empty()) categories += ','; + categories += category; + } + return categories; +} + +void LegacyTracingAgent::AppendTraceEvent(TraceObject* trace_event) { + for (const auto& id_writer : writers_) + id_writer.second->AppendTraceEvent(trace_event); +} + +void LegacyTracingAgent::AddMetadataEvent(std::unique_ptr event) { + Mutex::ScopedLock lock(metadata_events_mutex_); + metadata_events_.push_back(std::move(event)); +} + +void LegacyTracingAgent::Flush(bool blocking) { + { + Mutex::ScopedLock lock(metadata_events_mutex_); + for (const auto& event : metadata_events_) AppendTraceEvent(event.get()); + } + + for (const auto& id_writer : writers_) id_writer.second->Flush(blocking); +} + +void LegacyTracingAgent::StartTracing(const std::string& categories) { + // Attach a new NodeTraceWriter only if this function hasn't been called + // before. + if (tracing_file_writer_.id_ != LegacyTracingAgent::kDefaultHandleId) return; + + using std::operator""sv; + auto parts = std::views::split(categories, ","sv); + + std::set categories_set; + for (const auto& s : parts) { + categories_set.emplace(std::string(s.data(), s.size())); + } + + tracing_file_writer_ = + AddClient(categories_set, + std::unique_ptr(new NodeTraceWriter( + per_process::cli_options->trace_event_file_pattern)), + kUseDefaultCategories); +} + +void LegacyTracingAgent::StopTracing() { + tracing_file_writer_.reset(); + tracing_file_writer_ = AgentWriterHandle(this, kDefaultHandleId); +} + +AgentWriterHandle* LegacyTracingAgent::GetDefaultWriterHandle() { + return &tracing_file_writer_; +} + +void TracingController::AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* name, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const uint64_t* arg_values, + std::unique_ptr* convertable_values, + unsigned int flags) { + std::unique_ptr trace_event(new TraceObject); + trace_event->Initialize(TRACE_EVENT_PHASE_METADATA, + category_group_enabled, + name, + node::tracing::kGlobalScope, // scope + node::tracing::kNoId, // id + node::tracing::kNoId, // bind_id + num_args, + arg_names, + arg_types, + arg_values, + convertable_values, + TRACE_EVENT_FLAG_NONE, + CurrentTimestampMicroseconds(), + CurrentCpuTimestampMicroseconds()); + LegacyTracingAgent* node_agent = + static_cast(Agent::GetInstance()); + if (node_agent != nullptr) + node_agent->AddMetadataEvent(std::move(trace_event)); +} + +} // namespace tracing +} // namespace node diff --git a/src/tracing/agent_legacy.h b/src/tracing/agent_legacy.h new file mode 100644 index 00000000000000..4b2a728dc28a53 --- /dev/null +++ b/src/tracing/agent_legacy.h @@ -0,0 +1,142 @@ +#ifndef SRC_TRACING_AGENT_LEGACY_H_ +#define SRC_TRACING_AGENT_LEGACY_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +// This is an implementation of the legacy V8 tracing agent +// defined in `libplatform/v8-tracing.h`. + +#include "libplatform/v8-tracing.h" +#include "node_mutex.h" +#include "tracing/agent.h" +#include "util.h" +#include "uv.h" + +#include +#include +#include +#include + +namespace node { +namespace tracing { + +using v8::platform::tracing::TraceConfig; +using v8::platform::tracing::TraceObject; + +class AsyncTraceWriter { + public: + virtual ~AsyncTraceWriter() = default; + virtual void AppendTraceEvent(TraceObject* trace_event) = 0; + virtual void Flush(bool blocking) = 0; + virtual void InitializeOnThread(uv_loop_t* loop) {} +}; + +class TracingController : public v8::platform::tracing::TracingController { + public: + TracingController() : v8::platform::tracing::TracingController() {} + + int64_t CurrentTimestampMicroseconds() override { return uv_hrtime() / 1000; } + void AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* name, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const uint64_t* arg_values, + std::unique_ptr* convertable_values, + unsigned int flags); +}; + +class NodeTraceStateObserver + : public v8::TracingController::TraceStateObserver { + public: + void OnTraceEnabled() override; + void OnTraceDisabled() override { UNREACHABLE(); } + + explicit NodeTraceStateObserver(v8::TracingController* controller) + : controller_(controller) {} + ~NodeTraceStateObserver() override = default; + + private: + v8::TracingController* controller_; +}; + +class LegacyTracingAgent final : public Agent { + public: + enum UseDefaultCategoryMode { + kUseDefaultCategories, + kIgnoreDefaultCategories + }; + + LegacyTracingAgent(); + ~LegacyTracingAgent() override; + + TracingController* GetTracingController() override { + TracingController* controller = tracing_controller_.get(); + CHECK_NOT_NULL(controller); + return controller; + } + + AgentWriterHandle AddClient(const std::set& categories, + std::unique_ptr writer, + enum UseDefaultCategoryMode mode); + std::string GetEnabledCategories() const override; + void AppendTraceEvent(TraceObject* trace_event); + void AddMetadataEvent(std::unique_ptr event); + void Flush(bool blocking); + TraceConfig* CreateTraceConfig() const; + + void StartTracing(const std::string& categories) override; + void StopTracing() override; + AgentWriterHandle* GetDefaultWriterHandle() override; + + void AddTraceStateObserver( + v8::TracingController::TraceStateObserver* observer) override { + tracing_controller_->AddTraceStateObserver(observer); + } + void RemoveTraceStateObserver( + v8::TracingController::TraceStateObserver* observer) override { + tracing_controller_->RemoveTraceStateObserver(observer); + } + + private: + static constexpr int kDefaultHandleId = -1; + + void Disconnect(int client) override; + + void Enable(int id, const std::set& categories) override; + void Disable(int id, const std::set& categories) override; + + void InitializeWritersOnThread(); + void Start(); + void Stop(); + + uv_thread_t thread_; + uv_loop_t tracing_loop_; + + bool started_ = false; + class ScopedSuspendTracing; + + int next_writer_id_ = 1; + std::unordered_map> categories_; + std::unordered_map> writers_; + std::unique_ptr tracing_controller_; + + Mutex initialize_writer_mutex_; + ConditionVariable initialize_writer_condvar_; + uv_async_t initialize_writer_async_; + std::set to_be_initialized_; + + Mutex metadata_events_mutex_; + std::list> metadata_events_; + + AgentWriterHandle tracing_file_writer_; + std::unique_ptr trace_state_observer_; +}; + +} // namespace tracing +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_TRACING_AGENT_LEGACY_H_ diff --git a/src/tracing/node_trace_buffer.cc b/src/tracing/node_trace_buffer.cc index e187a1d78c8197..4e2b1226b05b2e 100644 --- a/src/tracing/node_trace_buffer.cc +++ b/src/tracing/node_trace_buffer.cc @@ -6,10 +6,10 @@ namespace node { namespace tracing { -InternalTraceBuffer::InternalTraceBuffer(size_t max_chunks, uint32_t id, - Agent* agent) - : flushing_(false), max_chunks_(max_chunks), - agent_(agent), id_(id) { +InternalTraceBuffer::InternalTraceBuffer(size_t max_chunks, + uint32_t id, + LegacyTracingAgent* agent) + : flushing_(false), max_chunks_(max_chunks), agent_(agent), id_(id) { chunks_.resize(max_chunks); } @@ -96,7 +96,8 @@ void InternalTraceBuffer::ExtractHandle( } NodeTraceBuffer::NodeTraceBuffer(size_t max_chunks, - Agent* agent, uv_loop_t* tracing_loop) + LegacyTracingAgent* agent, + uv_loop_t* tracing_loop) : tracing_loop_(tracing_loop), buffer1_(max_chunks, 0, agent), buffer2_(max_chunks, 1, agent) { diff --git a/src/tracing/node_trace_buffer.h b/src/tracing/node_trace_buffer.h index 18e4f43efaae3a..d9f4b221c91f2a 100644 --- a/src/tracing/node_trace_buffer.h +++ b/src/tracing/node_trace_buffer.h @@ -1,9 +1,11 @@ #ifndef SRC_TRACING_NODE_TRACE_BUFFER_H_ #define SRC_TRACING_NODE_TRACE_BUFFER_H_ -#include "tracing/agent.h" -#include "node_mutex.h" +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + #include "libplatform/v8-tracing.h" +#include "node_mutex.h" +#include "tracing/agent_legacy.h" #include @@ -19,7 +21,9 @@ class NodeTraceBuffer; class InternalTraceBuffer { public: - InternalTraceBuffer(size_t max_chunks, uint32_t id, Agent* agent); + InternalTraceBuffer(size_t max_chunks, + uint32_t id, + LegacyTracingAgent* agent); TraceObject* AddTraceEvent(uint64_t* handle); TraceObject* GetEventByHandle(uint64_t handle); @@ -41,7 +45,7 @@ class InternalTraceBuffer { Mutex mutex_; bool flushing_; size_t max_chunks_; - Agent* agent_; + LegacyTracingAgent* agent_; std::vector> chunks_; size_t total_chunks_ = 0; uint32_t current_chunk_seq_ = 1; @@ -50,7 +54,9 @@ class InternalTraceBuffer { class NodeTraceBuffer : public TraceBuffer { public: - NodeTraceBuffer(size_t max_chunks, Agent* agent, uv_loop_t* tracing_loop); + NodeTraceBuffer(size_t max_chunks, + LegacyTracingAgent* agent, + uv_loop_t* tracing_loop); ~NodeTraceBuffer() override; TraceObject* AddTraceEvent(uint64_t* handle) override; @@ -80,4 +86,6 @@ class NodeTraceBuffer : public TraceBuffer { } // namespace tracing } // namespace node +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + #endif // SRC_TRACING_NODE_TRACE_BUFFER_H_ diff --git a/src/tracing/node_trace_writer.h b/src/tracing/node_trace_writer.h index cd965d77b7859f..02efb2c75a84a4 100644 --- a/src/tracing/node_trace_writer.h +++ b/src/tracing/node_trace_writer.h @@ -1,11 +1,13 @@ #ifndef SRC_TRACING_NODE_TRACE_WRITER_H_ #define SRC_TRACING_NODE_TRACE_WRITER_H_ +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + #include #include #include "libplatform/v8-tracing.h" -#include "tracing/agent.h" +#include "tracing/agent_legacy.h" #include "uv.h" namespace node { @@ -72,4 +74,6 @@ class NodeTraceWriter : public AsyncTraceWriter { } // namespace tracing } // namespace node +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + #endif // SRC_TRACING_NODE_TRACE_WRITER_H_ diff --git a/src/tracing/trace_event.cc b/src/tracing/trace_event.cc index 35acb8a9a8fd10..59306fafb3a10d 100644 --- a/src/tracing/trace_event.cc +++ b/src/tracing/trace_event.cc @@ -4,23 +4,8 @@ namespace node { namespace tracing { -Agent* g_agent = nullptr; v8::TracingController* g_controller = nullptr; -void TraceEventHelper::SetAgent(Agent* agent) { - if (agent) { - g_agent = agent; - g_controller = agent->GetTracingController(); - } else { - g_agent = nullptr; - g_controller = nullptr; - } -} - -Agent* TraceEventHelper::GetAgent() { - return g_agent; -} - v8::TracingController* TraceEventHelper::GetTracingController() { return g_controller; } diff --git a/src/tracing/trace_event.h b/src/tracing/trace_event.h index a662a081dc3bf3..a0f8c695ea0160 100644 --- a/src/tracing/trace_event.h +++ b/src/tracing/trace_event.h @@ -6,7 +6,7 @@ #define SRC_TRACING_TRACE_EVENT_H_ #include "v8-platform.h" -#include "tracing/agent.h" +#include "tracing/agent_legacy.h" #include "trace_event_common.h" #include @@ -315,9 +315,6 @@ class TraceEventHelper { static v8::TracingController* GetTracingController(); static void SetTracingController(v8::TracingController* controller); - static Agent* GetAgent(); - static void SetAgent(Agent* agent); - static inline const uint8_t* GetCategoryGroupEnabled(const char* group) { v8::TracingController* controller = GetTracingController(); static const uint8_t disabled = 0; @@ -517,11 +514,12 @@ static V8_INLINE void AddMetadataEventImpl( static_cast(arg_values[1]))); } node::tracing::Agent* agent = - node::tracing::TraceEventHelper::GetAgent(); + node::tracing::Agent::GetInstance(); if (agent == nullptr) return; - return agent->GetTracingController()->AddMetadataEvent( - category_group_enabled, name, num_args, arg_names, arg_types, arg_values, - arg_convertibles, flags); + static_cast( + agent->GetTracingController()) + ->AddMetadataEvent(category_group_enabled, name, num_args, arg_names, + arg_types, arg_values, arg_convertibles, flags); } // Define SetTraceValue for each allowed type. It stores the type and diff --git a/test/cctest/node_test_fixture.cc b/test/cctest/node_test_fixture.cc index 6b75e88d14c2b0..0da5a908e5f38e 100644 --- a/test/cctest/node_test_fixture.cc +++ b/test/cctest/node_test_fixture.cc @@ -12,10 +12,8 @@ node::IsolateData* EnvironmentTestFixture::isolate_data_ = nullptr; void NodeTestEnvironment::SetUp() { NodeZeroIsolateTestFixture::tracing_agent = - std::make_unique(); - node::tracing::TraceEventHelper::SetAgent( - NodeZeroIsolateTestFixture::tracing_agent.get()); - node::tracing::TracingController* tracing_controller = + node::tracing::Agent::CreateDefault(); + v8::TracingController* tracing_controller = NodeZeroIsolateTestFixture::tracing_agent->GetTracingController(); static constexpr int kV8ThreadPoolSize = 4; NodeZeroIsolateTestFixture::platform.reset( diff --git a/test/cctest/node_test_fixture.h b/test/cctest/node_test_fixture.h index d3ec9d25a3ddf7..56245bde417e7c 100644 --- a/test/cctest/node_test_fixture.h +++ b/test/cctest/node_test_fixture.h @@ -57,7 +57,8 @@ struct Argv { using ArrayBufferUniquePtr = std::unique_ptr; -using TracingAgentUniquePtr = std::unique_ptr; +using TracingAgentUniquePtr = + std::unique_ptr; using NodePlatformUniquePtr = std::unique_ptr; class NodeTestEnvironment final : public ::testing::Environment { diff --git a/test/fuzzers/fuzz_env.cc b/test/fuzzers/fuzz_env.cc index 326d82ae20e03d..e2169296550da6 100644 --- a/test/fuzzers/fuzz_env.cc +++ b/test/fuzzers/fuzz_env.cc @@ -35,9 +35,8 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors); - tracing_agent = std::make_unique(); - node::tracing::TraceEventHelper::SetAgent(tracing_agent.get()); - node::tracing::TracingController* tracing_controller = + tracing_agent = node::tracing::Agent::CreateDefault(); + v8::TracingController* tracing_controller = tracing_agent->GetTracingController(); CHECK_EQ(0, uv_loop_init(¤t_loop)); static constexpr int kV8ThreadPoolSize = 4; diff --git a/test/fuzzers/fuzz_strings.cc b/test/fuzzers/fuzz_strings.cc index 2226a471f3bef9..92b386d2ecd4a7 100644 --- a/test/fuzzers/fuzz_strings.cc +++ b/test/fuzzers/fuzz_strings.cc @@ -42,9 +42,8 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors); - tracing_agent = std::make_unique(); - node::tracing::TraceEventHelper::SetAgent(tracing_agent.get()); - node::tracing::TracingController* tracing_controller = + tracing_agent = node::tracing::Agent::CreateDefault(); + v8::TracingController* tracing_controller = tracing_agent->GetTracingController(); CHECK_EQ(0, uv_loop_init(¤t_loop)); static constexpr int kV8ThreadPoolSize = 4;