traced_value.h 16 KB

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