summaryrefslogtreecommitdiff
path: root/src/inspector/tracing_agent.cc
blob: 92c3597590dabfbea1e6fc49a9cb1ee2e2191256 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "tracing_agent.h"

#include "env-inl.h"
#include "v8.h"

#include <set>
#include <sstream>

namespace node {
namespace inspector {
namespace protocol {

namespace {
using v8::platform::tracing::TraceWriter;

class InspectorTraceWriter : public node::tracing::AsyncTraceWriter {
 public:
  explicit InspectorTraceWriter(NodeTracing::Frontend* frontend)
                                : frontend_(frontend) {}

  void AppendTraceEvent(
      v8::platform::tracing::TraceObject* trace_event) override {
    if (!json_writer_)
      json_writer_.reset(TraceWriter::CreateJSONTraceWriter(stream_, "value"));
    json_writer_->AppendTraceEvent(trace_event);
  }

  void Flush(bool) override {
    if (!json_writer_)
      return;
    json_writer_.reset();
    std::ostringstream result(
        "{\"method\":\"NodeTracing.dataCollected\",\"data\":",
        std::ostringstream::ate);
    result << stream_.str();
    result << "}";
    frontend_->sendRawNotification(result.str());
    stream_.str("");
  }

 private:
  std::unique_ptr<TraceWriter> json_writer_;
  std::ostringstream stream_;
  NodeTracing::Frontend* frontend_;
};
}  // namespace

TracingAgent::TracingAgent(Environment* env)
                           : env_(env) {
}

TracingAgent::~TracingAgent() {
  trace_writer_.reset();
}

void TracingAgent::Wire(UberDispatcher* dispatcher) {
  frontend_.reset(new NodeTracing::Frontend(dispatcher->channel()));
  NodeTracing::Dispatcher::wire(dispatcher, this);
}

DispatchResponse TracingAgent::start(
    std::unique_ptr<protocol::NodeTracing::TraceConfig> traceConfig) {
  if (!trace_writer_.empty()) {
    return DispatchResponse::Error(
        "Call NodeTracing::end to stop tracing before updating the config");
  }

  std::set<std::string> categories_set;
  protocol::Array<std::string>* categories =
      traceConfig->getIncludedCategories();
  for (size_t i = 0; i < categories->length(); i++)
    categories_set.insert(categories->get(i));

  if (categories_set.empty())
    return DispatchResponse::Error("At least one category should be enabled");

  trace_writer_ = env_->tracing_agent()->AddClient(
      categories_set,
      std::unique_ptr<InspectorTraceWriter>(
          new InspectorTraceWriter(frontend_.get())));
  return DispatchResponse::OK();
}

DispatchResponse TracingAgent::stop() {
  trace_writer_.reset();
  frontend_->tracingComplete();
  return DispatchResponse::OK();
}

DispatchResponse TracingAgent::getCategories(
    std::unique_ptr<protocol::Array<String>>* categories) {
  *categories = Array<String>::create();
  categories->get()->addItem("node");
  categories->get()->addItem("node.async");
  categories->get()->addItem("node.bootstrap");
  categories->get()->addItem("node.fs.sync");
  categories->get()->addItem("node.perf");
  categories->get()->addItem("node.perf.usertiming");
  categories->get()->addItem("node.perf.timerify");
  categories->get()->addItem("v8");
  return DispatchResponse::OK();
}

}  // namespace protocol
}  // namespace inspector
}  // namespace node