trace_event_impl.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright (c) 2012 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. #include "base/trace_event/trace_event_impl.h"
  5. #include <stddef.h>
  6. #include <sstream>
  7. #include "base/format_macros.h"
  8. #include "base/json/string_escape.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/notreached.h"
  11. #include "base/process/process_handle.h"
  12. #include "base/strings/string_number_conversions.h"
  13. #include "base/strings/string_util.h"
  14. #include "base/strings/stringprintf.h"
  15. #include "base/strings/utf_string_conversions.h"
  16. #include "base/trace_event/trace_event.h"
  17. #include "base/trace_event/trace_log.h"
  18. #include "base/trace_event/traced_value.h"
  19. #include "build/build_config.h"
  20. #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
  21. // Define static storage for trace event categories (see
  22. // PERFETTO_DEFINE_CATEGORIES).
  23. PERFETTO_TRACK_EVENT_STATIC_STORAGE();
  24. namespace perfetto {
  25. namespace legacy {
  26. template <>
  27. perfetto::ThreadTrack ConvertThreadId(const ::base::PlatformThreadId& thread) {
  28. return perfetto::ThreadTrack::ForThread(static_cast<int32_t>(thread));
  29. }
  30. #if BUILDFLAG(IS_WIN)
  31. template <>
  32. perfetto::ThreadTrack ConvertThreadId(const int& thread) {
  33. return perfetto::ThreadTrack::ForThread(static_cast<int32_t>(thread));
  34. }
  35. #endif // BUILDFLAG(IS_WIN)
  36. } // namespace legacy
  37. TraceTimestamp
  38. TraceTimestampTraits<::base::TimeTicks>::ConvertTimestampToTraceTimeNs(
  39. const ::base::TimeTicks& ticks) {
  40. return {TrackEvent::GetTraceClockId(),
  41. static_cast<uint64_t>(ticks.since_origin().InNanoseconds())};
  42. }
  43. namespace internal {
  44. void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
  45. ::base::TimeTicks ticks) {
  46. annotation->set_int_value(ticks.since_origin().InMilliseconds());
  47. }
  48. void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
  49. ::base::Time time) {
  50. annotation->set_int_value(time.since_origin().InMilliseconds());
  51. }
  52. } // namespace internal
  53. } // namespace perfetto
  54. #endif // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
  55. namespace base {
  56. namespace trace_event {
  57. bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) {
  58. return false;
  59. }
  60. // See comment for name TraceEvent::scope_ definition.
  61. static_assert(trace_event_internal::kGlobalScope == nullptr,
  62. "Invalid TraceEvent::scope default initializer value");
  63. TraceEvent::TraceEvent() = default;
  64. TraceEvent::TraceEvent(PlatformThreadId thread_id,
  65. TimeTicks timestamp,
  66. ThreadTicks thread_timestamp,
  67. char phase,
  68. const unsigned char* category_group_enabled,
  69. const char* name,
  70. const char* scope,
  71. unsigned long long id,
  72. unsigned long long bind_id,
  73. TraceArguments* args,
  74. unsigned int flags)
  75. : timestamp_(timestamp),
  76. thread_timestamp_(thread_timestamp),
  77. scope_(scope),
  78. id_(id),
  79. category_group_enabled_(category_group_enabled),
  80. name_(name),
  81. thread_id_(thread_id),
  82. flags_(flags),
  83. bind_id_(bind_id),
  84. phase_(phase) {
  85. InitArgs(args);
  86. }
  87. TraceEvent::~TraceEvent() = default;
  88. TraceEvent::TraceEvent(TraceEvent&& other) noexcept = default;
  89. TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept = default;
  90. void TraceEvent::Reset() {
  91. // Only reset fields that won't be initialized in Reset(int, ...), or that may
  92. // hold references to other objects.
  93. duration_ = TimeDelta::FromInternalValue(-1);
  94. args_.Reset();
  95. parameter_copy_storage_.Reset();
  96. }
  97. void TraceEvent::Reset(PlatformThreadId thread_id,
  98. TimeTicks timestamp,
  99. ThreadTicks thread_timestamp,
  100. char phase,
  101. const unsigned char* category_group_enabled,
  102. const char* name,
  103. const char* scope,
  104. unsigned long long id,
  105. unsigned long long bind_id,
  106. TraceArguments* args,
  107. unsigned int flags) {
  108. Reset();
  109. timestamp_ = timestamp;
  110. thread_timestamp_ = thread_timestamp;
  111. scope_ = scope;
  112. id_ = id;
  113. category_group_enabled_ = category_group_enabled;
  114. name_ = name;
  115. thread_id_ = thread_id;
  116. flags_ = flags;
  117. bind_id_ = bind_id;
  118. phase_ = phase;
  119. InitArgs(args);
  120. }
  121. void TraceEvent::InitArgs(TraceArguments* args) {
  122. if (args)
  123. args_ = std::move(*args);
  124. args_.CopyStringsTo(&parameter_copy_storage_,
  125. !!(flags_ & TRACE_EVENT_FLAG_COPY), &name_, &scope_);
  126. }
  127. void TraceEvent::UpdateDuration(const TimeTicks& now,
  128. const ThreadTicks& thread_now) {
  129. DCHECK_EQ(duration_.ToInternalValue(), -1);
  130. duration_ = now - timestamp_;
  131. // |thread_timestamp_| can be empty if the thread ticks clock wasn't
  132. // initialized when it was recorded.
  133. if (thread_timestamp_ != ThreadTicks())
  134. thread_duration_ = thread_now - thread_timestamp_;
  135. }
  136. void TraceEvent::EstimateTraceMemoryOverhead(
  137. TraceEventMemoryOverhead* overhead) {
  138. overhead->Add(TraceEventMemoryOverhead::kTraceEvent,
  139. parameter_copy_storage_.EstimateTraceMemoryOverhead());
  140. for (size_t i = 0; i < arg_size(); ++i) {
  141. if (arg_type(i) == TRACE_VALUE_TYPE_CONVERTABLE)
  142. arg_value(i).as_convertable->EstimateTraceMemoryOverhead(overhead);
  143. }
  144. }
  145. void TraceEvent::AppendAsJSON(
  146. std::string* out,
  147. const ArgumentFilterPredicate& argument_filter_predicate) const {
  148. int64_t time_int64 = timestamp_.ToInternalValue();
  149. ProcessId process_id;
  150. PlatformThreadId thread_id;
  151. if ((flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) &&
  152. process_id_ != kNullProcessId) {
  153. process_id = process_id_;
  154. thread_id = static_cast<PlatformThreadId>(-1);
  155. } else {
  156. process_id = TraceLog::GetInstance()->process_id();
  157. thread_id = thread_id_;
  158. }
  159. const char* category_group_name =
  160. TraceLog::GetCategoryGroupName(category_group_enabled_);
  161. // Category group checked at category creation time.
  162. DCHECK(!strchr(name_, '"'));
  163. StringAppendF(out,
  164. "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64
  165. ",\"ph\":\"%c\",\"cat\":\"%s\",\"name\":",
  166. static_cast<int>(process_id), static_cast<int>(thread_id),
  167. time_int64, phase_, category_group_name);
  168. EscapeJSONString(name_, true, out);
  169. *out += ",\"args\":";
  170. // Output argument names and values, stop at first NULL argument name.
  171. // TODO(oysteine): The dual predicates here is a bit ugly; if the filtering
  172. // capabilities need to grow even more precise we should rethink this
  173. // approach
  174. ArgumentNameFilterPredicate argument_name_filter_predicate;
  175. bool strip_args =
  176. arg_size() > 0 && arg_name(0) && !argument_filter_predicate.is_null() &&
  177. !argument_filter_predicate.Run(category_group_name, name_,
  178. &argument_name_filter_predicate);
  179. if (strip_args) {
  180. *out += "\"__stripped__\"";
  181. } else {
  182. *out += "{";
  183. for (size_t i = 0; i < arg_size() && arg_name(i); ++i) {
  184. if (i > 0)
  185. *out += ",";
  186. *out += "\"";
  187. *out += arg_name(i);
  188. *out += "\":";
  189. if (argument_name_filter_predicate.is_null() ||
  190. argument_name_filter_predicate.Run(arg_name(i))) {
  191. arg_value(i).AppendAsJSON(arg_type(i), out);
  192. } else {
  193. *out += "\"__stripped__\"";
  194. }
  195. }
  196. *out += "}";
  197. }
  198. if (phase_ == TRACE_EVENT_PHASE_COMPLETE) {
  199. int64_t duration = duration_.ToInternalValue();
  200. if (duration != -1)
  201. StringAppendF(out, ",\"dur\":%" PRId64, duration);
  202. if (!thread_timestamp_.is_null()) {
  203. int64_t thread_duration = thread_duration_.ToInternalValue();
  204. if (thread_duration != -1)
  205. StringAppendF(out, ",\"tdur\":%" PRId64, thread_duration);
  206. }
  207. }
  208. // Output tts if thread_timestamp is valid.
  209. if (!thread_timestamp_.is_null()) {
  210. int64_t thread_time_int64 = thread_timestamp_.ToInternalValue();
  211. StringAppendF(out, ",\"tts\":%" PRId64, thread_time_int64);
  212. }
  213. // Output async tts marker field if flag is set.
  214. if (flags_ & TRACE_EVENT_FLAG_ASYNC_TTS) {
  215. StringAppendF(out, ", \"use_async_tts\":1");
  216. }
  217. // If id_ is set, print it out as a hex string so we don't loose any
  218. // bits (it might be a 64-bit pointer).
  219. unsigned int id_flags_ = flags_ & (TRACE_EVENT_FLAG_HAS_ID |
  220. TRACE_EVENT_FLAG_HAS_LOCAL_ID |
  221. TRACE_EVENT_FLAG_HAS_GLOBAL_ID);
  222. if (id_flags_) {
  223. if (scope_ != trace_event_internal::kGlobalScope)
  224. StringAppendF(out, ",\"scope\":\"%s\"", scope_);
  225. switch (id_flags_) {
  226. case TRACE_EVENT_FLAG_HAS_ID:
  227. StringAppendF(out, ",\"id\":\"0x%" PRIx64 "\"",
  228. static_cast<uint64_t>(id_));
  229. break;
  230. case TRACE_EVENT_FLAG_HAS_LOCAL_ID:
  231. StringAppendF(out, ",\"id2\":{\"local\":\"0x%" PRIx64 "\"}",
  232. static_cast<uint64_t>(id_));
  233. break;
  234. case TRACE_EVENT_FLAG_HAS_GLOBAL_ID:
  235. StringAppendF(out, ",\"id2\":{\"global\":\"0x%" PRIx64 "\"}",
  236. static_cast<uint64_t>(id_));
  237. break;
  238. default:
  239. NOTREACHED() << "More than one of the ID flags are set";
  240. break;
  241. }
  242. }
  243. if (flags_ & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
  244. StringAppendF(out, ",\"bp\":\"e\"");
  245. if ((flags_ & TRACE_EVENT_FLAG_FLOW_OUT) ||
  246. (flags_ & TRACE_EVENT_FLAG_FLOW_IN)) {
  247. StringAppendF(out, ",\"bind_id\":\"0x%" PRIx64 "\"",
  248. static_cast<uint64_t>(bind_id_));
  249. }
  250. if (flags_ & TRACE_EVENT_FLAG_FLOW_IN)
  251. StringAppendF(out, ",\"flow_in\":true");
  252. if (flags_ & TRACE_EVENT_FLAG_FLOW_OUT)
  253. StringAppendF(out, ",\"flow_out\":true");
  254. // Instant events also output their scope.
  255. if (phase_ == TRACE_EVENT_PHASE_INSTANT) {
  256. char scope = '?';
  257. switch (flags_ & TRACE_EVENT_FLAG_SCOPE_MASK) {
  258. case TRACE_EVENT_SCOPE_GLOBAL:
  259. scope = TRACE_EVENT_SCOPE_NAME_GLOBAL;
  260. break;
  261. case TRACE_EVENT_SCOPE_PROCESS:
  262. scope = TRACE_EVENT_SCOPE_NAME_PROCESS;
  263. break;
  264. case TRACE_EVENT_SCOPE_THREAD:
  265. scope = TRACE_EVENT_SCOPE_NAME_THREAD;
  266. break;
  267. }
  268. StringAppendF(out, ",\"s\":\"%c\"", scope);
  269. }
  270. *out += "}";
  271. }
  272. void TraceEvent::AppendPrettyPrinted(std::ostringstream* out) const {
  273. *out << name_ << "[";
  274. *out << TraceLog::GetCategoryGroupName(category_group_enabled_);
  275. *out << "]";
  276. if (arg_size() > 0 && arg_name(0)) {
  277. *out << ", {";
  278. for (size_t i = 0; i < arg_size() && arg_name(i); ++i) {
  279. if (i > 0)
  280. *out << ", ";
  281. *out << arg_name(i) << ":";
  282. std::string value_as_text;
  283. arg_value(i).AppendAsJSON(arg_type(i), &value_as_text);
  284. *out << value_as_text;
  285. }
  286. *out << "}";
  287. }
  288. }
  289. } // namespace trace_event
  290. } // namespace base