OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/test/trace_event_analyzer.h" | 5 #include "base/test/trace_event_analyzer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <math.h> | 8 #include <math.h> |
9 | 9 |
10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 | 13 |
14 namespace trace_analyzer { | 14 namespace trace_analyzer { |
15 | 15 |
16 // TraceEvent | 16 // TraceEvent |
17 | 17 |
18 TraceEvent::TraceEvent() | 18 TraceEvent::TraceEvent() |
19 : thread(0, 0), | 19 : thread(0, 0), |
20 timestamp(0), | 20 timestamp(0), |
21 phase(TRACE_EVENT_PHASE_BEGIN), | 21 phase(TRACE_EVENT_PHASE_BEGIN), |
22 other_event(NULL) { | 22 other_event(NULL) { |
23 } | 23 } |
24 | 24 |
25 TraceEvent::~TraceEvent() { | 25 TraceEvent::~TraceEvent() { |
26 } | 26 } |
27 | 27 |
28 bool TraceEvent::SetFromJSON(const base::Value* event_value) { | 28 bool TraceEvent::SetFromJSON(const base::Value* event_value) { |
29 if (event_value->GetType() != base::Value::TYPE_DICTIONARY) | 29 if (event_value->GetType() != base::Value::TYPE_DICTIONARY) { |
| 30 LOG(ERROR) << "Value must be TYPE_DICTIONARY"; |
30 return false; | 31 return false; |
| 32 } |
31 const base::DictionaryValue* dictionary = | 33 const base::DictionaryValue* dictionary = |
32 static_cast<const base::DictionaryValue*>(event_value); | 34 static_cast<const base::DictionaryValue*>(event_value); |
33 | 35 |
34 std::string phase_str; | 36 std::string phase_str; |
35 base::DictionaryValue* args = NULL; | 37 base::DictionaryValue* args = NULL; |
36 | 38 |
37 if (dictionary->GetInteger("pid", &thread.process_id) && | 39 if (!dictionary->GetString("ph", &phase_str)) { |
38 dictionary->GetInteger("tid", &thread.thread_id) && | 40 LOG(ERROR) << "ph is missing from TraceEvent JSON"; |
39 dictionary->GetDouble("ts", ×tamp) && | 41 return false; |
40 dictionary->GetString("cat", &category) && | 42 } |
41 dictionary->GetString("name", &name) && | |
42 dictionary->GetString("ph", &phase_str) && | |
43 dictionary->GetDictionary("args", &args)) { | |
44 | 43 |
45 phase = base::debug::TraceEvent::GetPhase(phase_str.c_str()); | 44 phase = base::debug::TraceEvent::GetPhase(phase_str.c_str()); |
46 | 45 |
47 // For each argument, copy the type and create a trace_analyzer::TraceValue. | 46 bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA); |
48 base::DictionaryValue::key_iterator keyi = args->begin_keys(); | 47 bool require_id = (phase == TRACE_EVENT_PHASE_START || |
49 for (; keyi != args->end_keys(); ++keyi) { | 48 phase == TRACE_EVENT_PHASE_FINISH); |
50 std::string str; | 49 |
51 bool boolean = false; | 50 if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) { |
52 int int_num = 0; | 51 LOG(ERROR) << "pid is missing from TraceEvent JSON"; |
53 double double_num = 0.0; | 52 return false; |
54 Value* value = NULL; | 53 } |
55 if (args->GetWithoutPathExpansion(*keyi, &value)) { | 54 if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) { |
56 if (value->GetAsString(&str)) | 55 LOG(ERROR) << "tid is missing from TraceEvent JSON"; |
57 arg_strings[*keyi] = str; | 56 return false; |
58 else if (value->GetAsInteger(&int_num)) | 57 } |
59 arg_numbers[*keyi] = static_cast<double>(int_num); | 58 if (require_origin && !dictionary->GetDouble("ts", ×tamp)) { |
60 else if (value->GetAsBoolean(&boolean)) | 59 LOG(ERROR) << "ts is missing from TraceEvent JSON"; |
61 arg_numbers[*keyi] = static_cast<double>(boolean ? 1 : 0); | 60 return false; |
62 else if (value->GetAsDouble(&double_num)) | 61 } |
63 arg_numbers[*keyi] = double_num; | 62 if (!dictionary->GetString("cat", &category)) { |
64 else | 63 LOG(ERROR) << "cat is missing from TraceEvent JSON"; |
65 return false; // Invalid trace event JSON format. | 64 return false; |
| 65 } |
| 66 if (!dictionary->GetString("name", &name)) { |
| 67 LOG(ERROR) << "name is missing from TraceEvent JSON"; |
| 68 return false; |
| 69 } |
| 70 if (!dictionary->GetDictionary("args", &args)) { |
| 71 LOG(ERROR) << "args is missing from TraceEvent JSON"; |
| 72 return false; |
| 73 } |
| 74 if (require_id && !dictionary->GetString("id", &id)) { |
| 75 LOG(ERROR) << "id is missing from START/FINISH TraceEvent JSON"; |
| 76 return false; |
| 77 } |
| 78 |
| 79 // For each argument, copy the type and create a trace_analyzer::TraceValue. |
| 80 base::DictionaryValue::key_iterator keyi = args->begin_keys(); |
| 81 for (; keyi != args->end_keys(); ++keyi) { |
| 82 std::string str; |
| 83 bool boolean = false; |
| 84 int int_num = 0; |
| 85 double double_num = 0.0; |
| 86 Value* value = NULL; |
| 87 if (args->GetWithoutPathExpansion(*keyi, &value)) { |
| 88 if (value->GetAsString(&str)) |
| 89 arg_strings[*keyi] = str; |
| 90 else if (value->GetAsInteger(&int_num)) |
| 91 arg_numbers[*keyi] = static_cast<double>(int_num); |
| 92 else if (value->GetAsBoolean(&boolean)) |
| 93 arg_numbers[*keyi] = static_cast<double>(boolean ? 1 : 0); |
| 94 else if (value->GetAsDouble(&double_num)) |
| 95 arg_numbers[*keyi] = double_num; |
| 96 else { |
| 97 LOG(ERROR) << "Value type of argument is not supported: " << |
| 98 static_cast<int>(value->GetType()); |
| 99 return false; // Invalid trace event JSON format. |
66 } | 100 } |
67 } | 101 } |
68 | |
69 return true; | |
70 } | 102 } |
71 | 103 |
72 return false; | 104 return true; |
73 } | 105 } |
74 | 106 |
75 double TraceEvent::GetAbsTimeToOtherEvent() const { | 107 double TraceEvent::GetAbsTimeToOtherEvent() const { |
76 return fabs(other_event->timestamp - timestamp); | 108 return fabs(other_event->timestamp - timestamp); |
77 } | 109 } |
78 | 110 |
79 bool TraceEvent::GetArgAsString(const std::string& name, | 111 bool TraceEvent::GetArgAsString(const std::string& name, |
80 std::string* arg) const { | 112 std::string* arg) const { |
81 std::map<std::string, std::string>::const_iterator i = arg_strings.find(name); | 113 std::map<std::string, std::string>::const_iterator i = arg_strings.find(name); |
82 if (i != arg_strings.end()) { | 114 if (i != arg_strings.end()) { |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 } | 461 } |
430 case EVENT_PHASE: | 462 case EVENT_PHASE: |
431 case OTHER_PHASE: | 463 case OTHER_PHASE: |
432 return static_cast<double>(the_event->phase); | 464 return static_cast<double>(the_event->phase); |
433 case EVENT_CATEGORY: | 465 case EVENT_CATEGORY: |
434 case OTHER_CATEGORY: | 466 case OTHER_CATEGORY: |
435 return the_event->category; | 467 return the_event->category; |
436 case EVENT_NAME: | 468 case EVENT_NAME: |
437 case OTHER_NAME: | 469 case OTHER_NAME: |
438 return the_event->name; | 470 return the_event->name; |
| 471 case EVENT_ID: |
| 472 case OTHER_ID: |
| 473 return the_event->id; |
439 case EVENT_HAS_STRING_ARG: | 474 case EVENT_HAS_STRING_ARG: |
440 case OTHER_HAS_STRING_ARG: | 475 case OTHER_HAS_STRING_ARG: |
441 return (the_event->HasStringArg(string_) ? 1.0 : 0.0); | 476 return (the_event->HasStringArg(string_) ? 1.0 : 0.0); |
442 case EVENT_HAS_NUMBER_ARG: | 477 case EVENT_HAS_NUMBER_ARG: |
443 case OTHER_HAS_NUMBER_ARG: | 478 case OTHER_HAS_NUMBER_ARG: |
444 return (the_event->HasNumberArg(string_) ? 1.0 : 0.0); | 479 return (the_event->HasNumberArg(string_) ? 1.0 : 0.0); |
445 case EVENT_ARG: | 480 case EVENT_ARG: |
446 case OTHER_ARG: | 481 case OTHER_ARG: |
447 { | 482 { |
448 // Search for the argument name and return its value if found. | 483 // Search for the argument name and return its value if found. |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 if (!ParseEventsFromJson(json_events, &raw_events_)) | 669 if (!ParseEventsFromJson(json_events, &raw_events_)) |
635 return false; | 670 return false; |
636 std::stable_sort(raw_events_.begin(), raw_events_.end()); | 671 std::stable_sort(raw_events_.begin(), raw_events_.end()); |
637 ParseMetadata(); | 672 ParseMetadata(); |
638 return true; | 673 return true; |
639 } | 674 } |
640 | 675 |
641 void TraceAnalyzer::AssociateBeginEndEvents() { | 676 void TraceAnalyzer::AssociateBeginEndEvents() { |
642 using namespace trace_analyzer; | 677 using namespace trace_analyzer; |
643 | 678 |
644 Query begin(Query(EVENT_PHASE) == | 679 Query begin(Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_BEGIN)); |
645 Query::Phase(TRACE_EVENT_PHASE_BEGIN)); | 680 Query end(Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_END)); |
646 Query end(Query(EVENT_PHASE) == | |
647 Query::Phase(TRACE_EVENT_PHASE_END)); | |
648 Query match(Query(EVENT_NAME) == Query(OTHER_NAME) && | 681 Query match(Query(EVENT_NAME) == Query(OTHER_NAME) && |
649 Query(EVENT_CATEGORY) == Query(OTHER_CATEGORY) && | 682 Query(EVENT_CATEGORY) == Query(OTHER_CATEGORY) && |
650 Query(EVENT_TID) == Query(OTHER_TID) && | 683 Query(EVENT_TID) == Query(OTHER_TID) && |
651 Query(EVENT_PID) == Query(OTHER_PID)); | 684 Query(EVENT_PID) == Query(OTHER_PID)); |
652 | 685 |
653 AssociateEvents(begin, end, match); | 686 AssociateEvents(begin, end, match); |
654 } | 687 } |
655 | 688 |
| 689 void TraceAnalyzer::AssociateStartFinishEvents() { |
| 690 using namespace trace_analyzer; |
| 691 |
| 692 Query begin(Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_START)); |
| 693 Query end(Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_FINISH)); |
| 694 Query match(Query(EVENT_NAME) == Query(OTHER_NAME) && |
| 695 Query(EVENT_CATEGORY) == Query(OTHER_CATEGORY) && |
| 696 Query(EVENT_ID) == Query(OTHER_ID)); |
| 697 |
| 698 AssociateEvents(begin, end, match); |
| 699 } |
| 700 |
656 void TraceAnalyzer::AssociateEvents(const Query& first, | 701 void TraceAnalyzer::AssociateEvents(const Query& first, |
657 const Query& second, | 702 const Query& second, |
658 const Query& match) { | 703 const Query& match) { |
659 DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after " | 704 DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after " |
660 "FindEvents"; | 705 "FindEvents"; |
661 | 706 |
662 // Search for matching begin/end event pairs. When a matching end is found, | 707 // Search for matching begin/end event pairs. When a matching end is found, |
663 // it is associated with the begin event. | 708 // it is associated with the begin event. |
664 std::vector<TraceEvent*> begin_stack; | 709 std::vector<TraceEvent*> begin_stack; |
665 for (size_t event_index = 0; event_index < raw_events_.size(); | 710 for (size_t event_index = 0; event_index < raw_events_.size(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 continue; | 767 continue; |
723 std::map<std::string, std::string>::const_iterator string_it = | 768 std::map<std::string, std::string>::const_iterator string_it = |
724 this_event.arg_strings.find("name"); | 769 this_event.arg_strings.find("name"); |
725 if (string_it != this_event.arg_strings.end()) | 770 if (string_it != this_event.arg_strings.end()) |
726 thread_names_[this_event.thread] = string_it->second; | 771 thread_names_[this_event.thread] = string_it->second; |
727 } | 772 } |
728 } | 773 } |
729 | 774 |
730 } // namespace trace_analyzer | 775 } // namespace trace_analyzer |
731 | 776 |
OLD | NEW |