trace_event_analyzer.cc 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  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/test/trace_event_analyzer.h"
  5. #include <math.h>
  6. #include <algorithm>
  7. #include <set>
  8. #include "base/bind.h"
  9. #include "base/json/json_reader.h"
  10. #include "base/logging.h"
  11. #include "base/memory/ptr_util.h"
  12. #include "base/memory/ref_counted_memory.h"
  13. #include "base/ranges/algorithm.h"
  14. #include "base/run_loop.h"
  15. #include "base/strings/pattern.h"
  16. #include "base/trace_event/trace_buffer.h"
  17. #include "base/trace_event/trace_config.h"
  18. #include "base/trace_event/trace_log.h"
  19. #include "base/values.h"
  20. #include "third_party/abseil-cpp/absl/types/optional.h"
  21. namespace {
  22. void OnTraceDataCollected(base::OnceClosure quit_closure,
  23. base::trace_event::TraceResultBuffer* buffer,
  24. const scoped_refptr<base::RefCountedString>& json,
  25. bool has_more_events) {
  26. buffer->AddFragment(json->data());
  27. if (!has_more_events)
  28. std::move(quit_closure).Run();
  29. }
  30. } // namespace
  31. namespace trace_analyzer {
  32. // TraceEvent
  33. TraceEvent::TraceEvent() : thread(0, 0) {}
  34. TraceEvent::TraceEvent(TraceEvent&& other) = default;
  35. TraceEvent::~TraceEvent() = default;
  36. TraceEvent& TraceEvent::operator=(TraceEvent&& rhs) = default;
  37. bool TraceEvent::SetFromJSON(const base::Value* event_value) {
  38. if (!event_value->is_dict()) {
  39. LOG(ERROR) << "Value must be Type::DICTIONARY";
  40. return false;
  41. }
  42. const base::Value::Dict& event_dict = event_value->GetDict();
  43. const std::string* maybe_phase = event_dict.FindString("ph");
  44. if (!maybe_phase) {
  45. LOG(ERROR) << "ph is missing from TraceEvent JSON";
  46. return false;
  47. }
  48. phase = *maybe_phase->data();
  49. bool may_have_duration = (phase == TRACE_EVENT_PHASE_COMPLETE);
  50. bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA);
  51. bool require_id = (phase == TRACE_EVENT_PHASE_ASYNC_BEGIN ||
  52. phase == TRACE_EVENT_PHASE_ASYNC_STEP_INTO ||
  53. phase == TRACE_EVENT_PHASE_ASYNC_STEP_PAST ||
  54. phase == TRACE_EVENT_PHASE_MEMORY_DUMP ||
  55. phase == TRACE_EVENT_PHASE_CREATE_OBJECT ||
  56. phase == TRACE_EVENT_PHASE_DELETE_OBJECT ||
  57. phase == TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ||
  58. phase == TRACE_EVENT_PHASE_ASYNC_END);
  59. if (require_origin) {
  60. absl::optional<int> maybe_process_id = event_dict.FindInt("pid");
  61. if (!maybe_process_id) {
  62. LOG(ERROR) << "pid is missing from TraceEvent JSON";
  63. return false;
  64. }
  65. thread.process_id = *maybe_process_id;
  66. absl::optional<int> maybe_thread_id = event_dict.FindInt("tid");
  67. if (!maybe_thread_id) {
  68. LOG(ERROR) << "tid is missing from TraceEvent JSON";
  69. return false;
  70. }
  71. thread.thread_id = *maybe_thread_id;
  72. absl::optional<double> maybe_timestamp = event_dict.FindDouble("ts");
  73. if (!maybe_timestamp) {
  74. LOG(ERROR) << "ts is missing from TraceEvent JSON";
  75. return false;
  76. }
  77. timestamp = *maybe_timestamp;
  78. }
  79. if (may_have_duration) {
  80. absl::optional<double> maybe_duration = event_dict.FindDouble("dur");
  81. if (maybe_duration)
  82. duration = *maybe_duration;
  83. }
  84. const std::string* maybe_category = event_dict.FindString("cat");
  85. if (!maybe_category) {
  86. LOG(ERROR) << "cat is missing from TraceEvent JSON";
  87. return false;
  88. }
  89. category = *maybe_category;
  90. const std::string* maybe_name = event_dict.FindString("name");
  91. if (!maybe_name) {
  92. LOG(ERROR) << "name is missing from TraceEvent JSON";
  93. return false;
  94. }
  95. name = *maybe_name;
  96. const base::Value::Dict* maybe_args = event_dict.FindDict("args");
  97. if (!maybe_args) {
  98. // If argument filter is enabled, the arguments field contains a string
  99. // value.
  100. const std::string* maybe_stripped_args = event_dict.FindString("args");
  101. if (!maybe_stripped_args || *maybe_stripped_args != "__stripped__") {
  102. LOG(ERROR) << "args is missing from TraceEvent JSON";
  103. return false;
  104. }
  105. }
  106. const base::Value::Dict* maybe_id2 = nullptr;
  107. if (require_id) {
  108. const std::string* maybe_id = event_dict.FindString("id");
  109. maybe_id2 = event_dict.FindDict("id2");
  110. if (!maybe_id && !maybe_id2) {
  111. LOG(ERROR)
  112. << "id/id2 is missing from ASYNC_BEGIN/ASYNC_END TraceEvent JSON";
  113. return false;
  114. }
  115. if (maybe_id)
  116. id = *maybe_id;
  117. }
  118. absl::optional<double> maybe_thread_duration = event_dict.FindDouble("tdur");
  119. if (maybe_thread_duration) {
  120. thread_duration = *maybe_thread_duration;
  121. }
  122. absl::optional<double> maybe_thread_timestamp = event_dict.FindDouble("tts");
  123. if (maybe_thread_timestamp) {
  124. thread_timestamp = *maybe_thread_timestamp;
  125. }
  126. const std::string* maybe_scope = event_dict.FindString("scope");
  127. if (maybe_scope) {
  128. scope = *maybe_scope;
  129. }
  130. const std::string* maybe_bind_id = event_dict.FindString("bind_id");
  131. if (maybe_bind_id) {
  132. bind_id = *maybe_bind_id;
  133. }
  134. absl::optional<bool> maybe_flow_out = event_dict.FindBool("flow_out");
  135. if (maybe_flow_out) {
  136. flow_out = *maybe_flow_out;
  137. }
  138. absl::optional<bool> maybe_flow_in = event_dict.FindBool("flow_in");
  139. if (maybe_flow_in) {
  140. flow_in = *maybe_flow_in;
  141. }
  142. if (maybe_id2) {
  143. const std::string* maybe_global_id2 = maybe_id2->FindString("global");
  144. if (maybe_global_id2) {
  145. global_id2 = *maybe_global_id2;
  146. }
  147. const std::string* maybe_local_id2 = maybe_id2->FindString("local");
  148. if (maybe_local_id2) {
  149. local_id2 = *maybe_local_id2;
  150. }
  151. }
  152. // For each argument, copy the type and create a trace_analyzer::TraceValue.
  153. // TODO(crbug.com/1303874): Add BINARY and LIST arg types if needed.
  154. if (maybe_args) {
  155. for (auto pair : *maybe_args) {
  156. switch (pair.second.type()) {
  157. case base::Value::Type::STRING:
  158. arg_strings[pair.first] = pair.second.GetString();
  159. break;
  160. case base::Value::Type::INTEGER:
  161. arg_numbers[pair.first] = static_cast<double>(pair.second.GetInt());
  162. break;
  163. case base::Value::Type::BOOLEAN:
  164. arg_numbers[pair.first] = pair.second.GetBool() ? 1.0 : 0.0;
  165. break;
  166. case base::Value::Type::DOUBLE:
  167. arg_numbers[pair.first] = pair.second.GetDouble();
  168. break;
  169. case base::Value::Type::DICT:
  170. arg_dicts[pair.first] = pair.second.GetDict().Clone();
  171. break;
  172. default:
  173. break;
  174. }
  175. }
  176. }
  177. return true;
  178. }
  179. double TraceEvent::GetAbsTimeToOtherEvent() const {
  180. return fabs(other_event->timestamp - timestamp);
  181. }
  182. bool TraceEvent::GetArgAsString(const std::string& arg_name,
  183. std::string* arg) const {
  184. const auto it = arg_strings.find(arg_name);
  185. if (it != arg_strings.end()) {
  186. *arg = it->second;
  187. return true;
  188. }
  189. return false;
  190. }
  191. bool TraceEvent::GetArgAsNumber(const std::string& arg_name,
  192. double* arg) const {
  193. const auto it = arg_numbers.find(arg_name);
  194. if (it != arg_numbers.end()) {
  195. *arg = it->second;
  196. return true;
  197. }
  198. return false;
  199. }
  200. bool TraceEvent::GetArgAsDict(const std::string& arg_name,
  201. base::Value::Dict* arg) const {
  202. const auto it = arg_dicts.find(arg_name);
  203. if (it != arg_dicts.end()) {
  204. *arg = it->second.Clone();
  205. return true;
  206. }
  207. return false;
  208. }
  209. bool TraceEvent::HasStringArg(const std::string& arg_name) const {
  210. return (arg_strings.find(arg_name) != arg_strings.end());
  211. }
  212. bool TraceEvent::HasNumberArg(const std::string& arg_name) const {
  213. return (arg_numbers.find(arg_name) != arg_numbers.end());
  214. }
  215. bool TraceEvent::HasDictArg(const std::string& arg_name) const {
  216. return (arg_dicts.find(arg_name) != arg_dicts.end());
  217. }
  218. std::string TraceEvent::GetKnownArgAsString(const std::string& arg_name) const {
  219. std::string arg_string;
  220. bool result = GetArgAsString(arg_name, &arg_string);
  221. DCHECK(result);
  222. return arg_string;
  223. }
  224. double TraceEvent::GetKnownArgAsDouble(const std::string& arg_name) const {
  225. double arg_double = 0;
  226. bool result = GetArgAsNumber(arg_name, &arg_double);
  227. DCHECK(result);
  228. return arg_double;
  229. }
  230. int TraceEvent::GetKnownArgAsInt(const std::string& arg_name) const {
  231. double arg_double = 0;
  232. bool result = GetArgAsNumber(arg_name, &arg_double);
  233. DCHECK(result);
  234. return static_cast<int>(arg_double);
  235. }
  236. bool TraceEvent::GetKnownArgAsBool(const std::string& arg_name) const {
  237. double arg_double = 0;
  238. bool result = GetArgAsNumber(arg_name, &arg_double);
  239. DCHECK(result);
  240. return (arg_double != 0.0);
  241. }
  242. base::Value::Dict TraceEvent::GetKnownArgAsDict(
  243. const std::string& arg_name) const {
  244. base::Value::Dict arg_dict;
  245. bool result = GetArgAsDict(arg_name, &arg_dict);
  246. DCHECK(result);
  247. return arg_dict;
  248. }
  249. // QueryNode
  250. QueryNode::QueryNode(const Query& query) : query_(query) {
  251. }
  252. QueryNode::~QueryNode() = default;
  253. // Query
  254. Query::Query(TraceEventMember member)
  255. : type_(QUERY_EVENT_MEMBER),
  256. operator_(OP_INVALID),
  257. member_(member),
  258. number_(0),
  259. is_pattern_(false) {
  260. }
  261. Query::Query(TraceEventMember member, const std::string& arg_name)
  262. : type_(QUERY_EVENT_MEMBER),
  263. operator_(OP_INVALID),
  264. member_(member),
  265. number_(0),
  266. string_(arg_name),
  267. is_pattern_(false) {
  268. }
  269. Query::Query(const Query& query) = default;
  270. Query::~Query() = default;
  271. Query Query::String(const std::string& str) {
  272. return Query(str);
  273. }
  274. Query Query::Double(double num) {
  275. return Query(num);
  276. }
  277. Query Query::Int(int32_t num) {
  278. return Query(static_cast<double>(num));
  279. }
  280. Query Query::Uint(uint32_t num) {
  281. return Query(static_cast<double>(num));
  282. }
  283. Query Query::Bool(bool boolean) {
  284. return Query(boolean ? 1.0 : 0.0);
  285. }
  286. Query Query::Phase(char phase) {
  287. return Query(static_cast<double>(phase));
  288. }
  289. Query Query::Pattern(const std::string& pattern) {
  290. Query query(pattern);
  291. query.is_pattern_ = true;
  292. return query;
  293. }
  294. bool Query::Evaluate(const TraceEvent& event) const {
  295. // First check for values that can convert to bool.
  296. // double is true if != 0:
  297. double bool_value = 0.0;
  298. bool is_bool = GetAsDouble(event, &bool_value);
  299. if (is_bool)
  300. return (bool_value != 0.0);
  301. // string is true if it is non-empty:
  302. std::string str_value;
  303. bool is_str = GetAsString(event, &str_value);
  304. if (is_str)
  305. return !str_value.empty();
  306. DCHECK_EQ(QUERY_BOOLEAN_OPERATOR, type_)
  307. << "Invalid query: missing boolean expression";
  308. DCHECK(left_.get());
  309. DCHECK(right_.get() || is_unary_operator());
  310. if (is_comparison_operator()) {
  311. DCHECK(left().is_value() && right().is_value())
  312. << "Invalid query: comparison operator used between event member and "
  313. "value.";
  314. bool compare_result = false;
  315. if (CompareAsDouble(event, &compare_result))
  316. return compare_result;
  317. if (CompareAsString(event, &compare_result))
  318. return compare_result;
  319. return false;
  320. }
  321. // It's a logical operator.
  322. switch (operator_) {
  323. case OP_AND:
  324. return left().Evaluate(event) && right().Evaluate(event);
  325. case OP_OR:
  326. return left().Evaluate(event) || right().Evaluate(event);
  327. case OP_NOT:
  328. return !left().Evaluate(event);
  329. default:
  330. NOTREACHED();
  331. return false;
  332. }
  333. }
  334. bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const {
  335. double lhs, rhs;
  336. if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs))
  337. return false;
  338. switch (operator_) {
  339. case OP_EQ:
  340. *result = (lhs == rhs);
  341. return true;
  342. case OP_NE:
  343. *result = (lhs != rhs);
  344. return true;
  345. case OP_LT:
  346. *result = (lhs < rhs);
  347. return true;
  348. case OP_LE:
  349. *result = (lhs <= rhs);
  350. return true;
  351. case OP_GT:
  352. *result = (lhs > rhs);
  353. return true;
  354. case OP_GE:
  355. *result = (lhs >= rhs);
  356. return true;
  357. default:
  358. NOTREACHED();
  359. return false;
  360. }
  361. }
  362. bool Query::CompareAsString(const TraceEvent& event, bool* result) const {
  363. std::string lhs, rhs;
  364. if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs))
  365. return false;
  366. switch (operator_) {
  367. case OP_EQ:
  368. if (right().is_pattern_)
  369. *result = base::MatchPattern(lhs, rhs);
  370. else if (left().is_pattern_)
  371. *result = base::MatchPattern(rhs, lhs);
  372. else
  373. *result = (lhs == rhs);
  374. return true;
  375. case OP_NE:
  376. if (right().is_pattern_)
  377. *result = !base::MatchPattern(lhs, rhs);
  378. else if (left().is_pattern_)
  379. *result = !base::MatchPattern(rhs, lhs);
  380. else
  381. *result = (lhs != rhs);
  382. return true;
  383. case OP_LT:
  384. *result = (lhs < rhs);
  385. return true;
  386. case OP_LE:
  387. *result = (lhs <= rhs);
  388. return true;
  389. case OP_GT:
  390. *result = (lhs > rhs);
  391. return true;
  392. case OP_GE:
  393. *result = (lhs >= rhs);
  394. return true;
  395. default:
  396. NOTREACHED();
  397. return false;
  398. }
  399. }
  400. bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
  401. double* num) const {
  402. DCHECK_EQ(QUERY_ARITHMETIC_OPERATOR, type_);
  403. DCHECK(left_.get());
  404. DCHECK(right_.get() || is_unary_operator());
  405. double lhs = 0, rhs = 0;
  406. if (!left().GetAsDouble(event, &lhs))
  407. return false;
  408. if (!is_unary_operator() && !right().GetAsDouble(event, &rhs))
  409. return false;
  410. switch (operator_) {
  411. case OP_ADD:
  412. *num = lhs + rhs;
  413. return true;
  414. case OP_SUB:
  415. *num = lhs - rhs;
  416. return true;
  417. case OP_MUL:
  418. *num = lhs * rhs;
  419. return true;
  420. case OP_DIV:
  421. *num = lhs / rhs;
  422. return true;
  423. case OP_MOD:
  424. *num = static_cast<double>(static_cast<int64_t>(lhs) %
  425. static_cast<int64_t>(rhs));
  426. return true;
  427. case OP_NEGATE:
  428. *num = -lhs;
  429. return true;
  430. default:
  431. NOTREACHED();
  432. return false;
  433. }
  434. }
  435. bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
  436. switch (type_) {
  437. case QUERY_ARITHMETIC_OPERATOR:
  438. return EvaluateArithmeticOperator(event, num);
  439. case QUERY_EVENT_MEMBER:
  440. return GetMemberValueAsDouble(event, num);
  441. case QUERY_NUMBER:
  442. *num = number_;
  443. return true;
  444. default:
  445. return false;
  446. }
  447. }
  448. bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
  449. switch (type_) {
  450. case QUERY_EVENT_MEMBER:
  451. return GetMemberValueAsString(event, str);
  452. case QUERY_STRING:
  453. *str = string_;
  454. return true;
  455. default:
  456. return false;
  457. }
  458. }
  459. const TraceEvent* Query::SelectTargetEvent(const TraceEvent* event,
  460. TraceEventMember member) {
  461. if (member >= OTHER_FIRST_MEMBER && member <= OTHER_LAST_MEMBER)
  462. return event->other_event;
  463. if (member >= PREV_FIRST_MEMBER && member <= PREV_LAST_MEMBER)
  464. return event->prev_event;
  465. return event;
  466. }
  467. bool Query::GetMemberValueAsDouble(const TraceEvent& event,
  468. double* num) const {
  469. DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
  470. // This could be a request for a member of |event| or a member of |event|'s
  471. // associated previous or next event. Store the target event in the_event:
  472. const TraceEvent* the_event = SelectTargetEvent(&event, member_);
  473. // Request for member of associated event, but there is no associated event.
  474. if (!the_event)
  475. return false;
  476. switch (member_) {
  477. case EVENT_PID:
  478. case OTHER_PID:
  479. case PREV_PID:
  480. *num = static_cast<double>(the_event->thread.process_id);
  481. return true;
  482. case EVENT_TID:
  483. case OTHER_TID:
  484. case PREV_TID:
  485. *num = static_cast<double>(the_event->thread.thread_id);
  486. return true;
  487. case EVENT_TIME:
  488. case OTHER_TIME:
  489. case PREV_TIME:
  490. *num = the_event->timestamp;
  491. return true;
  492. case EVENT_DURATION:
  493. if (!the_event->has_other_event())
  494. return false;
  495. *num = the_event->GetAbsTimeToOtherEvent();
  496. return true;
  497. case EVENT_COMPLETE_DURATION:
  498. if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE)
  499. return false;
  500. *num = the_event->duration;
  501. return true;
  502. case EVENT_PHASE:
  503. case OTHER_PHASE:
  504. case PREV_PHASE:
  505. *num = static_cast<double>(the_event->phase);
  506. return true;
  507. case EVENT_HAS_STRING_ARG:
  508. case OTHER_HAS_STRING_ARG:
  509. case PREV_HAS_STRING_ARG:
  510. *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0);
  511. return true;
  512. case EVENT_HAS_NUMBER_ARG:
  513. case OTHER_HAS_NUMBER_ARG:
  514. case PREV_HAS_NUMBER_ARG:
  515. *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
  516. return true;
  517. case EVENT_ARG:
  518. case OTHER_ARG:
  519. case PREV_ARG: {
  520. // Search for the argument name and return its value if found.
  521. auto num_i = the_event->arg_numbers.find(string_);
  522. if (num_i == the_event->arg_numbers.end())
  523. return false;
  524. *num = num_i->second;
  525. return true;
  526. }
  527. case EVENT_HAS_OTHER:
  528. // return 1.0 (true) if the other event exists
  529. *num = event.other_event ? 1.0 : 0.0;
  530. return true;
  531. case EVENT_HAS_PREV:
  532. *num = event.prev_event ? 1.0 : 0.0;
  533. return true;
  534. default:
  535. return false;
  536. }
  537. }
  538. bool Query::GetMemberValueAsString(const TraceEvent& event,
  539. std::string* str) const {
  540. DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
  541. // This could be a request for a member of |event| or a member of |event|'s
  542. // associated previous or next event. Store the target event in the_event:
  543. const TraceEvent* the_event = SelectTargetEvent(&event, member_);
  544. // Request for member of associated event, but there is no associated event.
  545. if (!the_event)
  546. return false;
  547. switch (member_) {
  548. case EVENT_CATEGORY:
  549. case OTHER_CATEGORY:
  550. case PREV_CATEGORY:
  551. *str = the_event->category;
  552. return true;
  553. case EVENT_NAME:
  554. case OTHER_NAME:
  555. case PREV_NAME:
  556. *str = the_event->name;
  557. return true;
  558. case EVENT_ID:
  559. case OTHER_ID:
  560. case PREV_ID:
  561. *str = the_event->id;
  562. return true;
  563. case EVENT_ARG:
  564. case OTHER_ARG:
  565. case PREV_ARG: {
  566. // Search for the argument name and return its value if found.
  567. auto str_i = the_event->arg_strings.find(string_);
  568. if (str_i == the_event->arg_strings.end())
  569. return false;
  570. *str = str_i->second;
  571. return true;
  572. }
  573. default:
  574. return false;
  575. }
  576. }
  577. Query::Query(const std::string& str)
  578. : type_(QUERY_STRING),
  579. operator_(OP_INVALID),
  580. member_(EVENT_INVALID),
  581. number_(0),
  582. string_(str),
  583. is_pattern_(false) {
  584. }
  585. Query::Query(double num)
  586. : type_(QUERY_NUMBER),
  587. operator_(OP_INVALID),
  588. member_(EVENT_INVALID),
  589. number_(num),
  590. is_pattern_(false) {
  591. }
  592. const Query& Query::left() const {
  593. return left_->query();
  594. }
  595. const Query& Query::right() const {
  596. return right_->query();
  597. }
  598. Query Query::operator==(const Query& rhs) const {
  599. return Query(*this, rhs, OP_EQ);
  600. }
  601. Query Query::operator!=(const Query& rhs) const {
  602. return Query(*this, rhs, OP_NE);
  603. }
  604. Query Query::operator<(const Query& rhs) const {
  605. return Query(*this, rhs, OP_LT);
  606. }
  607. Query Query::operator<=(const Query& rhs) const {
  608. return Query(*this, rhs, OP_LE);
  609. }
  610. Query Query::operator>(const Query& rhs) const {
  611. return Query(*this, rhs, OP_GT);
  612. }
  613. Query Query::operator>=(const Query& rhs) const {
  614. return Query(*this, rhs, OP_GE);
  615. }
  616. Query Query::operator&&(const Query& rhs) const {
  617. return Query(*this, rhs, OP_AND);
  618. }
  619. Query Query::operator||(const Query& rhs) const {
  620. return Query(*this, rhs, OP_OR);
  621. }
  622. Query Query::operator!() const {
  623. return Query(*this, OP_NOT);
  624. }
  625. Query Query::operator+(const Query& rhs) const {
  626. return Query(*this, rhs, OP_ADD);
  627. }
  628. Query Query::operator-(const Query& rhs) const {
  629. return Query(*this, rhs, OP_SUB);
  630. }
  631. Query Query::operator*(const Query& rhs) const {
  632. return Query(*this, rhs, OP_MUL);
  633. }
  634. Query Query::operator/(const Query& rhs) const {
  635. return Query(*this, rhs, OP_DIV);
  636. }
  637. Query Query::operator%(const Query& rhs) const {
  638. return Query(*this, rhs, OP_MOD);
  639. }
  640. Query Query::operator-() const {
  641. return Query(*this, OP_NEGATE);
  642. }
  643. Query::Query(const Query& left, const Query& right, Operator binary_op)
  644. : operator_(binary_op),
  645. left_(new QueryNode(left)),
  646. right_(new QueryNode(right)),
  647. member_(EVENT_INVALID),
  648. number_(0) {
  649. type_ = (binary_op < OP_ADD ?
  650. QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
  651. }
  652. Query::Query(const Query& left, Operator unary_op)
  653. : operator_(unary_op),
  654. left_(new QueryNode(left)),
  655. member_(EVENT_INVALID),
  656. number_(0) {
  657. type_ = (unary_op < OP_ADD ?
  658. QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
  659. }
  660. namespace {
  661. // Search |events| for |query| and add matches to |output|.
  662. size_t FindMatchingEvents(const std::vector<TraceEvent>& events,
  663. const Query& query,
  664. TraceEventVector* output,
  665. bool ignore_metadata_events) {
  666. for (const auto& i : events) {
  667. if (ignore_metadata_events && i.phase == TRACE_EVENT_PHASE_METADATA)
  668. continue;
  669. if (query.Evaluate(i))
  670. output->push_back(&i);
  671. }
  672. return output->size();
  673. }
  674. bool ParseEventsFromJson(const std::string& json,
  675. std::vector<TraceEvent>* output) {
  676. absl::optional<base::Value> root = base::JSONReader::Read(json);
  677. if (!root)
  678. return false;
  679. base::Value::List* list = nullptr;
  680. if (root->is_list()) {
  681. list = &root->GetList();
  682. } else if (root->is_dict()) {
  683. list = root->GetDict().FindList("traceEvents");
  684. }
  685. if (!list)
  686. return false;
  687. for (const auto& item : *list) {
  688. TraceEvent event;
  689. if (!event.SetFromJSON(&item))
  690. return false;
  691. output->push_back(std::move(event));
  692. }
  693. return true;
  694. }
  695. } // namespace
  696. // TraceAnalyzer
  697. TraceAnalyzer::TraceAnalyzer()
  698. : ignore_metadata_events_(false), allow_association_changes_(true) {}
  699. TraceAnalyzer::~TraceAnalyzer() = default;
  700. // static
  701. std::unique_ptr<TraceAnalyzer> TraceAnalyzer::Create(
  702. const std::string& json_events) {
  703. std::unique_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer());
  704. if (analyzer->SetEvents(json_events))
  705. return analyzer;
  706. return nullptr;
  707. }
  708. bool TraceAnalyzer::SetEvents(const std::string& json_events) {
  709. raw_events_.clear();
  710. if (!ParseEventsFromJson(json_events, &raw_events_))
  711. return false;
  712. base::ranges::stable_sort(raw_events_);
  713. ParseMetadata();
  714. return true;
  715. }
  716. void TraceAnalyzer::AssociateBeginEndEvents() {
  717. using trace_analyzer::Query;
  718. Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN));
  719. Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END));
  720. Query match(Query::EventName() == Query::OtherName() &&
  721. Query::EventCategory() == Query::OtherCategory() &&
  722. Query::EventTid() == Query::OtherTid() &&
  723. Query::EventPid() == Query::OtherPid());
  724. AssociateEvents(begin, end, match);
  725. }
  726. void TraceAnalyzer::AssociateAsyncBeginEndEvents(bool match_pid) {
  727. using trace_analyzer::Query;
  728. Query begin(
  729. Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
  730. Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
  731. Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
  732. Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) ||
  733. Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
  734. Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
  735. Query match(Query::EventCategory() == Query::OtherCategory() &&
  736. Query::EventId() == Query::OtherId());
  737. if (match_pid) {
  738. match = match && Query::EventPid() == Query::OtherPid();
  739. }
  740. AssociateEvents(begin, end, match);
  741. }
  742. void TraceAnalyzer::AssociateEvents(const Query& first,
  743. const Query& second,
  744. const Query& match) {
  745. DCHECK(allow_association_changes_)
  746. << "AssociateEvents not allowed after FindEvents";
  747. // Search for matching begin/end event pairs. When a matching end is found,
  748. // it is associated with the begin event.
  749. std::vector<TraceEvent*> begin_stack;
  750. for (auto& this_event : raw_events_) {
  751. if (second.Evaluate(this_event)) {
  752. // Search stack for matching begin, starting from end.
  753. for (int stack_index = static_cast<int>(begin_stack.size()) - 1;
  754. stack_index >= 0; --stack_index) {
  755. TraceEvent& begin_event = *begin_stack[stack_index];
  756. // Temporarily set other to test against the match query.
  757. const TraceEvent* other_backup = begin_event.other_event;
  758. begin_event.other_event = &this_event;
  759. if (match.Evaluate(begin_event)) {
  760. // Found a matching begin/end pair.
  761. // Set the associated previous event
  762. this_event.prev_event = &begin_event;
  763. // Erase the matching begin event index from the stack.
  764. begin_stack.erase(begin_stack.begin() + stack_index);
  765. break;
  766. }
  767. // Not a match, restore original other and continue.
  768. begin_event.other_event = other_backup;
  769. }
  770. }
  771. // Even if this_event is a |second| event that has matched an earlier
  772. // |first| event, it can still also be a |first| event and be associated
  773. // with a later |second| event.
  774. if (first.Evaluate(this_event)) {
  775. begin_stack.push_back(&this_event);
  776. }
  777. }
  778. }
  779. void TraceAnalyzer::MergeAssociatedEventArgs() {
  780. for (auto& i : raw_events_) {
  781. // Merge all associated events with the first event.
  782. const TraceEvent* other = i.other_event;
  783. // Avoid looping by keeping set of encountered TraceEvents.
  784. std::set<const TraceEvent*> encounters;
  785. encounters.insert(&i);
  786. while (other && encounters.find(other) == encounters.end()) {
  787. encounters.insert(other);
  788. i.arg_numbers.insert(other->arg_numbers.begin(),
  789. other->arg_numbers.end());
  790. i.arg_strings.insert(other->arg_strings.begin(),
  791. other->arg_strings.end());
  792. other = other->other_event;
  793. }
  794. }
  795. }
  796. size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) {
  797. allow_association_changes_ = false;
  798. output->clear();
  799. return FindMatchingEvents(
  800. raw_events_, query, output, ignore_metadata_events_);
  801. }
  802. const TraceEvent* TraceAnalyzer::FindFirstOf(const Query& query) {
  803. TraceEventVector output;
  804. if (FindEvents(query, &output) > 0)
  805. return output.front();
  806. return nullptr;
  807. }
  808. const TraceEvent* TraceAnalyzer::FindLastOf(const Query& query) {
  809. TraceEventVector output;
  810. if (FindEvents(query, &output) > 0)
  811. return output.back();
  812. return nullptr;
  813. }
  814. const std::string& TraceAnalyzer::GetThreadName(
  815. const TraceEvent::ProcessThreadID& thread) {
  816. // If thread is not found, just add and return empty string.
  817. return thread_names_[thread];
  818. }
  819. void TraceAnalyzer::ParseMetadata() {
  820. for (const auto& this_event : raw_events_) {
  821. // Check for thread name metadata.
  822. if (this_event.phase != TRACE_EVENT_PHASE_METADATA ||
  823. this_event.name != "thread_name")
  824. continue;
  825. std::map<std::string, std::string>::const_iterator string_it =
  826. this_event.arg_strings.find("name");
  827. if (string_it != this_event.arg_strings.end())
  828. thread_names_[this_event.thread] = string_it->second;
  829. }
  830. }
  831. // Utility functions for collecting process-local traces and creating a
  832. // |TraceAnalyzer| from the result.
  833. void Start(const std::string& category_filter_string) {
  834. DCHECK(!base::trace_event::TraceLog::GetInstance()->IsEnabled());
  835. base::trace_event::TraceLog::GetInstance()->SetEnabled(
  836. base::trace_event::TraceConfig(category_filter_string, ""),
  837. base::trace_event::TraceLog::RECORDING_MODE);
  838. }
  839. std::unique_ptr<TraceAnalyzer> Stop() {
  840. DCHECK(base::trace_event::TraceLog::GetInstance()->IsEnabled());
  841. base::trace_event::TraceLog::GetInstance()->SetDisabled();
  842. base::trace_event::TraceResultBuffer buffer;
  843. base::trace_event::TraceResultBuffer::SimpleOutput trace_output;
  844. buffer.SetOutputCallback(trace_output.GetCallback());
  845. base::RunLoop run_loop;
  846. buffer.Start();
  847. base::trace_event::TraceLog::GetInstance()->Flush(
  848. base::BindRepeating(&OnTraceDataCollected, run_loop.QuitClosure(),
  849. base::Unretained(&buffer)));
  850. run_loop.Run();
  851. buffer.Finish();
  852. return TraceAnalyzer::Create(trace_output.json_output);
  853. }
  854. // TraceEventVector utility functions.
  855. bool GetRateStats(const TraceEventVector& events,
  856. RateStats* stats,
  857. const RateStatsOptions* options) {
  858. DCHECK(stats);
  859. // Need at least 3 events to calculate rate stats.
  860. const size_t kMinEvents = 3;
  861. if (events.size() < kMinEvents) {
  862. LOG(ERROR) << "Not enough events: " << events.size();
  863. return false;
  864. }
  865. std::vector<double> deltas;
  866. size_t num_deltas = events.size() - 1;
  867. for (size_t i = 0; i < num_deltas; ++i) {
  868. double delta = events.at(i + 1)->timestamp - events.at(i)->timestamp;
  869. if (delta < 0.0) {
  870. LOG(ERROR) << "Events are out of order";
  871. return false;
  872. }
  873. deltas.push_back(delta);
  874. }
  875. base::ranges::sort(deltas);
  876. if (options) {
  877. if (options->trim_min + options->trim_max > events.size() - kMinEvents) {
  878. LOG(ERROR) << "Attempt to trim too many events";
  879. return false;
  880. }
  881. deltas.erase(deltas.begin(), deltas.begin() + options->trim_min);
  882. deltas.erase(deltas.end() - options->trim_max, deltas.end());
  883. }
  884. num_deltas = deltas.size();
  885. double delta_sum = 0.0;
  886. for (size_t i = 0; i < num_deltas; ++i)
  887. delta_sum += deltas[i];
  888. stats->min_us = *base::ranges::min_element(deltas);
  889. stats->max_us = *base::ranges::max_element(deltas);
  890. stats->mean_us = delta_sum / static_cast<double>(num_deltas);
  891. double sum_mean_offsets_squared = 0.0;
  892. for (size_t i = 0; i < num_deltas; ++i) {
  893. double offset = fabs(deltas[i] - stats->mean_us);
  894. sum_mean_offsets_squared += offset * offset;
  895. }
  896. stats->standard_deviation_us =
  897. sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1));
  898. return true;
  899. }
  900. bool FindFirstOf(const TraceEventVector& events,
  901. const Query& query,
  902. size_t position,
  903. size_t* return_index) {
  904. DCHECK(return_index);
  905. for (size_t i = position; i < events.size(); ++i) {
  906. if (query.Evaluate(*events[i])) {
  907. *return_index = i;
  908. return true;
  909. }
  910. }
  911. return false;
  912. }
  913. bool FindLastOf(const TraceEventVector& events,
  914. const Query& query,
  915. size_t position,
  916. size_t* return_index) {
  917. DCHECK(return_index);
  918. for (size_t i = std::min(position + 1, events.size()); i != 0; --i) {
  919. if (query.Evaluate(*events[i - 1])) {
  920. *return_index = i - 1;
  921. return true;
  922. }
  923. }
  924. return false;
  925. }
  926. bool FindClosest(const TraceEventVector& events,
  927. const Query& query,
  928. size_t position,
  929. size_t* return_closest,
  930. size_t* return_second_closest) {
  931. DCHECK(return_closest);
  932. if (events.empty() || position >= events.size())
  933. return false;
  934. size_t closest = events.size();
  935. size_t second_closest = events.size();
  936. for (size_t i = 0; i < events.size(); ++i) {
  937. if (!query.Evaluate(*events.at(i)))
  938. continue;
  939. if (closest == events.size()) {
  940. closest = i;
  941. continue;
  942. }
  943. if (fabs(events.at(i)->timestamp - events.at(position)->timestamp) <
  944. fabs(events.at(closest)->timestamp - events.at(position)->timestamp)) {
  945. second_closest = closest;
  946. closest = i;
  947. } else if (second_closest == events.size()) {
  948. second_closest = i;
  949. }
  950. }
  951. if (closest < events.size() &&
  952. (!return_second_closest || second_closest < events.size())) {
  953. *return_closest = closest;
  954. if (return_second_closest)
  955. *return_second_closest = second_closest;
  956. return true;
  957. }
  958. return false;
  959. }
  960. size_t CountMatches(const TraceEventVector& events,
  961. const Query& query,
  962. size_t begin_position,
  963. size_t end_position) {
  964. if (begin_position >= events.size())
  965. return 0u;
  966. end_position = (end_position < events.size()) ? end_position : events.size();
  967. size_t count = 0u;
  968. for (size_t i = begin_position; i < end_position; ++i) {
  969. if (query.Evaluate(*events.at(i)))
  970. ++count;
  971. }
  972. return count;
  973. }
  974. } // namespace trace_analyzer