traced_value.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // Copyright 2014 The Chromium 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. #ifndef BASE_TRACE_EVENT_TRACED_VALUE_H_
  5. #define BASE_TRACE_EVENT_TRACED_VALUE_H_
  6. #include <stddef.h>
  7. #include <memory>
  8. #include <sstream>
  9. #include <string>
  10. #include <vector>
  11. #include "base/macros.h"
  12. #include "base/pickle.h"
  13. #include "base/strings/string_piece.h"
  14. #include "base/trace_event/trace_event_impl.h"
  15. namespace base {
  16. class Value;
  17. namespace trace_event {
  18. class BASE_EXPORT TracedValue : public ConvertableToTraceFormat {
  19. public:
  20. // TODO(oysteine): |capacity| is not used in any production code. Consider
  21. // removing it.
  22. explicit TracedValue(size_t capacity = 0);
  23. ~TracedValue() override;
  24. void EndDictionary();
  25. void EndArray();
  26. // These methods assume that |name| is a long lived "quoted" string.
  27. void SetInteger(const char* name, int value);
  28. void SetDouble(const char* name, double value);
  29. void SetBoolean(const char* name, bool value);
  30. void SetString(const char* name, base::StringPiece value);
  31. void SetValue(const char* name, TracedValue* value);
  32. void SetPointer(const char* name, void* value);
  33. void BeginDictionary(const char* name);
  34. void BeginArray(const char* name);
  35. // These, instead, can be safely passed a temporary string.
  36. void SetIntegerWithCopiedName(base::StringPiece name, int value);
  37. void SetDoubleWithCopiedName(base::StringPiece name, double value);
  38. void SetBooleanWithCopiedName(base::StringPiece name, bool value);
  39. void SetStringWithCopiedName(base::StringPiece name, base::StringPiece value);
  40. void SetValueWithCopiedName(base::StringPiece name, TracedValue* value);
  41. void SetPointerWithCopiedName(base::StringPiece name, void* value);
  42. void BeginDictionaryWithCopiedName(base::StringPiece name);
  43. void BeginArrayWithCopiedName(base::StringPiece name);
  44. void AppendInteger(int);
  45. void AppendDouble(double);
  46. void AppendBoolean(bool);
  47. void AppendString(base::StringPiece);
  48. void AppendPointer(void*);
  49. void BeginArray();
  50. void BeginDictionary();
  51. // ConvertableToTraceFormat implementation.
  52. void AppendAsTraceFormat(std::string* out) const override;
  53. bool AppendToProto(ProtoAppender* appender) override;
  54. void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
  55. // Helper to auto-close an array. The call to |ArrayScope::~ArrayScope| closes
  56. // the array.
  57. //
  58. // To be constructed using:
  59. // |TracedValue::AppendArrayScoped|
  60. // |TracedValue::BeginArrayScoped|
  61. // |TracedValue::BeginArrayScopedWithCopiedName|
  62. //
  63. // |ArrayScope| holds a |TracedValue| pointer which should remain a valid
  64. // pointer until |ArrayScope::~ArrayScope| is called.
  65. //
  66. // |ArrayScope::~ArrayScope| calls |TracedValue::EndArray| (which checks if
  67. // the held |TracedValue*| is in array state).
  68. //
  69. // Example:
  70. // std::unique_ptr<TracedValue> value(new TracedValue());
  71. // {
  72. // auto scope = value->BeginArrayScoped("array_name");
  73. // value->AppendBoolean(false);
  74. // }
  75. class BASE_EXPORT ArrayScope {
  76. public:
  77. ArrayScope(const ArrayScope&) = delete;
  78. ArrayScope(ArrayScope&&) = default;
  79. ArrayScope& operator=(const ArrayScope&) = delete;
  80. ArrayScope& operator=(ArrayScope&&) = default;
  81. ~ArrayScope();
  82. private:
  83. explicit ArrayScope(TracedValue* value);
  84. TracedValue* value_;
  85. friend class TracedValue;
  86. };
  87. // Call |BeginArray| or |BeginArrayWithCopiedName| with no / the same
  88. // parameter and return an |ArrayScope| holding |this|.
  89. ArrayScope AppendArrayScoped() WARN_UNUSED_RESULT;
  90. ArrayScope BeginArrayScoped(const char* name) WARN_UNUSED_RESULT;
  91. ArrayScope BeginArrayScopedWithCopiedName(base::StringPiece name)
  92. WARN_UNUSED_RESULT;
  93. // Helper to auto-close a dictionary. The call to
  94. // |DictionaryScope::~DictionaryScope| closes the dictionary.
  95. //
  96. // To be constructed using:
  97. // |TracedValue::AppendDictionaryScoped|
  98. // |TracedValue::BeginDictionaryScoped|
  99. // |TracedValue::BeginDictionaryScopedWithCopiedName|
  100. //
  101. // |DictionaryScope| holds a |TracedValue| pointer which should remain a valid
  102. // pointer until |DictionaryScope::~DictionaryScope| is called.
  103. //
  104. // |DictionaryScope::~DictionaryScope| calls |TracedValue::EndDictionary|
  105. // (which checks if the held |TracedValue*| is in dictionary state).
  106. //
  107. // Example:
  108. // std::unique_ptr<TracedValue> value(new TracedValue());
  109. // {
  110. // auto scope = value->BeginDictionaryScoped("dictionary_name");
  111. // value->SetBoolean("my_boolean", false);
  112. // }
  113. class BASE_EXPORT DictionaryScope {
  114. public:
  115. DictionaryScope(const DictionaryScope&) = delete;
  116. DictionaryScope(DictionaryScope&&) = default;
  117. DictionaryScope& operator=(const DictionaryScope&) = delete;
  118. DictionaryScope& operator=(DictionaryScope&&) = default;
  119. ~DictionaryScope();
  120. private:
  121. explicit DictionaryScope(TracedValue* value);
  122. TracedValue* value_;
  123. friend class TracedValue;
  124. };
  125. // Call |BeginDictionary| or |BeginDictionaryWithCopiedName| with no / the
  126. // same parameter and return a |DictionaryScope| holding |this|.
  127. DictionaryScope AppendDictionaryScoped() WARN_UNUSED_RESULT;
  128. DictionaryScope BeginDictionaryScoped(const char* name) WARN_UNUSED_RESULT;
  129. DictionaryScope BeginDictionaryScopedWithCopiedName(base::StringPiece name)
  130. WARN_UNUSED_RESULT;
  131. class BASE_EXPORT Array;
  132. class BASE_EXPORT Dictionary;
  133. class BASE_EXPORT ValueHolder;
  134. class BASE_EXPORT ArrayItem;
  135. class BASE_EXPORT DictionaryItem;
  136. // Helper to enable easier initialization of |TracedValue|. This is intended
  137. // for quick local debugging as there is overhead of creating
  138. // |std::initializer_list| of name-value objects (in the case of containers
  139. // the value is also a |std::initializer_list|). Generally the helper types
  140. // |TracedValue::Dictionary|, |TracedValue::Array|,
  141. // |TracedValue::DictionaryItem|, |TracedValue::ArrayItem| must be valid as
  142. // well as their internals (e.g., |base::StringPiece| data should be valid
  143. // when |TracedValue::Build| is called; |TracedValue::Array| or
  144. // |TracedValue::Dictionary| holds a |std::initializer_list| whose underlying
  145. // array needs to be valid when calling |TracedValue::Build|).
  146. //
  147. // Example:
  148. // auto value = TracedValue::Build({
  149. // {"int_var_name", 42},
  150. // {"double_var_name", 3.14},
  151. // {"string_var_name", "hello world"},
  152. // {"empty_array", TracedValue::Array({})},
  153. // {"dictionary", TracedValue::Dictionary({
  154. // {"my_ptr", static_cast<void*>(my_ptr)},
  155. // {"nested_array", TracedValue::Array({1, false, 0.5})},
  156. // })},
  157. // });
  158. static std::unique_ptr<TracedValue> Build(
  159. const std::initializer_list<DictionaryItem> items);
  160. // An |Array| instance represents an array of |ArrayItem| objects. This is a
  161. // helper to allow initializer list like construction of arrays using
  162. // |TracedValue::Build|.
  163. //
  164. // An instance holds an |std::initializer_list<TracedValue::ArrayItem>| and is
  165. // cheap to copy (copying the initializer_list does not copy the underlying
  166. // objects). The underlying array must exist at the time when
  167. // |TracedValue::Build| is called.
  168. class Array {
  169. public:
  170. // This constructor expects that the initializer_list is valid when
  171. // |TracedValue::Build| is called.
  172. Array(const std::initializer_list<ArrayItem> items);
  173. Array(Array&&);
  174. void WriteToValue(TracedValue* value) const;
  175. private:
  176. std::initializer_list<ArrayItem> items_;
  177. };
  178. // A helper to hold a dictionary. Similar to |TracedValue::Array|.
  179. class Dictionary {
  180. public:
  181. // This constructor expects that the initializer_list is valid when
  182. // |TracedValue::Build| is called.
  183. Dictionary(const std::initializer_list<DictionaryItem> items);
  184. Dictionary(Dictionary&&);
  185. void WriteToValue(TracedValue* value) const;
  186. private:
  187. std::initializer_list<DictionaryItem> items_;
  188. };
  189. // A |ValueHolder| holds a single value or a container (int, double... or an
  190. // |Array| / |Dictionary|). Not to be used outside of the context of
  191. // |TracedValue::Build| (has one parameter implicit constructors).
  192. //
  193. // Base class for |TracedValue::ArrayItem| and |TracedValue::DictionaryItem|.
  194. class ValueHolder {
  195. public:
  196. // Implicit constructors allow constructing |DictionaryItem| without having
  197. // to write |{"name", TracedValue::ValueHolder(1)}|.
  198. ValueHolder(int value); // NOLINT(google-explicit-constructor)
  199. ValueHolder(double value); // NOLINT(google-explicit-constructor)
  200. ValueHolder(bool value); // NOLINT(google-explicit-constructor)
  201. ValueHolder(void* value); // NOLINT(google-explicit-constructor)
  202. // StringPiece's backing storage / const char* pointer needs to remain valid
  203. // until TracedValue::Build is called.
  204. // NOLINTNEXTLINE(google-explicit-constructor)
  205. ValueHolder(base::StringPiece value);
  206. // Create a copy to avoid holding a reference to a non-existing string:
  207. //
  208. // Example:
  209. // TracedValue::Build({{"my_string", std::string("std::string value")}});
  210. // Explanation:
  211. // 1. std::string temporary is passed to the constructor of |ValueHolder|.
  212. // 2. |ValueHolder| is passed to the constructor of |DictionaryItem|.
  213. // 3. |Build| iterates initializer_list of |DictionaryItems|.
  214. //
  215. // If the original |ValueHolder| kept just a reference to the string (or
  216. // a |base::StringPiece|) then |Build| is undefined behaviour, as it is
  217. // passing a reference to an out-of-scope temporary to
  218. // |TracedValue::SetString|.
  219. // NOLINTNEXTLINE(google-explicit-constructor)
  220. ValueHolder(std::string value);
  221. // Define an explicit overload for const char* to resolve the ambiguity
  222. // between the base::StringPiece, void*, and bool constructors for string
  223. // literals.
  224. ValueHolder(const char* value); // NOLINT(google-explicit-constructor)
  225. ValueHolder(Array& value); // NOLINT(google-explicit-constructor)
  226. ValueHolder(Dictionary& value); // NOLINT(google-explicit-constructor)
  227. ValueHolder(ValueHolder&&);
  228. protected:
  229. void WriteToValue(TracedValue* value) const;
  230. void WriteToValue(const char* name, TracedValue* value) const;
  231. private:
  232. union KeptValue {
  233. // Copy is handled by the holder (based on
  234. // |TracedValue::ValueHolder::kept_value_type_|).
  235. int int_value;
  236. double double_value;
  237. bool bool_value;
  238. base::StringPiece string_piece_value;
  239. std::string std_string_value;
  240. void* void_ptr_value;
  241. Array array_value;
  242. Dictionary dictionary_value;
  243. // Default constructor is implicitly deleted because union field has a
  244. // non-trivial default constructor.
  245. KeptValue() {} // NOLINT(modernize-use-equals-default)
  246. ~KeptValue() {} // NOLINT(modernize-use-equals-default)
  247. };
  248. // Reimplementing a subset of C++17 std::variant.
  249. enum class KeptValueType {
  250. kIntType,
  251. kDoubleType,
  252. kBoolType,
  253. kStringPieceType,
  254. kStdStringType,
  255. kVoidPtrType,
  256. kArrayType,
  257. kDictionaryType,
  258. };
  259. KeptValue kept_value_;
  260. KeptValueType kept_value_type_;
  261. };
  262. // |ArrayItem| is a |ValueHolder| which can be used to construct an |Array|.
  263. class ArrayItem : public ValueHolder {
  264. public:
  265. // Implicit constructors allow calling |TracedValue::Array({1, true, 3.14})|
  266. // instead of |TracedValue::Array({TracedValue::ArrayItem(1),
  267. // TracedValue::ArrayItem(true), TracedValue::ArrayItem(3.14)})|.
  268. template <typename T>
  269. // NOLINTNEXTLINE(google-explicit-constructor)
  270. ArrayItem(T value) : ValueHolder(value) {}
  271. void WriteToValue(TracedValue* value) const;
  272. };
  273. // |DictionaryItem| instance represents a single name-value pair.
  274. //
  275. // |name| is assumed to be a long lived "quoted" string.
  276. class DictionaryItem : public ValueHolder {
  277. public:
  278. // These constructors assume that |name| is a long lived "quoted" string.
  279. template <typename T>
  280. DictionaryItem(const char* name, T value)
  281. : ValueHolder(value), name_(name) {}
  282. void WriteToValue(TracedValue* value) const;
  283. private:
  284. const char* name_;
  285. };
  286. // A custom serialization class can be supplied by implementing the
  287. // Writer interface and supplying a factory class to SetWriterFactoryCallback.
  288. // Primarily used by Perfetto to write TracedValues directly into its proto
  289. // format, which lets us do a direct memcpy() in AppendToProto() rather than
  290. // a JSON serialization step in AppendAsTraceFormat.
  291. class BASE_EXPORT Writer {
  292. public:
  293. virtual ~Writer() = default;
  294. virtual void BeginArray() = 0;
  295. virtual void BeginDictionary() = 0;
  296. virtual void EndDictionary() = 0;
  297. virtual void EndArray() = 0;
  298. // These methods assume that |name| is a long lived "quoted" string.
  299. virtual void SetInteger(const char* name, int value) = 0;
  300. virtual void SetDouble(const char* name, double value) = 0;
  301. virtual void SetBoolean(const char* name, bool value) = 0;
  302. virtual void SetString(const char* name, base::StringPiece value) = 0;
  303. virtual void SetValue(const char* name, Writer* value) = 0;
  304. virtual void BeginDictionary(const char* name) = 0;
  305. virtual void BeginArray(const char* name) = 0;
  306. // These, instead, can be safely passed a temporary string.
  307. virtual void SetIntegerWithCopiedName(base::StringPiece name,
  308. int value) = 0;
  309. virtual void SetDoubleWithCopiedName(base::StringPiece name,
  310. double value) = 0;
  311. virtual void SetBooleanWithCopiedName(base::StringPiece name,
  312. bool value) = 0;
  313. virtual void SetStringWithCopiedName(base::StringPiece name,
  314. base::StringPiece value) = 0;
  315. virtual void SetValueWithCopiedName(base::StringPiece name,
  316. Writer* value) = 0;
  317. virtual void BeginDictionaryWithCopiedName(base::StringPiece name) = 0;
  318. virtual void BeginArrayWithCopiedName(base::StringPiece name) = 0;
  319. virtual void AppendInteger(int) = 0;
  320. virtual void AppendDouble(double) = 0;
  321. virtual void AppendBoolean(bool) = 0;
  322. virtual void AppendString(base::StringPiece) = 0;
  323. virtual void AppendAsTraceFormat(std::string* out) const = 0;
  324. virtual bool AppendToProto(ProtoAppender* appender);
  325. virtual void EstimateTraceMemoryOverhead(
  326. TraceEventMemoryOverhead* overhead) = 0;
  327. virtual bool IsPickleWriter() const = 0;
  328. virtual bool IsProtoWriter() const = 0;
  329. };
  330. typedef std::unique_ptr<Writer> (*WriterFactoryCallback)(size_t capacity);
  331. static void SetWriterFactoryCallback(WriterFactoryCallback callback);
  332. protected:
  333. TracedValue(size_t capacity, bool forced_json);
  334. std::unique_ptr<base::Value> ToBaseValue() const;
  335. private:
  336. std::unique_ptr<Writer> writer_;
  337. #ifndef NDEBUG
  338. // In debug builds checks the pairings of {Start,End}{Dictionary,Array}
  339. std::vector<bool> nesting_stack_;
  340. #endif
  341. DISALLOW_COPY_AND_ASSIGN(TracedValue);
  342. };
  343. // TracedValue that is convertable to JSON format. This has lower performance
  344. // than the default TracedValue in production code, and should be used only for
  345. // testing and debugging. Should be avoided in tracing. It's for
  346. // testing/debugging code calling value dumping function designed for tracing,
  347. // like the following:
  348. //
  349. // TracedValueJSON value;
  350. // AsValueInto(&value); // which is designed for tracing.
  351. // return value.ToJSON();
  352. //
  353. // If the code is merely for testing/debugging, base::Value should be used
  354. // instead.
  355. class BASE_EXPORT TracedValueJSON : public TracedValue {
  356. public:
  357. explicit TracedValueJSON(size_t capacity = 0)
  358. : TracedValue(capacity, /*forced_josn*/ true) {}
  359. using TracedValue::ToBaseValue;
  360. // Converts the value into a JSON string without formatting. Suitable for
  361. // printing a simple value or printing a value in a single line context.
  362. std::string ToJSON() const;
  363. // Converts the value into a formatted JSON string, with indentation, spaces
  364. // and new lines for better human readability of complex values.
  365. std::string ToFormattedJSON() const;
  366. };
  367. } // namespace trace_event
  368. } // namespace base
  369. #endif // BASE_TRACE_EVENT_TRACED_VALUE_H_