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: 29 86 33.7 %
Date: 2019-02-01 22:03:38 Branches: 4 30 13.3 %

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