1 #ifndef SRC_TRACING_AGENT_H_
2 #define SRC_TRACING_AGENT_H_
3
4 #include "libplatform/v8-tracing.h"
5 #include "uv.h"
6 #include "util.h"
7 #include "node_mutex.h"
8
9 #include <list>
10 #include <set>
11 #include <string>
12 #include <unordered_map>
13
14 namespace v8 {
15 class ConvertableToTraceFormat;
16 class TracingController;
17 } // namespace v8
18
19 namespace node {
20 namespace tracing {
21
22 using v8::platform::tracing::TraceConfig;
23 using v8::platform::tracing::TraceObject;
24
25 class Agent;
26
27 class AsyncTraceWriter {
28 public:
29 virtual ~AsyncTraceWriter() = default;
30 virtual void AppendTraceEvent(TraceObject* trace_event) = 0;
31 virtual void Flush(bool blocking) = 0;
InitializeOnThread(uv_loop_t * loop)32 virtual void InitializeOnThread(uv_loop_t* loop) {}
33 };
34
35 class TracingController : public v8::platform::tracing::TracingController {
36 public:
TracingController()37 TracingController() : v8::platform::tracing::TracingController() {}
38
CurrentTimestampMicroseconds()39 int64_t CurrentTimestampMicroseconds() override {
40 return uv_hrtime() / 1000;
41 }
42 void AddMetadataEvent(
43 const unsigned char* category_group_enabled,
44 const char* name,
45 int num_args,
46 const char** arg_names,
47 const unsigned char* arg_types,
48 const uint64_t* arg_values,
49 std::unique_ptr<v8::ConvertableToTraceFormat>* convertable_values,
50 unsigned int flags);
51 };
52
53 class AgentWriterHandle {
54 public:
55 inline AgentWriterHandle() = default;
~AgentWriterHandle()56 inline ~AgentWriterHandle() { reset(); }
57
58 inline AgentWriterHandle(AgentWriterHandle&& other);
59 inline AgentWriterHandle& operator=(AgentWriterHandle&& other);
empty()60 inline bool empty() const { return agent_ == nullptr; }
61 inline void reset();
62
63 inline void Enable(const std::set<std::string>& categories);
64 inline void Disable(const std::set<std::string>& categories);
65
66 inline bool IsDefaultHandle();
67
agent()68 inline Agent* agent() { return agent_; }
69
70 inline v8::TracingController* GetTracingController();
71
72 AgentWriterHandle(const AgentWriterHandle& other) = delete;
73 AgentWriterHandle& operator=(const AgentWriterHandle& other) = delete;
74
75 private:
AgentWriterHandle(Agent * agent,int id)76 inline AgentWriterHandle(Agent* agent, int id) : agent_(agent), id_(id) {}
77
78 Agent* agent_ = nullptr;
79 int id_;
80
81 friend class Agent;
82 };
83
84 class Agent {
85 public:
86 Agent();
87 ~Agent();
88
GetTracingController()89 TracingController* GetTracingController() {
90 TracingController* controller = tracing_controller_.get();
91 CHECK_NOT_NULL(controller);
92 return controller;
93 }
94
95 enum UseDefaultCategoryMode {
96 kUseDefaultCategories,
97 kIgnoreDefaultCategories
98 };
99
100 // Destroying the handle disconnects the client
101 AgentWriterHandle AddClient(const std::set<std::string>& categories,
102 std::unique_ptr<AsyncTraceWriter> writer,
103 enum UseDefaultCategoryMode mode);
104 // A handle that is only used for managing the default categories
105 // (which can then implicitly be used through using `USE_DEFAULT_CATEGORIES`
106 // when adding a client later).
107 AgentWriterHandle DefaultHandle();
108
109 // Returns a comma-separated list of enabled categories.
110 std::string GetEnabledCategories() const;
111
112 // Writes to all writers registered through AddClient().
113 void AppendTraceEvent(TraceObject* trace_event);
114
115 void AddMetadataEvent(std::unique_ptr<TraceObject> event);
116 // Flushes all writers registered through AddClient().
117 void Flush(bool blocking);
118
119 TraceConfig* CreateTraceConfig() const;
120
121 private:
122 friend class AgentWriterHandle;
123
124 void InitializeWritersOnThread();
125
126 void Start();
127 void StopTracing();
128 void Disconnect(int client);
129
130 void Enable(int id, const std::set<std::string>& categories);
131 void Disable(int id, const std::set<std::string>& categories);
132
133 uv_thread_t thread_;
134 uv_loop_t tracing_loop_;
135
136 bool started_ = false;
137 class ScopedSuspendTracing;
138
139 // Each individual Writer has one id.
140 int next_writer_id_ = 1;
141 enum { kDefaultHandleId = -1 };
142 // These maps store the original arguments to AddClient(), by id.
143 std::unordered_map<int, std::multiset<std::string>> categories_;
144 std::unordered_map<int, std::unique_ptr<AsyncTraceWriter>> writers_;
145 std::unique_ptr<TracingController> tracing_controller_;
146
147 // Variables related to initializing per-event-loop properties of individual
148 // writers, such as libuv handles.
149 Mutex initialize_writer_mutex_;
150 ConditionVariable initialize_writer_condvar_;
151 uv_async_t initialize_writer_async_;
152 std::set<AsyncTraceWriter*> to_be_initialized_;
153
154 Mutex metadata_events_mutex_;
155 std::list<std::unique_ptr<TraceObject>> metadata_events_;
156 };
157
reset()158 void AgentWriterHandle::reset() {
159 if (agent_ != nullptr)
160 agent_->Disconnect(id_);
161 agent_ = nullptr;
162 }
163
164 AgentWriterHandle& AgentWriterHandle::operator=(AgentWriterHandle&& other) {
165 reset();
166 agent_ = other.agent_;
167 id_ = other.id_;
168 other.agent_ = nullptr;
169 return *this;
170 }
171
AgentWriterHandle(AgentWriterHandle && other)172 AgentWriterHandle::AgentWriterHandle(AgentWriterHandle&& other) {
173 *this = std::move(other);
174 }
175
Enable(const std::set<std::string> & categories)176 void AgentWriterHandle::Enable(const std::set<std::string>& categories) {
177 if (agent_ != nullptr) agent_->Enable(id_, categories);
178 }
179
Disable(const std::set<std::string> & categories)180 void AgentWriterHandle::Disable(const std::set<std::string>& categories) {
181 if (agent_ != nullptr) agent_->Disable(id_, categories);
182 }
183
IsDefaultHandle()184 bool AgentWriterHandle::IsDefaultHandle() {
185 return agent_ != nullptr && id_ == Agent::kDefaultHandleId;
186 }
187
GetTracingController()188 inline v8::TracingController* AgentWriterHandle::GetTracingController() {
189 return agent_ != nullptr ? agent_->GetTracingController() : nullptr;
190 }
191
192 } // namespace tracing
193 } // namespace node
194
195 #endif // SRC_TRACING_AGENT_H_
196