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/node_trace_events.cc | |
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/node_trace_events.cc')
-rw-r--r-- | src/node_trace_events.cc | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index 96d00115fee..1e02048d1f0 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -1,15 +1,98 @@ +#include "node.h" #include "node_internals.h" #include "tracing/agent.h" +#include "env.h" +#include "base_object-inl.h" + +#include <set> +#include <string> namespace node { +using v8::Array; using v8::Context; using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; using v8::Int32; using v8::Local; using v8::Object; +using v8::String; using v8::Value; +class NodeCategorySet : public BaseObject { + public: + ~NodeCategorySet() override { + // Verify that the thing was properly disabled before gc + CHECK_NE(enabled_, true); + } + + static void New(const FunctionCallbackInfo<Value>& args); + static void Enable(const FunctionCallbackInfo<Value>& args); + static void Disable(const FunctionCallbackInfo<Value>& args); + + const std::set<std::string>& GetCategories() { return categories_; } + + private: + NodeCategorySet(Environment* env, + Local<Object> wrap, + std::set<std::string> categories) : + BaseObject(env, wrap), categories_(categories) { + MakeWeak<NodeCategorySet>(this); + } + + bool enabled_ = false; + const std::set<std::string> categories_; +}; + +void NodeCategorySet::New(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + std::set<std::string> categories; + CHECK(args[0]->IsArray()); + Local<Array> cats = args[0].As<Array>(); + for (size_t n = 0; n < cats->Length(); n++) { + Local<Value> category = cats->Get(env->context(), n).ToLocalChecked(); + Utf8Value val(env->isolate(), category); + categories.emplace(*val); + } + CHECK_NE(env->tracing_agent(), nullptr); + new NodeCategorySet(env, args.This(), categories); +} + +void NodeCategorySet::Enable(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + NodeCategorySet* category_set; + ASSIGN_OR_RETURN_UNWRAP(&category_set, args.Holder()); + CHECK_NE(category_set, nullptr); + auto categories = category_set->GetCategories(); + if (!category_set->enabled_ && !categories.empty()) { + env->tracing_agent()->Enable(categories); + category_set->enabled_ = true; + } +} + +void NodeCategorySet::Disable(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + NodeCategorySet* category_set; + ASSIGN_OR_RETURN_UNWRAP(&category_set, args.Holder()); + CHECK_NE(category_set, nullptr); + auto categories = category_set->GetCategories(); + if (category_set->enabled_ && !categories.empty()) { + env->tracing_agent()->Disable(categories); + category_set->enabled_ = false; + } +} + +void GetEnabledCategories(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + std::string categories = env->tracing_agent()->GetEnabledCategories(); + if (!categories.empty()) { + args.GetReturnValue().Set( + String::NewFromUtf8(env->isolate(), + categories.c_str(), + v8::NewStringType::kNormal).ToLocalChecked()); + } +} + // The tracing APIs require category groups to be pointers to long-lived // strings. Those strings are stored here. static std::unordered_set<std::string> categoryGroups; @@ -140,6 +223,16 @@ void Initialize(Local<Object> target, env->SetMethod(target, "emit", Emit); env->SetMethod(target, "categoryGroupEnabled", CategoryGroupEnabled); + env->SetMethod(target, "getEnabledCategories", GetEnabledCategories); + + Local<FunctionTemplate> category_set = + env->NewFunctionTemplate(NodeCategorySet::New); + category_set->InstanceTemplate()->SetInternalFieldCount(1); + env->SetProtoMethod(category_set, "enable", NodeCategorySet::Enable); + env->SetProtoMethod(category_set, "disable", NodeCategorySet::Disable); + + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "CategorySet"), + category_set->GetFunction()); } } // namespace node |