GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: inspector/tracing_agent.cc Lines: 85 88 96.6 %
Date: 2022-06-12 04:16:28 Branches: 12 18 66.7 %

Line Branch Exec Source
1
#include "tracing_agent.h"
2
#include "main_thread_interface.h"
3
#include "node_internals.h"
4
#include "node_v8_platform-inl.h"
5
#include "v8.h"
6
7
#include <set>
8
#include <sstream>
9
10
namespace node {
11
namespace inspector {
12
namespace protocol {
13
14
namespace {
15
using v8::platform::tracing::TraceWriter;
16
17
class DeletableFrontendWrapper : public Deletable {
18
 public:
19
7018
  explicit DeletableFrontendWrapper(
20
      std::weak_ptr<NodeTracing::Frontend> frontend)
21
7018
      : frontend_(frontend) {}
22
23
  // This should only be called from the main thread, meaning frontend should
24
  // not be destroyed concurrently.
25
4
  NodeTracing::Frontend* get() { return frontend_.lock().get(); }
26
27
 private:
28
  std::weak_ptr<NodeTracing::Frontend> frontend_;
29
};
30
31
class CreateFrontendWrapperRequest : public Request {
32
 public:
33
7018
  CreateFrontendWrapperRequest(int object_id,
34
                               std::weak_ptr<NodeTracing::Frontend> frontend)
35
7018
      : object_id_(object_id) {
36
7018
    frontend_wrapper_ = std::make_unique<DeletableFrontendWrapper>(frontend);
37
7018
  }
38
39
7018
  void Call(MainThreadInterface* thread) override {
40
7018
    thread->AddObject(object_id_, std::move(frontend_wrapper_));
41
7018
  }
42
43
 private:
44
  int object_id_;
45
  std::unique_ptr<DeletableFrontendWrapper> frontend_wrapper_;
46
};
47
48
class DestroyFrontendWrapperRequest : public Request {
49
 public:
50
6507
  explicit DestroyFrontendWrapperRequest(int object_id)
51
6507
      : object_id_(object_id) {}
52
53
932
  void Call(MainThreadInterface* thread) override {
54
932
    thread->RemoveObject(object_id_);
55
932
  }
56
57
 private:
58
  int object_id_;
59
};
60
61
class SendMessageRequest : public Request {
62
 public:
63
4
  explicit SendMessageRequest(int object_id, const std::string& message)
64
4
      : object_id_(object_id), message_(message) {}
65
66
4
  void Call(MainThreadInterface* thread) override {
67
    DeletableFrontendWrapper* frontend_wrapper =
68
        static_cast<DeletableFrontendWrapper*>(
69
4
            thread->GetObjectIfExists(object_id_));
70
4
    if (frontend_wrapper == nullptr) return;
71
4
    auto frontend = frontend_wrapper->get();
72
4
    if (frontend != nullptr) {
73
4
      frontend->sendRawJSONNotification(message_);
74
    }
75
  }
76
77
 private:
78
  int object_id_;
79
  std::string message_;
80
};
81
82
class InspectorTraceWriter : public node::tracing::AsyncTraceWriter {
83
 public:
84
2
  explicit InspectorTraceWriter(int frontend_object_id,
85
                                std::shared_ptr<MainThreadHandle> main_thread)
86
2
      : frontend_object_id_(frontend_object_id), main_thread_(main_thread) {}
87
88
93
  void AppendTraceEvent(
89
      v8::platform::tracing::TraceObject* trace_event) override {
90
93
    if (!json_writer_)
91
4
      json_writer_.reset(TraceWriter::CreateJSONTraceWriter(stream_, "value"));
92
93
    json_writer_->AppendTraceEvent(trace_event);
93
93
  }
94
95
4
  void Flush(bool) override {
96
4
    if (!json_writer_)
97
      return;
98
4
    json_writer_.reset();
99
    std::ostringstream result(
100
        "{\"method\":\"NodeTracing.dataCollected\",\"params\":",
101
8
        std::ostringstream::ate);
102
4
    result << stream_.str();
103
4
    result << "}";
104
8
    main_thread_->Post(std::make_unique<SendMessageRequest>(frontend_object_id_,
105
8
                                                            result.str()));
106
4
    stream_.str("");
107
  }
108
109
 private:
110
  std::unique_ptr<TraceWriter> json_writer_;
111
  std::ostringstream stream_;
112
  int frontend_object_id_;
113
  std::shared_ptr<MainThreadHandle> main_thread_;
114
};
115
}  // namespace
116
117
7018
TracingAgent::TracingAgent(Environment* env,
118
7018
                           std::shared_ptr<MainThreadHandle> main_thread)
119
7018
    : env_(env), main_thread_(main_thread) {}
120
121
26028
TracingAgent::~TracingAgent() {
122
13014
  trace_writer_.reset();
123
26028
  main_thread_->Post(
124
26028
      std::make_unique<DestroyFrontendWrapperRequest>(frontend_object_id_));
125
26028
}
126
127
7018
void TracingAgent::Wire(UberDispatcher* dispatcher) {
128
  // Note that frontend is still owned by TracingAgent
129
7018
  frontend_ = std::make_shared<NodeTracing::Frontend>(dispatcher->channel());
130
7018
  frontend_object_id_ = main_thread_->newObjectId();
131
14036
  main_thread_->Post(std::make_unique<CreateFrontendWrapperRequest>(
132
7018
      frontend_object_id_, frontend_));
133
7018
  NodeTracing::Dispatcher::wire(dispatcher, this);
134
7018
}
135
136
3
DispatchResponse TracingAgent::start(
137
    std::unique_ptr<protocol::NodeTracing::TraceConfig> traceConfig) {
138
3
  if (!trace_writer_.empty()) {
139
    return DispatchResponse::Error(
140
        "Call NodeTracing::end to stop tracing before updating the config");
141
  }
142
3
  if (!env_->owns_process_state()) {
143
    return DispatchResponse::Error(
144
1
        "Tracing properties can only be changed through main thread sessions");
145
  }
146
147
4
  std::set<std::string> categories_set;
148
  protocol::Array<std::string>* categories =
149
2
      traceConfig->getIncludedCategories();
150
4
  for (size_t i = 0; i < categories->length(); i++)
151
2
    categories_set.insert(categories->get(i));
152
153
2
  if (categories_set.empty())
154
    return DispatchResponse::Error("At least one category should be enabled");
155
156
2
  tracing::AgentWriterHandle* writer = GetTracingAgentWriter();
157
2
  if (writer != nullptr) {
158
    trace_writer_ =
159
6
        writer->agent()->AddClient(categories_set,
160
2
                                   std::make_unique<InspectorTraceWriter>(
161
2
                                       frontend_object_id_, main_thread_),
162
2
                                   tracing::Agent::kIgnoreDefaultCategories);
163
  }
164
2
  return DispatchResponse::OK();
165
}
166
167
2
DispatchResponse TracingAgent::stop() {
168
2
  trace_writer_.reset();
169
2
  frontend_->tracingComplete();
170
2
  return DispatchResponse::OK();
171
}
172
173
1
DispatchResponse TracingAgent::getCategories(
174
    std::unique_ptr<protocol::Array<String>>* categories) {
175
1
  *categories = Array<String>::create();
176
1
  categories->get()->addItem("node");
177
1
  categories->get()->addItem("node.async");
178
1
  categories->get()->addItem("node.bootstrap");
179
1
  categories->get()->addItem("node.fs.sync");
180
1
  categories->get()->addItem("node.perf");
181
1
  categories->get()->addItem("node.perf.usertiming");
182
1
  categories->get()->addItem("node.perf.timerify");
183
1
  categories->get()->addItem("v8");
184
1
  return DispatchResponse::OK();
185
}
186
187
}  // namespace protocol
188
}  // namespace inspector
189
}  // namespace node