• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "base_object-inl.h"
2 #include "env-inl.h"
3 #include "memory_tracker-inl.h"
4 #include "node.h"
5 #include "node_internals.h"
6 #include "node_v8_platform-inl.h"
7 #include "tracing/agent.h"
8 #include "util-inl.h"
9 
10 #include <set>
11 #include <string>
12 
13 namespace node {
14 
15 using v8::Array;
16 using v8::Context;
17 using v8::Function;
18 using v8::FunctionCallbackInfo;
19 using v8::FunctionTemplate;
20 using v8::Local;
21 using v8::NewStringType;
22 using v8::Object;
23 using v8::String;
24 using v8::Value;
25 
26 class NodeCategorySet : public BaseObject {
27  public:
28   static void Initialize(Local<Object> target,
29                   Local<Value> unused,
30                   Local<Context> context,
31                   void* priv);
32 
33   static void New(const FunctionCallbackInfo<Value>& args);
34   static void Enable(const FunctionCallbackInfo<Value>& args);
35   static void Disable(const FunctionCallbackInfo<Value>& args);
36 
GetCategories() const37   const std::set<std::string>& GetCategories() const { return categories_; }
38 
MemoryInfo(MemoryTracker * tracker) const39   void MemoryInfo(MemoryTracker* tracker) const override {
40     tracker->TrackField("categories", categories_);
41   }
42 
43   SET_MEMORY_INFO_NAME(NodeCategorySet)
44   SET_SELF_SIZE(NodeCategorySet)
45 
46  private:
NodeCategorySet(Environment * env,Local<Object> wrap,std::set<std::string> && categories)47   NodeCategorySet(Environment* env,
48                   Local<Object> wrap,
49                   std::set<std::string>&& categories) :
50         BaseObject(env, wrap), categories_(std::move(categories)) {
51     MakeWeak();
52   }
53 
54   bool enabled_ = false;
55   const std::set<std::string> categories_;
56 };
57 
New(const FunctionCallbackInfo<Value> & args)58 void NodeCategorySet::New(const FunctionCallbackInfo<Value>& args) {
59   Environment* env = Environment::GetCurrent(args);
60   std::set<std::string> categories;
61   CHECK(args[0]->IsArray());
62   Local<Array> cats = args[0].As<Array>();
63   for (size_t n = 0; n < cats->Length(); n++) {
64     Local<Value> category;
65     if (!cats->Get(env->context(), n).ToLocal(&category)) return;
66     Utf8Value val(env->isolate(), category);
67     if (!*val) return;
68     categories.emplace(*val);
69   }
70   CHECK_NOT_NULL(GetTracingAgentWriter());
71   new NodeCategorySet(env, args.This(), std::move(categories));
72 }
73 
Enable(const FunctionCallbackInfo<Value> & args)74 void NodeCategorySet::Enable(const FunctionCallbackInfo<Value>& args) {
75   NodeCategorySet* category_set;
76   ASSIGN_OR_RETURN_UNWRAP(&category_set, args.Holder());
77   CHECK_NOT_NULL(category_set);
78   const auto& categories = category_set->GetCategories();
79   if (!category_set->enabled_ && !categories.empty()) {
80     // Starts the Tracing Agent if it wasn't started already (e.g. through
81     // a command line flag.)
82     StartTracingAgent();
83     GetTracingAgentWriter()->Enable(categories);
84     category_set->enabled_ = true;
85   }
86 }
87 
Disable(const FunctionCallbackInfo<Value> & args)88 void NodeCategorySet::Disable(const FunctionCallbackInfo<Value>& args) {
89   NodeCategorySet* category_set;
90   ASSIGN_OR_RETURN_UNWRAP(&category_set, args.Holder());
91   CHECK_NOT_NULL(category_set);
92   const auto& categories = category_set->GetCategories();
93   if (category_set->enabled_ && !categories.empty()) {
94     GetTracingAgentWriter()->Disable(categories);
95     category_set->enabled_ = false;
96   }
97 }
98 
GetEnabledCategories(const FunctionCallbackInfo<Value> & args)99 void GetEnabledCategories(const FunctionCallbackInfo<Value>& args) {
100   Environment* env = Environment::GetCurrent(args);
101   std::string categories =
102       GetTracingAgentWriter()->agent()->GetEnabledCategories();
103   if (!categories.empty()) {
104     args.GetReturnValue().Set(
105       String::NewFromUtf8(env->isolate(),
106                           categories.c_str(),
107                           NewStringType::kNormal,
108                           categories.size()).ToLocalChecked());
109   }
110 }
111 
SetTraceCategoryStateUpdateHandler(const FunctionCallbackInfo<Value> & args)112 static void SetTraceCategoryStateUpdateHandler(
113     const FunctionCallbackInfo<Value>& args) {
114   Environment* env = Environment::GetCurrent(args);
115   CHECK(args[0]->IsFunction());
116   env->set_trace_category_state_function(args[0].As<Function>());
117 }
118 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)119 void NodeCategorySet::Initialize(Local<Object> target,
120                 Local<Value> unused,
121                 Local<Context> context,
122                 void* priv) {
123   Environment* env = Environment::GetCurrent(context);
124 
125   env->SetMethod(target, "getEnabledCategories", GetEnabledCategories);
126   env->SetMethod(
127       target, "setTraceCategoryStateUpdateHandler",
128       SetTraceCategoryStateUpdateHandler);
129 
130   Local<FunctionTemplate> category_set =
131       env->NewFunctionTemplate(NodeCategorySet::New);
132   category_set->InstanceTemplate()->SetInternalFieldCount(
133       NodeCategorySet::kInternalFieldCount);
134   category_set->Inherit(BaseObject::GetConstructorTemplate(env));
135   env->SetProtoMethod(category_set, "enable", NodeCategorySet::Enable);
136   env->SetProtoMethod(category_set, "disable", NodeCategorySet::Disable);
137 
138   env->SetConstructorFunction(target, "CategorySet", category_set);
139 
140   Local<String> isTraceCategoryEnabled =
141       FIXED_ONE_BYTE_STRING(env->isolate(), "isTraceCategoryEnabled");
142   Local<String> trace = FIXED_ONE_BYTE_STRING(env->isolate(), "trace");
143 
144   // Grab the trace and isTraceCategoryEnabled intrinsics from the binding
145   // object and expose those to our binding layer.
146   Local<Object> binding = context->GetExtrasBindingObject();
147   target->Set(context, isTraceCategoryEnabled,
148               binding->Get(context, isTraceCategoryEnabled).ToLocalChecked())
149                   .Check();
150   target->Set(context, trace,
151               binding->Get(context, trace).ToLocalChecked()).Check();
152 }
153 
154 }  // namespace node
155 
156 NODE_MODULE_CONTEXT_AWARE_INTERNAL(trace_events,
157                                    node::NodeCategorySet::Initialize)
158