GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tracing/agent.h Lines: 35 35 100.0 %
Date: 2022-09-11 04:22:34 Branches: 10 14 71.4 %

Line Branch Exec Source
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
178
  virtual ~AsyncTraceWriter() = default;
30
  virtual void AppendTraceEvent(TraceObject* trace_event) = 0;
31
  virtual void Flush(bool blocking) = 0;
32
2
  virtual void InitializeOnThread(uv_loop_t* loop) {}
33
};
34
35
class TracingController : public v8::platform::tracing::TracingController {
36
 public:
37
5521
  TracingController() : v8::platform::tracing::TracingController() {}
38
39
1844
  int64_t CurrentTimestampMicroseconds() override {
40
1844
    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
12840
  inline AgentWriterHandle() = default;
56
17874
  inline ~AgentWriterHandle() { reset(); }
57
58
  inline AgentWriterHandle(AgentWriterHandle&& other);
59
  inline AgentWriterHandle& operator=(AgentWriterHandle&& other);
60
3
  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
68
19
  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:
76
5609
  inline AgentWriterHandle(Agent* agent, int id) : agent_(agent), id_(id) {}
77
78
  Agent* agent_ = nullptr;
79
  int id_ = 0;
80
81
  friend class Agent;
82
};
83
84
class Agent {
85
 public:
86
  Agent();
87
  ~Agent();
88
89
23737
  TracingController* GetTracingController() {
90
23737
    TracingController* controller = tracing_controller_.get();
91
23737
    CHECK_NOT_NULL(controller);
92
23737
    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
158
35673
void AgentWriterHandle::reset() {
159
35673
  if (agent_ != nullptr)
160
5608
    agent_->Disconnect(id_);
161
35673
  agent_ = nullptr;
162
35673
}
163
164
5609
AgentWriterHandle& AgentWriterHandle::operator=(AgentWriterHandle&& other) {
165
5609
  reset();
166
5609
  agent_ = other.agent_;
167
5609
  id_ = other.id_;
168
5609
  other.agent_ = nullptr;
169
5609
  return *this;
170
}
171
172
AgentWriterHandle::AgentWriterHandle(AgentWriterHandle&& other) {
173
  *this = std::move(other);
174
}
175
176
20
void AgentWriterHandle::Enable(const std::set<std::string>& categories) {
177
20
  if (agent_ != nullptr) agent_->Enable(id_, categories);
178
20
}
179
180
6
void AgentWriterHandle::Disable(const std::set<std::string>& categories) {
181
6
  if (agent_ != nullptr) agent_->Disable(id_, categories);
182
6
}
183
184
105
bool AgentWriterHandle::IsDefaultHandle() {
185

105
  return agent_ != nullptr && id_ == Agent::kDefaultHandleId;
186
}
187
188
12011
inline v8::TracingController* AgentWriterHandle::GetTracingController() {
189
12011
  return agent_ != nullptr ? agent_->GetTracingController() : nullptr;
190
}
191
192
}  // namespace tracing
193
}  // namespace node
194
195
#endif  // SRC_TRACING_AGENT_H_