LCOV - code coverage report
Current view: top level - src/libplatform/tracing - trace-writer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 68 77 88.3 %
Date: 2019-04-18 Functions: 9 10 90.0 %

          Line data    Source code
       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             : 
       5             : #include "src/libplatform/tracing/trace-writer.h"
       6             : 
       7             : #include <cmath>
       8             : 
       9             : #include "base/trace_event/common/trace_event_common.h"
      10             : #include "include/v8-platform.h"
      11             : #include "src/base/platform/platform.h"
      12             : 
      13             : namespace v8 {
      14             : namespace platform {
      15             : namespace tracing {
      16             : 
      17             : // Writes the given string to a stream, taking care to escape characters
      18             : // when necessary.
      19             : V8_INLINE static void WriteJSONStringToStream(const char* str,
      20             :                                               std::ostream& stream) {
      21          35 :   size_t len = strlen(str);
      22          35 :   stream << "\"";
      23         355 :   for (size_t i = 0; i < len; ++i) {
      24             :     // All of the permitted escape sequences in JSON strings, as per
      25             :     // https://mathiasbynens.be/notes/javascript-escapes
      26         160 :     switch (str[i]) {
      27             :       case '\b':
      28           0 :         stream << "\\b";
      29             :         break;
      30             :       case '\f':
      31           0 :         stream << "\\f";
      32             :         break;
      33             :       case '\n':
      34           0 :         stream << "\\n";
      35             :         break;
      36             :       case '\r':
      37           0 :         stream << "\\r";
      38             :         break;
      39             :       case '\t':
      40           0 :         stream << "\\t";
      41             :         break;
      42             :       case '\"':
      43          30 :         stream << "\\\"";
      44             :         break;
      45             :       case '\\':
      46           0 :         stream << "\\\\";
      47             :         break;
      48             :       // Note that because we use double quotes for JSON strings,
      49             :       // we don't need to escape single quotes.
      50             :       default:
      51             :         stream << str[i];
      52             :         break;
      53             :     }
      54             :   }
      55          35 :   stream << "\"";
      56             : }
      57             : 
      58         120 : void JSONTraceWriter::AppendArgValue(uint8_t type,
      59             :                                      TraceObject::ArgValue value) {
      60         120 :   switch (type) {
      61             :     case TRACE_VALUE_TYPE_BOOL:
      62          10 :       stream_ << (value.as_bool ? "true" : "false");
      63          10 :       break;
      64             :     case TRACE_VALUE_TYPE_UINT:
      65          25 :       stream_ << value.as_uint;
      66             :       break;
      67             :     case TRACE_VALUE_TYPE_INT:
      68          20 :       stream_ << value.as_int;
      69             :       break;
      70             :     case TRACE_VALUE_TYPE_DOUBLE: {
      71             :       std::string real;
      72          25 :       double val = value.as_double;
      73          25 :       if (std::isfinite(val)) {
      74          20 :         std::ostringstream convert_stream;
      75             :         convert_stream << val;
      76          10 :         real = convert_stream.str();
      77             :         // Ensure that the number has a .0 if there's no decimal or 'e'.  This
      78             :         // makes sure that when we read the JSON back, it's interpreted as a
      79             :         // real rather than an int.
      80          30 :         if (real.find('.') == std::string::npos &&
      81          15 :             real.find('e') == std::string::npos &&
      82           5 :             real.find('E') == std::string::npos) {
      83             :           real += ".0";
      84             :         }
      85          15 :       } else if (std::isnan(val)) {
      86             :         // The JSON spec doesn't allow NaN and Infinity (since these are
      87             :         // objects in EcmaScript).  Use strings instead.
      88             :         real = "\"NaN\"";
      89          10 :       } else if (val < 0) {
      90             :         real = "\"-Infinity\"";
      91             :       } else {
      92             :         real = "\"Infinity\"";
      93             :       }
      94          25 :       stream_ << real;
      95             :       break;
      96             :     }
      97             :     case TRACE_VALUE_TYPE_POINTER:
      98             :       // JSON only supports double and int numbers.
      99             :       // So as not to lose bits from a 64-bit pointer, output as a hex string.
     100          10 :       stream_ << "\"" << value.as_pointer << "\"";
     101           5 :       break;
     102             :     case TRACE_VALUE_TYPE_STRING:
     103             :     case TRACE_VALUE_TYPE_COPY_STRING:
     104          35 :       if (value.as_string == nullptr) {
     105           0 :         stream_ << "\"nullptr\"";
     106             :       } else {
     107          35 :         WriteJSONStringToStream(value.as_string, stream_);
     108             :       }
     109             :       break;
     110             :     default:
     111           0 :       UNREACHABLE();
     112             :       break;
     113             :   }
     114         120 : }
     115             : 
     116          20 : void JSONTraceWriter::AppendArgValue(ConvertableToTraceFormat* value) {
     117             :   std::string arg_stringified;
     118          20 :   value->AppendAsTraceFormat(&arg_stringified);
     119          20 :   stream_ << arg_stringified;
     120          20 : }
     121             : 
     122          11 : JSONTraceWriter::JSONTraceWriter(std::ostream& stream)
     123          22 :     : JSONTraceWriter(stream, "traceEvents") {}
     124             : 
     125          16 : JSONTraceWriter::JSONTraceWriter(std::ostream& stream, const std::string& tag)
     126          16 :     : stream_(stream) {
     127          16 :   stream_ << "{\"" << tag << "\":[";
     128          16 : }
     129             : 
     130          32 : JSONTraceWriter::~JSONTraceWriter() { stream_ << "]}"; }
     131             : 
     132         150 : void JSONTraceWriter::AppendTraceEvent(TraceObject* trace_event) {
     133         150 :   if (append_comma_) stream_ << ",";
     134         150 :   append_comma_ = true;
     135         300 :   stream_ << "{\"pid\":" << trace_event->pid()
     136         150 :           << ",\"tid\":" << trace_event->tid()
     137             :           << ",\"ts\":" << trace_event->ts()
     138             :           << ",\"tts\":" << trace_event->tts() << ",\"ph\":\""
     139             :           << trace_event->phase() << "\",\"cat\":\""
     140             :           << TracingController::GetCategoryGroupName(
     141         300 :                  trace_event->category_enabled_flag())
     142         150 :           << "\",\"name\":\"" << trace_event->name()
     143             :           << "\",\"dur\":" << trace_event->duration()
     144             :           << ",\"tdur\":" << trace_event->cpu_duration();
     145         150 :   if (trace_event->flags() &
     146             :       (TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT)) {
     147          10 :     stream_ << ",\"bind_id\":\"0x" << std::hex << trace_event->bind_id() << "\""
     148             :             << std::dec;
     149          10 :     if (trace_event->flags() & TRACE_EVENT_FLAG_FLOW_IN) {
     150          10 :       stream_ << ",\"flow_in\":true";
     151             :     }
     152          10 :     if (trace_event->flags() & TRACE_EVENT_FLAG_FLOW_OUT) {
     153          10 :       stream_ << ",\"flow_out\":true";
     154             :     }
     155             :   }
     156         150 :   if (trace_event->flags() & TRACE_EVENT_FLAG_HAS_ID) {
     157          10 :     if (trace_event->scope() != nullptr) {
     158           0 :       stream_ << ",\"scope\":\"" << trace_event->scope() << "\"";
     159             :     }
     160             :     // So as not to lose bits from a 64-bit integer, output as a hex string.
     161          10 :     stream_ << ",\"id\":\"0x" << std::hex << trace_event->id() << "\""
     162             :             << std::dec;
     163             :   }
     164         150 :   stream_ << ",\"args\":{";
     165             :   const char** arg_names = trace_event->arg_names();
     166             :   const uint8_t* arg_types = trace_event->arg_types();
     167             :   TraceObject::ArgValue* arg_values = trace_event->arg_values();
     168             :   std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables =
     169             :       trace_event->arg_convertables();
     170         430 :   for (int i = 0; i < trace_event->num_args(); ++i) {
     171         140 :     if (i > 0) stream_ << ",";
     172         280 :     stream_ << "\"" << arg_names[i] << "\":";
     173         140 :     if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
     174          40 :       AppendArgValue(arg_convertables[i].get());
     175             :     } else {
     176         120 :       AppendArgValue(arg_types[i], arg_values[i]);
     177             :     }
     178             :   }
     179         150 :   stream_ << "}}";
     180             :   // TODO(fmeawad): Add support for Flow Events.
     181         150 : }
     182             : 
     183          16 : void JSONTraceWriter::Flush() {}
     184             : 
     185          11 : TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream) {
     186          11 :   return new JSONTraceWriter(stream);
     187             : }
     188             : 
     189           5 : TraceWriter* TraceWriter::CreateJSONTraceWriter(std::ostream& stream,
     190             :                                                 const std::string& tag) {
     191           5 :   return new JSONTraceWriter(stream, tag);
     192             : }
     193             : 
     194             : }  // namespace tracing
     195             : }  // namespace platform
     196             : }  // namespace v8

Generated by: LCOV version 1.10