Chromium Code Reviews| Index: src/libplatform/tracing/trace-writer.cc |
| diff --git a/src/libplatform/tracing/trace-writer.cc b/src/libplatform/tracing/trace-writer.cc |
| index 464b5713fc2b69b6076f43b7cd40ef0ad7e8dd50..22ff9eeb498aad0f8ca5f7bc094e8960625254d8 100644 |
| --- a/src/libplatform/tracing/trace-writer.cc |
| +++ b/src/libplatform/tracing/trace-writer.cc |
| @@ -4,13 +4,85 @@ |
| #include "src/libplatform/tracing/trace-writer.h" |
| +#include <cmath> |
| + |
| #include "src/base/platform/platform.h" |
| +#include "src/tracing/trace-event.h" |
| namespace v8 { |
| namespace platform { |
| namespace tracing { |
| -JSONTraceWriter::JSONTraceWriter(std::ostream& stream) : stream_(stream) { |
| +void EscapeJSONString(Isolate* isolate, const char* str, std::ostream& stream) { |
| + HandleScope handle_scope(isolate); |
| + Local<Context> context = Context::New(isolate); |
| + Context::Scope context_scope(context); |
| + Local<String> v8_str = |
| + String::NewFromUtf8(isolate, str, NewStringType::kNormal) |
| + .ToLocalChecked(); |
| + Local<Object> v8_obj = v8_str->ToObject(context).ToLocalChecked(); |
| + String::Utf8Value escaped_str( |
| + JSON::Stringify(context, v8_obj).ToLocalChecked()); |
| + stream << *escaped_str; |
| +} |
| + |
| +void JSONTraceWriter::AppendTraceValue(uint8_t type, |
| + TraceObject::TraceValue value) { |
| + switch (type) { |
| + case TRACE_VALUE_TYPE_BOOL: |
| + stream_ << (value.as_bool ? "true" : "false"); |
| + break; |
| + case TRACE_VALUE_TYPE_UINT: |
| + stream_ << value.as_uint; |
| + break; |
| + case TRACE_VALUE_TYPE_INT: |
| + stream_ << value.as_int; |
| + break; |
| + case TRACE_VALUE_TYPE_DOUBLE: { |
| + std::string real; |
| + double val = value.as_double; |
| + if (std::isfinite(val)) { |
| + std::ostringstream convert_stream; |
| + convert_stream << val; |
| + real = convert_stream.str(); |
| + // Ensure that the number has a .0 if there's no decimal or 'e'. This |
| + // makes sure that when we read the JSON back, it's interpreted as a |
| + // real rather than an int. |
| + if (real.find('.') == std::string::npos && |
| + real.find('e') == std::string::npos && |
| + real.find('E') == std::string::npos) { |
| + real += ".0"; |
| + } |
| + } else if (std::isnan(val)) { |
| + // The JSON spec doesn't allow NaN and Infinity (since these are |
| + // objects in EcmaScript). Use strings instead. |
| + real = "\"NaN\""; |
| + } else if (val < 0) { |
| + real = "\"-Infinity\""; |
| + } else { |
| + real = "\"Infinity\""; |
| + } |
| + stream_ << real; |
| + break; |
| + } |
| + case TRACE_VALUE_TYPE_POINTER: |
| + // JSON only supports double and int numbers. |
| + // So as not to lose bits from a 64-bit pointer, output as a hex string. |
| + stream_ << "\"" << value.as_pointer << "\""; |
| + break; |
| + case TRACE_VALUE_TYPE_STRING: |
| + case TRACE_VALUE_TYPE_COPY_STRING: |
| + EscapeJSONString(isolate_, value.as_string ? value.as_string : "NULL", |
|
lpy
2016/07/28 21:18:20
Why do you think this should be escaped? Can you g
rskang
2016/07/28 21:25:54
Example, for single string argument:
TRACE_EVENT1(
rskang
2016/07/28 22:45:36
I have removed JSON escaping for a later CL.
|
| + stream_); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| +} |
| + |
| +JSONTraceWriter::JSONTraceWriter(Isolate* isolate, std::ostream& stream) |
| + : isolate_(isolate), stream_(stream) { |
| stream_ << "{\"traceEvents\":["; |
| } |
| @@ -19,37 +91,41 @@ JSONTraceWriter::~JSONTraceWriter() { stream_ << "]}"; } |
| void JSONTraceWriter::AppendTraceEvent(TraceObject* trace_event) { |
| if (append_comma_) stream_ << ","; |
| append_comma_ = true; |
| - if (trace_event->scope() == NULL) { |
| - stream_ << "{\"pid\":" << trace_event->pid() |
| - << ",\"tid\":" << trace_event->tid() |
| - << ",\"ts\":" << trace_event->ts() |
| - << ",\"tts\":" << trace_event->tts() << ",\"ph\":\"" |
| - << trace_event->phase() << "\",\"cat\":\"" |
| - << TracingController::GetCategoryGroupName( |
| - trace_event->category_enabled_flag()) |
| - << "\",\"name\":\"" << trace_event->name() |
| - << "\",\"args\":{},\"dur\":" << trace_event->duration() |
| - << ",\"tdur\":" << trace_event->cpu_duration() << "}"; |
| - } else { |
| - stream_ << "{\"pid\":" << trace_event->pid() |
| - << ",\"tid\":" << trace_event->tid() |
| - << ",\"ts\":" << trace_event->ts() |
| - << ",\"tts\":" << trace_event->tts() << ",\"ph\":\"" |
| - << trace_event->phase() << "\",\"cat\":\"" |
| - << TracingController::GetCategoryGroupName( |
| - trace_event->category_enabled_flag()) |
| - << "\",\"name\":\"" << trace_event->name() << "\",\"scope\":\"" |
| - << trace_event->scope() |
| - << "\",\"args\":{},\"dur\":" << trace_event->duration() |
| - << ",\"tdur\":" << trace_event->cpu_duration() << "}"; |
| + stream_ << "{\"pid\":" << trace_event->pid() |
| + << ",\"tid\":" << trace_event->tid() |
| + << ",\"ts\":" << trace_event->ts() |
| + << ",\"tts\":" << trace_event->tts() << ",\"ph\":\"" |
| + << trace_event->phase() << "\",\"cat\":\"" |
| + << TracingController::GetCategoryGroupName( |
| + trace_event->category_enabled_flag()) |
| + << "\",\"name\":"; |
| + EscapeJSONString(isolate_, trace_event->name(), stream_); |
| + stream_ << ",\"dur\":" << trace_event->duration() |
| + << ",\"tdur\":" << trace_event->cpu_duration(); |
| + if (trace_event->flags() & TRACE_EVENT_FLAG_HAS_ID) { |
| + if (trace_event->scope() != internal::tracing::kGlobalScope) { |
| + stream_ << ",\"scope\":\"" << trace_event->scope() << "\""; |
| + } |
| + stream_ << ",\"id\":" << trace_event->id(); |
| + } |
| + stream_ << ",\"args\":{"; |
| + const char** arg_names = trace_event->arg_names(); |
| + const uint8_t* arg_types = trace_event->arg_types(); |
| + TraceObject::TraceValue* arg_values = trace_event->arg_values(); |
| + for (int i = 0; i < kTraceMaxNumArgs && arg_names[i]; ++i) { |
| + if (i > 0) stream_ << ","; |
| + stream_ << "\"" << arg_names[i] << "\":"; |
| + AppendTraceValue(arg_types[i], arg_values[i]); |
| } |
| + stream_ << "}}"; |
| // TODO(fmeawad): Add support for Flow Events. |
| } |
| void JSONTraceWriter::Flush() {} |
| -TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream) { |
| - return new JSONTraceWriter(stream); |
| +TraceWriter* TraceWriter::CreateJSONTraceWriter(Isolate* isolate, |
| + std::ostream& stream) { |
| + return new JSONTraceWriter(isolate, stream); |
| } |
| } // namespace tracing |