v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
trace-writer.cc
Go to the documentation of this file.
1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cmath>
8
12
13#if defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
15#endif
16
17namespace v8 {
18namespace platform {
19namespace tracing {
20
21// Writes the given string to a stream, taking care to escape characters
22// when necessary.
23V8_INLINE static void WriteJSONStringToStream(const char* str,
24 std::ostream& stream) {
25 size_t len = strlen(str);
26 stream << "\"";
27 for (size_t i = 0; i < len; ++i) {
28 // All of the permitted escape sequences in JSON strings, as per
29 // https://mathiasbynens.be/notes/javascript-escapes
30 switch (str[i]) {
31 case '\b':
32 stream << "\\b";
33 break;
34 case '\f':
35 stream << "\\f";
36 break;
37 case '\n':
38 stream << "\\n";
39 break;
40 case '\r':
41 stream << "\\r";
42 break;
43 case '\t':
44 stream << "\\t";
45 break;
46 case '\"':
47 stream << "\\\"";
48 break;
49 case '\\':
50 stream << "\\\\";
51 break;
52 // Note that because we use double quotes for JSON strings,
53 // we don't need to escape single quotes.
54 default:
55 stream << str[i];
56 break;
57 }
58 }
59 stream << "\"";
60}
61
64 switch (type) {
66 stream_ << (value.as_uint ? "true" : "false");
67 break;
69 stream_ << value.as_uint;
70 break;
72 stream_ << value.as_int;
73 break;
75 std::string real;
76 double val = value.as_double;
77 if (std::isfinite(val)) {
78 std::ostringstream convert_stream;
79 convert_stream << val;
80 real = convert_stream.str();
81 // Ensure that the number has a .0 if there's no decimal or 'e'. This
82 // makes sure that when we read the JSON back, it's interpreted as a
83 // real rather than an int.
84 if (real.find('.') == std::string::npos &&
85 real.find('e') == std::string::npos &&
86 real.find('E') == std::string::npos) {
87 real += ".0";
88 }
89 } else if (std::isnan(val)) {
90 // The JSON spec doesn't allow NaN and Infinity (since these are
91 // objects in ECMAScript). Use strings instead.
92 real = "\"NaN\"";
93 } else if (val < 0) {
94 real = "\"-Infinity\"";
95 } else {
96 real = "\"Infinity\"";
97 }
98 stream_ << real;
99 break;
100 }
102 // JSON only supports double and int numbers.
103 // So as not to lose bits from a 64-bit pointer, output as a hex string.
104 stream_ << "\"" << value.as_pointer << "\"";
105 break;
108 if (value.as_string == nullptr) {
109 stream_ << "\"nullptr\"";
110 } else {
111 WriteJSONStringToStream(value.as_string, stream_);
112 }
113 break;
114 default:
115 UNREACHABLE();
116 }
117}
118
120 std::string arg_stringified;
121 value->AppendAsTraceFormat(&arg_stringified);
122 stream_ << arg_stringified;
123}
124
126 : JSONTraceWriter(stream, "traceEvents") {}
127
128JSONTraceWriter::JSONTraceWriter(std::ostream& stream, const std::string& tag)
129 : stream_(stream) {
130 stream_ << "{\"" << tag << "\":[";
131}
132
134
136 if (append_comma_) stream_ << ",";
137 append_comma_ = true;
138 stream_ << "{\"pid\":" << trace_event->pid()
139 << ",\"tid\":" << trace_event->tid()
140 << ",\"ts\":" << trace_event->ts()
141 << ",\"tts\":" << trace_event->tts() << ",\"ph\":\""
142 << trace_event->phase() << "\",\"cat\":\""
144 trace_event->category_enabled_flag())
145 << "\",\"name\":\"" << trace_event->name()
146 << "\",\"dur\":" << trace_event->duration()
147 << ",\"tdur\":" << trace_event->cpu_duration();
148 if (trace_event->flags() &
150 stream_ << ",\"bind_id\":\"0x" << std::hex << trace_event->bind_id() << "\""
151 << std::dec;
152 if (trace_event->flags() & TRACE_EVENT_FLAG_FLOW_IN) {
153 stream_ << ",\"flow_in\":true";
154 }
155 if (trace_event->flags() & TRACE_EVENT_FLAG_FLOW_OUT) {
156 stream_ << ",\"flow_out\":true";
157 }
158 }
159 if (trace_event->flags() & TRACE_EVENT_FLAG_HAS_ID) {
160 if (trace_event->scope() != nullptr) {
161 stream_ << ",\"scope\":\"" << trace_event->scope() << "\"";
162 }
163 // So as not to lose bits from a 64-bit integer, output as a hex string.
164 stream_ << ",\"id\":\"0x" << std::hex << trace_event->id() << "\""
165 << std::dec;
166 }
167 stream_ << ",\"args\":{";
168 const char** arg_names = trace_event->arg_names();
169 const uint8_t* arg_types = trace_event->arg_types();
170 TraceObject::ArgValue* arg_values = trace_event->arg_values();
171 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables =
172 trace_event->arg_convertables();
173 for (int i = 0; i < trace_event->num_args(); ++i) {
174 if (i > 0) stream_ << ",";
175 stream_ << "\"" << arg_names[i] << "\":";
176 if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
177 AppendArgValue(arg_convertables[i].get());
178 } else {
179 AppendArgValue(arg_types[i], arg_values[i]);
180 }
181 }
182 stream_ << "}}";
183 // TODO(fmeawad): Add support for Flow Events.
184}
185
187
189 return new JSONTraceWriter(stream);
190}
191
193 const std::string& tag) {
194 return new JSONTraceWriter(stream, tag);
195}
196
197#if defined(V8_ENABLE_SYSTEM_INSTRUMENTATION)
198SystemInstrumentationTraceWriter::SystemInstrumentationTraceWriter() {
199 recorder_ = std::make_unique<Recorder>();
200}
201
202SystemInstrumentationTraceWriter::~SystemInstrumentationTraceWriter() {
203 recorder_.reset(nullptr);
204}
205
206void SystemInstrumentationTraceWriter::AppendTraceEvent(
207 TraceObject* trace_event) {
208 if (recorder_->IsEnabled()) {
209 recorder_->AddEvent(trace_event);
210 }
211}
212
213void SystemInstrumentationTraceWriter::Flush() {}
214
216 return new SystemInstrumentationTraceWriter();
217}
218#endif
219
220} // namespace tracing
221} // namespace platform
222} // namespace v8
void AppendTraceEvent(TraceObject *trace_event) override
void AppendArgValue(uint8_t type, TraceObject::ArgValue value)
std::unique_ptr< v8::ConvertableToTraceFormat > * arg_convertables()
Definition v8-tracing.h:79
const uint8_t * category_enabled_flag() const
Definition v8-tracing.h:68
static TraceWriter * CreateSystemInstrumentationTraceWriter()
static TraceWriter * CreateJSONTraceWriter(std::ostream &stream)
static const char * GetCategoryGroupName(const uint8_t *category_enabled_flag)
static V8_INLINE void WriteJSONStringToStream(const char *str, std::ostream &stream)
#define UNREACHABLE()
Definition logging.h:67
#define TRACE_VALUE_TYPE_STRING
#define TRACE_VALUE_TYPE_BOOL
#define TRACE_VALUE_TYPE_POINTER
#define TRACE_VALUE_TYPE_COPY_STRING
#define TRACE_VALUE_TYPE_INT
#define TRACE_VALUE_TYPE_UINT
#define TRACE_EVENT_FLAG_HAS_ID
#define TRACE_VALUE_TYPE_DOUBLE
#define TRACE_VALUE_TYPE_CONVERTABLE
#define TRACE_EVENT_FLAG_FLOW_OUT
#define TRACE_EVENT_FLAG_FLOW_IN
#define V8_INLINE
Definition v8config.h:500