GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/inspector/tracing_agent.cc Lines: 85 87 97.7 %
Date: 2019-02-23 22:23:05 Branches: 18 30 60.0 %

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