diff options
author | James M Snell <jasnell@gmail.com> | 2018-04-04 04:05:33 +0300 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2018-04-17 18:30:20 +0300 |
commit | 5c27e44488aa1c00248297204ff3484c24ff3ae7 (patch) | |
tree | 4c061d36122bcb91028eb9d0457dfa15bc84604a /src/tracing | |
parent | 95fafc0254f6636b7c7546ac63599c79a7182fd9 (diff) |
trace_events: adds a new trace_events api
Removes the requirement to use `--trace-events-enabled` to enable
trace events. Tracing is enabled automatically if there are any
enabled categories.
Adds a new `trace_events` module with an API for enabling/disabling
trace events at runtime without a command line flag.
```js
const trace_events = require('trace_events');
const categories = [ 'node.perf', 'node.async_hooks' ];
const tracing = trace_events.createTracing({ categories });
tracing.enable();
// do stuff
tracing.disable();
```
Multiple `Tracing` objects may exist and be enabled at any point
in time. The enabled trace event categories is the union of all
enabled `Tracing` objects and the `--trace-event-categories`
flag.
PR-URL: https://github.com/nodejs/node/pull/19803
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Diffstat (limited to 'src/tracing')
-rw-r--r-- | src/tracing/agent.cc | 113 | ||||
-rw-r--r-- | src/tracing/agent.h | 19 |
2 files changed, 101 insertions, 31 deletions
diff --git a/src/tracing/agent.cc b/src/tracing/agent.cc index 71e53e787a4..cd4c3c0df93 100644 --- a/src/tracing/agent.cc +++ b/src/tracing/agent.cc @@ -5,55 +5,40 @@ #include "tracing/node_trace_buffer.h" #include "tracing/node_trace_writer.h" -#include "env-inl.h" - namespace node { namespace tracing { using v8::platform::tracing::TraceConfig; using std::string; -Agent::Agent(const std::string& log_file_pattern) { - int err = uv_loop_init(&tracing_loop_); - CHECK_EQ(err, 0); +Agent::Agent(const std::string& log_file_pattern) + : log_file_pattern_(log_file_pattern) { + tracing_controller_ = new TracingController(); + tracing_controller_->Initialize(nullptr); +} + +void Agent::Start() { + if (started_) + return; - NodeTraceWriter* trace_writer = new NodeTraceWriter( - log_file_pattern, &tracing_loop_); + CHECK_EQ(uv_loop_init(&tracing_loop_), 0); + + NodeTraceWriter* trace_writer = + new NodeTraceWriter(log_file_pattern_, &tracing_loop_); TraceBuffer* trace_buffer = new NodeTraceBuffer( NodeTraceBuffer::kBufferChunks, trace_writer, &tracing_loop_); - tracing_controller_ = new TracingController(); tracing_controller_->Initialize(trace_buffer); -} - -void Agent::Start(const string& enabled_categories) { - TraceConfig* trace_config = new TraceConfig(); - if (!enabled_categories.empty()) { - std::stringstream category_list(enabled_categories); - while (category_list.good()) { - std::string category; - getline(category_list, category, ','); - trace_config->AddIncludedCategory(category.c_str()); - } - } else { - trace_config->AddIncludedCategory("v8"); - trace_config->AddIncludedCategory("node"); - trace_config->AddIncludedCategory("node.async_hooks"); - } // This thread should be created *after* async handles are created // (within NodeTraceWriter and NodeTraceBuffer constructors). // Otherwise the thread could shut down prematurely. - int err = uv_thread_create(&thread_, ThreadCb, this); - CHECK_EQ(err, 0); - - tracing_controller_->StartTracing(trace_config); + CHECK_EQ(0, uv_thread_create(&thread_, ThreadCb, this)); started_ = true; } void Agent::Stop() { - if (!started_) { + 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(); @@ -70,5 +55,73 @@ void Agent::ThreadCb(void* arg) { uv_run(&agent->tracing_loop_, UV_RUN_DEFAULT); } +void Agent::Enable(const std::string& categories) { + if (!categories.empty()) { + std::stringstream category_list(categories); + while (category_list.good()) { + std::string category; + getline(category_list, category, ','); + categories_.insert(category.c_str()); + } + RestartTracing(); + } +} + +void Agent::Enable(const std::set<std::string>& categories) { + if (!categories.empty()) { + categories_.insert(categories.begin(), categories.end()); + RestartTracing(); + } +} + +void Agent::Disable(const std::set<std::string>& categories) { + if (!categories.empty()) { + for (auto category : categories) { + auto pos = categories_.lower_bound(category); + if (pos != categories_.end()) + categories_.erase(pos); + } + RestartTracing(); + } +} + +void Agent::RestartTracing() { + static bool warned; + if (!warned) { + warned = true; + fprintf(stderr, "Warning: Trace event is an experimental feature " + "and could change at any time.\n"); + } + Start(); // Start the agent if it hasn't already been started + tracing_controller_->StopTracing(); + auto config = CreateTraceConfig(); + if (config != nullptr) + tracing_controller_->StartTracing(config); +} + +TraceConfig* Agent::CreateTraceConfig() { + if (categories_.empty()) + return nullptr; + TraceConfig* trace_config = new TraceConfig(); + for (auto category = categories_.begin(); + category != categories_.end(); + category = categories_.upper_bound(*category)) { + trace_config->AddIncludedCategory(category->c_str()); + } + return trace_config; +} + +std::string Agent::GetEnabledCategories() { + std::string categories; + for (auto category = categories_.begin(); + category != categories_.end(); + category = categories_.upper_bound(*category)) { + if (!categories.empty()) + categories += ','; + categories += *category; + } + return categories; +} + } // namespace tracing } // namespace node diff --git a/src/tracing/agent.h b/src/tracing/agent.h index 9d6bc4e90a3..ca5fd35417f 100644 --- a/src/tracing/agent.h +++ b/src/tracing/agent.h @@ -5,9 +5,14 @@ #include "uv.h" #include "v8.h" +#include <set> +#include <string> + namespace node { namespace tracing { +using v8::platform::tracing::TraceConfig; + class TracingController : public v8::platform::tracing::TracingController { public: TracingController() : v8::platform::tracing::TracingController() {} @@ -20,17 +25,29 @@ class TracingController : public v8::platform::tracing::TracingController { class Agent { public: explicit Agent(const std::string& log_file_pattern); - void Start(const std::string& enabled_categories); void Stop(); TracingController* GetTracingController() { return tracing_controller_; } + void Enable(const std::string& categories); + void Enable(const std::set<std::string>& categories); + void Disable(const std::set<std::string>& categories); + std::string GetEnabledCategories(); + private: static void ThreadCb(void* arg); + void Start(); + void RestartTracing(); + + TraceConfig* CreateTraceConfig(); + + const std::string& log_file_pattern_; uv_thread_t thread_; uv_loop_t tracing_loop_; bool started_ = false; + + std::multiset<std::string> categories_; TracingController* tracing_controller_ = nullptr; }; |