/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/inspector/tracing_agent.cc
214 строк
7 KB
Chengzhong Wu
src: abstract tracing agent for both legacy and perfetto
29 июн 2026, 16:57
Не верифицирован
29 июн 2026, 16:57
d95cbc2
Код
Авторство
О чём код?
#include "tracing_agent.h" #include "crdtp/json.h" #include "main_thread_interface.h" #include "node_internals.h" #include "node_v8_platform-inl.h" #include "tracing/agent_legacy.h" #include "v8.h" #include <set> #include <sstream> namespace node { namespace inspector { namespace protocol { namespace { using v8::platform::tracing::TraceWriter; class DeletableFrontendWrapper : public Deletable { public: explicit DeletableFrontendWrapper( std::weak_ptr<NodeTracing::Frontend> frontend) : frontend_(frontend) {} // This should only be called from the main thread, meaning frontend should // not be destroyed concurrently. NodeTracing::Frontend* get() { return frontend_.lock().get(); } private: std::weak_ptr<NodeTracing::Frontend> frontend_; }; class CreateFrontendWrapperRequest : public Request { public: CreateFrontendWrapperRequest(int object_id, std::weak_ptr<NodeTracing::Frontend> frontend) : object_id_(object_id) { frontend_wrapper_ = std::make_unique<DeletableFrontendWrapper>(frontend); } void Call(MainThreadInterface* thread) override { thread->AddObject(object_id_, std::move(frontend_wrapper_)); } private: int object_id_; std::unique_ptr<DeletableFrontendWrapper> frontend_wrapper_; }; class DestroyFrontendWrapperRequest : public Request { public: explicit DestroyFrontendWrapperRequest(int object_id) : object_id_(object_id) {} void Call(MainThreadInterface* thread) override { thread->RemoveObject(object_id_); } private: int object_id_; }; class SendMessageRequest : public Request { public: explicit SendMessageRequest(int object_id, const std::string& message) : object_id_(object_id), message_(message) {} void Call(MainThreadInterface* thread) override { DeletableFrontendWrapper* frontend_wrapper = static_cast<DeletableFrontendWrapper*>( thread->GetObjectIfExists(object_id_)); if (frontend_wrapper == nullptr) return; auto frontend = frontend_wrapper->get(); if (frontend == nullptr) { return; } std::vector<uint8_t> cbor; crdtp::Status status = crdtp::json::ConvertJSONToCBOR(crdtp::SpanFrom(message_), &cbor); DCHECK(status.ok()); USE(status); frontend->sendRawNotification(Serializable::From(cbor)); } private: int object_id_; std::string message_; }; class InspectorTraceWriter : public node::tracing::AsyncTraceWriter { public: explicit InspectorTraceWriter(int frontend_object_id, std::shared_ptr<MainThreadHandle> main_thread) : frontend_object_id_(frontend_object_id), main_thread_(main_thread) {} void AppendTraceEvent( v8::platform::tracing::TraceObject* trace_event) override { if (!json_writer_) json_writer_.reset(TraceWriter::CreateJSONTraceWriter(stream_, "value")); json_writer_->AppendTraceEvent(trace_event); } void Flush(bool) override { if (!json_writer_) return; json_writer_.reset(); std::ostringstream result( "{\"method\":\"NodeTracing.dataCollected\",\"params\":", std::ostringstream::ate); result << stream_.str(); result << "}"; main_thread_->Post(std::make_unique<SendMessageRequest>(frontend_object_id_, result.str())); stream_.str(""); } private: std::unique_ptr<TraceWriter> json_writer_; std::ostringstream stream_; int frontend_object_id_; std::shared_ptr<MainThreadHandle> main_thread_; }; } // namespace TracingAgent::TracingAgent(Environment* env, std::shared_ptr<MainThreadHandle> main_thread) : env_(env), main_thread_(main_thread) {} TracingAgent::~TracingAgent() { trace_writer_.reset(); main_thread_->Post( std::make_unique<DestroyFrontendWrapperRequest>(frontend_object_id_)); } void TracingAgent::Wire(UberDispatcher* dispatcher) { // Note that frontend is still owned by TracingAgent frontend_ = std::make_shared<NodeTracing::Frontend>(dispatcher->channel()); frontend_object_id_ = main_thread_->newObjectId(); main_thread_->Post(std::make_unique<CreateFrontendWrapperRequest>( frontend_object_id_, frontend_)); NodeTracing::Dispatcher::wire(dispatcher, this); } DispatchResponse TracingAgent::start( std::unique_ptr<protocol::NodeTracing::TraceConfig> traceConfig) { if (!trace_writer_.empty()) { return DispatchResponse::InvalidRequest( "Call NodeTracing::end to stop tracing before updating the config"); } if (!env_->owns_process_state()) { return DispatchResponse::InvalidRequest( "Tracing properties can only be changed through main thread sessions"); } std::set<std::string> categories_set; protocol::Array<std::string>* categories = traceConfig->getIncludedCategories(); for (size_t i = 0; i < categories->size(); i++) categories_set.insert((*categories)[i]); if (categories_set.empty()) return DispatchResponse::InvalidRequest( "At least one category should be enabled"); auto* agent = static_cast<tracing::LegacyTracingAgent*>(tracing::Agent::GetInstance()); if (agent != nullptr) { trace_writer_ = agent->AddClient(categories_set, std::make_unique<InspectorTraceWriter>( frontend_object_id_, main_thread_), tracing::LegacyTracingAgent::kIgnoreDefaultCategories); } return DispatchResponse::Success(); } DispatchResponse TracingAgent::stop() { trace_writer_.reset(); frontend_->tracingComplete(); return DispatchResponse::Success(); } DispatchResponse TracingAgent::getCategories( std::unique_ptr<protocol::Array<String>>* categories) { *categories = std::make_unique<Array<String>>(); protocol::Array<String>* categories_list = categories->get(); // In alphabetical order categories_list->emplace_back("node"); categories_list->emplace_back("node.async_hooks"); categories_list->emplace_back("node.bootstrap"); categories_list->emplace_back("node.console"); categories_list->emplace_back("node.dns.native"); categories_list->emplace_back("node.environment"); categories_list->emplace_back("node.fs.async"); categories_list->emplace_back("node.fs.sync"); categories_list->emplace_back("node.fs_dir.async"); categories_list->emplace_back("node.fs_dir.sync"); categories_list->emplace_back("node.http"); categories_list->emplace_back("node.net.native"); categories_list->emplace_back("node.perf"); categories_list->emplace_back("node.perf.timerify"); categories_list->emplace_back("node.perf.usertiming"); categories_list->emplace_back("node.promises.rejections"); categories_list->emplace_back("node.threadpoolwork.async"); categories_list->emplace_back("node.threadpoolwork.sync"); categories_list->emplace_back("node.vm.script"); categories_list->emplace_back("v8"); return DispatchResponse::Success(); } } // namespace protocol } // namespace inspector } // namespace node