Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2018-04-04 04:05:33 +0300
committerJames M Snell <jasnell@gmail.com>2018-04-17 18:30:20 +0300
commit5c27e44488aa1c00248297204ff3484c24ff3ae7 (patch)
tree4c061d36122bcb91028eb9d0457dfa15bc84604a /src/tracing
parent95fafc0254f6636b7c7546ac63599c79a7182fd9 (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.cc113
-rw-r--r--src/tracing/agent.h19
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;
};