Skip to content

Commit 27d17d4

Browse files
jasnelltargos
authored andcommitted
trace_events: add traced_value.cc/traced_value.h
Port of the V8 internal v8::tracing::TracedValue that allows structured data to be included in the trace event. The v8 class is not exported in the public API so we cannot use it directly. This is a simplified and slightly modified port. This commit only adds the class, it does not add uses of it. Those will come in separate PRs/commits. PR-URL: #21475 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 07cce88 commit 27d17d4

File tree

4 files changed

+391
-0
lines changed

4 files changed

+391
-0
lines changed

node.gyp

+3
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@
377377
'src/tracing/node_trace_buffer.cc',
378378
'src/tracing/node_trace_writer.cc',
379379
'src/tracing/trace_event.cc',
380+
'src/tracing/traced_value.cc',
380381
'src/tty_wrap.cc',
381382
'src/udp_wrap.cc',
382383
'src/util.cc',
@@ -437,6 +438,7 @@
437438
'src/tracing/node_trace_buffer.h',
438439
'src/tracing/node_trace_writer.h',
439440
'src/tracing/trace_event.h',
441+
'src/tracing/traced_value.h',
440442
'src/util.h',
441443
'src/util-inl.h',
442444
'deps/http_parser/http_parser.h',
@@ -950,6 +952,7 @@
950952
'test/cctest/test_node_postmortem_metadata.cc',
951953
'test/cctest/test_environment.cc',
952954
'test/cctest/test_platform.cc',
955+
'test/cctest/test_traced_value.cc',
953956
'test/cctest/test_util.cc',
954957
'test/cctest/test_url.cc'
955958
],

src/tracing/traced_value.cc

+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
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 "tracing/traced_value.h"
6+
7+
#include <math.h>
8+
#include <sstream>
9+
#include <stdio.h>
10+
#include <string>
11+
12+
#if defined(NODE_HAVE_I18N_SUPPORT)
13+
#include <unicode/utf8.h>
14+
#include <unicode/utypes.h>
15+
#endif
16+
17+
#if defined(_STLP_VENDOR_CSTD)
18+
// STLPort doesn't import fpclassify into the std namespace.
19+
#define FPCLASSIFY_NAMESPACE
20+
#else
21+
#define FPCLASSIFY_NAMESPACE std
22+
#endif
23+
24+
namespace node {
25+
namespace tracing {
26+
27+
namespace {
28+
29+
std::string EscapeString(const char* value) {
30+
std::string result;
31+
result += '"';
32+
char number_buffer[10];
33+
#if defined(NODE_HAVE_I18N_SUPPORT)
34+
int32_t len = strlen(value);
35+
int32_t p = 0;
36+
int32_t i = 0;
37+
for (; i < len; p = i) {
38+
UChar32 c;
39+
U8_NEXT_OR_FFFD(value, i, len, c);
40+
switch (c) {
41+
case '\b': result += "\\b"; break;
42+
case '\f': result += "\\f"; break;
43+
case '\n': result += "\\n"; break;
44+
case '\r': result += "\\r"; break;
45+
case '\t': result += "\\t"; break;
46+
case '\\': result += "\\\\"; break;
47+
case '"': result += "\\\""; break;
48+
default:
49+
if (c < 32 || c > 126) {
50+
snprintf(
51+
number_buffer, arraysize(number_buffer), "\\u%04X",
52+
static_cast<uint16_t>(static_cast<uint16_t>(c)));
53+
result += number_buffer;
54+
} else {
55+
result.append(value + p, i - p);
56+
}
57+
}
58+
}
59+
#else
60+
// If we do not have ICU, use a modified version of the non-UTF8 aware
61+
// code from V8's own TracedValue implementation. Note, however, This
62+
// will not produce correctly serialized results for UTF8 values.
63+
while (*value) {
64+
char c = *value++;
65+
switch (c) {
66+
case '\b': result += "\\b"; break;
67+
case '\f': result += "\\f"; break;
68+
case '\n': result += "\\n"; break;
69+
case '\r': result += "\\r"; break;
70+
case '\t': result += "\\t"; break;
71+
case '\\': result += "\\\\"; break;
72+
case '"': result += "\\\""; break;
73+
default:
74+
if (c < '\x20') {
75+
snprintf(
76+
number_buffer, arraysize(number_buffer), "\\u%04X",
77+
static_cast<unsigned>(static_cast<unsigned char>(c)));
78+
result += number_buffer;
79+
} else {
80+
result += c;
81+
}
82+
}
83+
}
84+
#endif // defined(NODE_HAVE_I18N_SUPPORT)
85+
result += '"';
86+
return result;
87+
}
88+
89+
std::string DoubleToCString(double v) {
90+
switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
91+
case FP_NAN: return "\"NaN\"";
92+
case FP_INFINITE: return (v < 0.0 ? "\"-Infinity\"" : "\"Infinity\"");
93+
case FP_ZERO: return "0";
94+
default:
95+
// This is a far less sophisticated version than the one used inside v8.
96+
std::ostringstream stream;
97+
stream.imbue(std::locale("C")); // Ignore locale
98+
stream << v;
99+
return stream.str();
100+
}
101+
}
102+
103+
} // namespace
104+
105+
std::unique_ptr<TracedValue> TracedValue::Create() {
106+
return std::unique_ptr<TracedValue>(new TracedValue(false));
107+
}
108+
109+
std::unique_ptr<TracedValue> TracedValue::CreateArray() {
110+
return std::unique_ptr<TracedValue>(new TracedValue(true));
111+
}
112+
113+
TracedValue::TracedValue(bool root_is_array) :
114+
first_item_(true), root_is_array_(root_is_array) {}
115+
116+
TracedValue::~TracedValue() {}
117+
118+
void TracedValue::SetInteger(const char* name, int value) {
119+
WriteName(name);
120+
data_ += std::to_string(value);
121+
}
122+
123+
void TracedValue::SetDouble(const char* name, double value) {
124+
WriteName(name);
125+
data_ += DoubleToCString(value);
126+
}
127+
128+
void TracedValue::SetBoolean(const char* name, bool value) {
129+
WriteName(name);
130+
data_ += value ? "true" : "false";
131+
}
132+
133+
void TracedValue::SetNull(const char* name) {
134+
WriteName(name);
135+
data_ += "null";
136+
}
137+
138+
void TracedValue::SetString(const char* name, const char* value) {
139+
WriteName(name);
140+
data_ += EscapeString(value);
141+
}
142+
143+
void TracedValue::BeginDictionary(const char* name) {
144+
WriteName(name);
145+
data_ += '{';
146+
first_item_ = true;
147+
}
148+
149+
void TracedValue::BeginArray(const char* name) {
150+
WriteName(name);
151+
data_ += '[';
152+
first_item_ = true;
153+
}
154+
155+
void TracedValue::AppendInteger(int value) {
156+
WriteComma();
157+
data_ += std::to_string(value);
158+
}
159+
160+
void TracedValue::AppendDouble(double value) {
161+
WriteComma();
162+
data_ += DoubleToCString(value);
163+
}
164+
165+
void TracedValue::AppendBoolean(bool value) {
166+
WriteComma();
167+
data_ += value ? "true" : "false";
168+
}
169+
170+
void TracedValue::AppendNull() {
171+
WriteComma();
172+
data_ += "null";
173+
}
174+
175+
void TracedValue::AppendString(const char* value) {
176+
WriteComma();
177+
data_ += EscapeString(value);
178+
}
179+
180+
void TracedValue::BeginDictionary() {
181+
WriteComma();
182+
data_ += '{';
183+
first_item_ = true;
184+
}
185+
186+
void TracedValue::BeginArray() {
187+
WriteComma();
188+
data_ += '[';
189+
first_item_ = true;
190+
}
191+
192+
void TracedValue::EndDictionary() {
193+
data_ += '}';
194+
first_item_ = false;
195+
}
196+
197+
void TracedValue::EndArray() {
198+
data_ += ']';
199+
first_item_ = false;
200+
}
201+
202+
void TracedValue::WriteComma() {
203+
if (first_item_) {
204+
first_item_ = false;
205+
} else {
206+
data_ += ',';
207+
}
208+
}
209+
210+
void TracedValue::WriteName(const char* name) {
211+
WriteComma();
212+
data_ += '"';
213+
data_ += name;
214+
data_ += "\":";
215+
}
216+
217+
void TracedValue::AppendAsTraceFormat(std::string* out) const {
218+
*out += root_is_array_ ? '[' : '{';
219+
*out += data_;
220+
*out += root_is_array_ ? ']' : '}';
221+
}
222+
223+
} // namespace tracing
224+
} // namespace node

src/tracing/traced_value.h

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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+
#ifndef SRC_TRACING_TRACED_VALUE_H_
6+
#define SRC_TRACING_TRACED_VALUE_H_
7+
8+
#include "node_internals.h"
9+
#include "v8.h"
10+
11+
#include <stddef.h>
12+
#include <memory>
13+
#include <string>
14+
15+
namespace node {
16+
namespace tracing {
17+
18+
class TracedValue : public v8::ConvertableToTraceFormat {
19+
public:
20+
~TracedValue() override;
21+
22+
static std::unique_ptr<TracedValue> Create();
23+
static std::unique_ptr<TracedValue> CreateArray();
24+
25+
void EndDictionary();
26+
void EndArray();
27+
28+
// These methods assume that |name| is a long lived "quoted" string.
29+
void SetInteger(const char* name, int value);
30+
void SetDouble(const char* name, double value);
31+
void SetBoolean(const char* name, bool value);
32+
void SetNull(const char* name);
33+
void SetString(const char* name, const char* value);
34+
void SetString(const char* name, const std::string& value) {
35+
SetString(name, value.c_str());
36+
}
37+
void BeginDictionary(const char* name);
38+
void BeginArray(const char* name);
39+
40+
void AppendInteger(int);
41+
void AppendDouble(double);
42+
void AppendBoolean(bool);
43+
void AppendNull();
44+
void AppendString(const char*);
45+
void AppendString(const std::string& value) { AppendString(value.c_str()); }
46+
void BeginArray();
47+
void BeginDictionary();
48+
49+
// ConvertableToTraceFormat implementation.
50+
void AppendAsTraceFormat(std::string* out) const override;
51+
52+
private:
53+
explicit TracedValue(bool root_is_array = false);
54+
55+
void WriteComma();
56+
void WriteName(const char* name);
57+
58+
std::string data_;
59+
bool first_item_;
60+
bool root_is_array_;
61+
62+
DISALLOW_COPY_AND_ASSIGN(TracedValue);
63+
};
64+
65+
} // namespace tracing
66+
} // namespace node
67+
68+
#endif // SRC_TRACING_TRACED_VALUE_H_

0 commit comments

Comments
 (0)