trace_event_android.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 <fcntl.h>
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include "base/bind.h"
  9. #include "base/format_macros.h"
  10. #include "base/logging.h"
  11. #include "base/posix/eintr_wrapper.h"
  12. #include "base/strings/stringprintf.h"
  13. #include "base/synchronization/waitable_event.h"
  14. #include "base/threading/thread.h"
  15. #include "base/trace_event/trace_event.h"
  16. #include "third_party/abseil-cpp/absl/types/optional.h"
  17. namespace base {
  18. namespace trace_event {
  19. namespace {
  20. int g_atrace_fd = -1;
  21. const char kATraceMarkerFile[] = "/sys/kernel/tracing/trace_marker";
  22. const char kLegacyATraceMarkerFile[] = "/sys/kernel/debug/tracing/trace_marker";
  23. void WriteToATrace(int fd, const char* buffer, size_t size) {
  24. size_t total_written = 0;
  25. while (total_written < size) {
  26. ssize_t written = HANDLE_EINTR(write(
  27. fd, buffer + total_written, size - total_written));
  28. if (written <= 0)
  29. break;
  30. total_written += static_cast<size_t>(written);
  31. }
  32. // Tracing might have been disabled before we were notified about it, which
  33. // triggers EBADF. Since enabling and disabling atrace is racy, ignore the
  34. // error in that case to avoid logging an error for every trace event.
  35. if (total_written < size && errno != EBADF) {
  36. PLOG(WARNING) << "Failed to write buffer '" << std::string(buffer, size)
  37. << "' to trace_marker";
  38. }
  39. }
  40. void WriteEvent(char phase,
  41. const char* category_group,
  42. const char* name,
  43. unsigned long long id,
  44. const TraceArguments& args,
  45. unsigned int flags) {
  46. std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name);
  47. if (flags & TRACE_EVENT_FLAG_HAS_ID)
  48. StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id));
  49. out += '|';
  50. const char* const* arg_names = args.names();
  51. for (size_t i = 0; i < args.size() && arg_names[i]; ++i) {
  52. if (i)
  53. out += ';';
  54. out += arg_names[i];
  55. out += '=';
  56. size_t value_start = out.length();
  57. args.values()[i].AppendAsJSON(args.types()[i], &out);
  58. // Remove the quotes which may confuse the atrace script.
  59. ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
  60. ReplaceSubstringsAfterOffset(&out, value_start, "\"", "");
  61. // Replace chars used for separators with similar chars in the value.
  62. std::replace(out.begin() + static_cast<ptrdiff_t>(value_start), out.end(),
  63. ';', ',');
  64. std::replace(out.begin() + static_cast<ptrdiff_t>(value_start), out.end(),
  65. '|', '!');
  66. }
  67. out += '|';
  68. out += category_group;
  69. WriteToATrace(g_atrace_fd, out.c_str(), out.size());
  70. }
  71. int OpenATraceMarkerFile(int mode) {
  72. int fd = HANDLE_EINTR(open(kATraceMarkerFile, mode));
  73. if (fd == -1)
  74. fd = HANDLE_EINTR(open(kLegacyATraceMarkerFile, mode));
  75. if (fd == -1) {
  76. PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile << " or "
  77. << kLegacyATraceMarkerFile;
  78. return -1;
  79. }
  80. return fd;
  81. }
  82. } // namespace
  83. // These functions support Android systrace.py when 'webview' category is
  84. // traced. With the new adb_profile_chrome, we may have two phases:
  85. // - before WebView is ready for combined tracing, we can use adb_profile_chrome
  86. // to trace android categories other than 'webview' and chromium categories.
  87. // In this way we can avoid the conflict between StartATrace/StopATrace and
  88. // the intents.
  89. // - TODO(wangxianzhu): after WebView is ready for combined tracing, remove
  90. // StartATrace, StopATrace and SendToATrace, and perhaps send Java traces
  91. // directly to atrace in trace_event_binding.cc.
  92. void TraceLog::StartATrace(const std::string& category_filter) {
  93. if (g_atrace_fd != -1)
  94. return;
  95. g_atrace_fd = OpenATraceMarkerFile(O_WRONLY);
  96. if (g_atrace_fd == -1)
  97. return;
  98. TraceConfig trace_config(category_filter);
  99. trace_config.SetTraceRecordMode(RECORD_CONTINUOUSLY);
  100. SetEnabled(trace_config, TraceLog::RECORDING_MODE);
  101. }
  102. void TraceLog::StopATrace() {
  103. if (g_atrace_fd != -1) {
  104. close(g_atrace_fd);
  105. g_atrace_fd = -1;
  106. }
  107. SetDisabled();
  108. }
  109. void TraceEvent::SendToATrace() {
  110. if (g_atrace_fd == -1)
  111. return;
  112. const char* category_group =
  113. TraceLog::GetCategoryGroupName(category_group_enabled_);
  114. switch (phase_) {
  115. case TRACE_EVENT_PHASE_BEGIN:
  116. WriteEvent('B', category_group, name_, id_, args_, flags_);
  117. break;
  118. case TRACE_EVENT_PHASE_COMPLETE:
  119. WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', category_group,
  120. name_, id_, args_, flags_);
  121. break;
  122. case TRACE_EVENT_PHASE_END:
  123. // Though a single 'E' is enough, here append pid, name and
  124. // category_group etc. So that unpaired events can be found easily.
  125. WriteEvent('E', category_group, name_, id_, args_, flags_);
  126. break;
  127. case TRACE_EVENT_PHASE_INSTANT:
  128. // Simulate an instance event with a pair of begin/end events.
  129. WriteEvent('B', category_group, name_, id_, args_, flags_);
  130. WriteToATrace(g_atrace_fd, "E", 1);
  131. break;
  132. case TRACE_EVENT_PHASE_COUNTER:
  133. for (size_t i = 0; i < arg_size() && arg_name(i); ++i) {
  134. DCHECK(arg_type(i) == TRACE_VALUE_TYPE_INT);
  135. std::string out =
  136. base::StringPrintf("C|%d|%s-%s", getpid(), name_, arg_name(i));
  137. if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
  138. StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_));
  139. StringAppendF(&out, "|%d|%s", static_cast<int>(arg_value(i).as_int),
  140. category_group);
  141. WriteToATrace(g_atrace_fd, out.c_str(), out.size());
  142. }
  143. break;
  144. default:
  145. // Do nothing.
  146. break;
  147. }
  148. }
  149. void TraceLog::AddClockSyncMetadataEvent() {
  150. int atrace_fd = OpenATraceMarkerFile(O_WRONLY | O_APPEND);
  151. if (atrace_fd == -1)
  152. return;
  153. // Android's kernel trace system has a trace_marker feature: this is a file on
  154. // debugfs that takes the written data and pushes it onto the trace
  155. // buffer. So, to establish clock sync, we write our monotonic clock into that
  156. // trace buffer.
  157. double now_in_seconds = (TRACE_TIME_TICKS_NOW() - TimeTicks()).InSecondsF();
  158. std::string marker = StringPrintf(
  159. "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
  160. WriteToATrace(atrace_fd, marker.c_str(), marker.size());
  161. close(atrace_fd);
  162. }
  163. void TraceLog::SetupATraceStartupTrace(const std::string& category_filter) {
  164. atrace_startup_config_ = TraceConfig(category_filter);
  165. }
  166. absl::optional<TraceConfig> TraceLog::TakeATraceStartupConfig() {
  167. return std::move(atrace_startup_config_);
  168. }
  169. } // namespace trace_event
  170. } // namespace base