| Index: base/test/trace_event_analyzer.cc
|
| ===================================================================
|
| --- base/test/trace_event_analyzer.cc (revision 107844)
|
| +++ base/test/trace_event_analyzer.cc (working copy)
|
| @@ -1,697 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "base/test/trace_event_analyzer.h"
|
| -
|
| -#include <algorithm>
|
| -#include <math.h>
|
| -
|
| -#include "base/json/json_reader.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/values.h"
|
| -
|
| -namespace trace_analyzer {
|
| -
|
| -// TraceEvent
|
| -
|
| -TraceEvent::TraceEvent()
|
| - : thread(0, 0),
|
| - timestamp(0),
|
| - phase(base::debug::TRACE_EVENT_PHASE_BEGIN),
|
| - other_event(NULL) {
|
| -}
|
| -
|
| -TraceEvent::~TraceEvent() {
|
| -}
|
| -
|
| -bool TraceEvent::SetFromJSON(const base::Value* event_value) {
|
| - if (event_value->GetType() != base::Value::TYPE_DICTIONARY)
|
| - return false;
|
| - const base::DictionaryValue* dictionary =
|
| - static_cast<const base::DictionaryValue*>(event_value);
|
| -
|
| - std::string phase_str;
|
| - base::DictionaryValue* args = NULL;
|
| -
|
| - if (dictionary->GetInteger("pid", &thread.process_id) &&
|
| - dictionary->GetInteger("tid", &thread.thread_id) &&
|
| - dictionary->GetDouble("ts", ×tamp) &&
|
| - dictionary->GetString("cat", &category) &&
|
| - dictionary->GetString("name", &name) &&
|
| - dictionary->GetString("ph", &phase_str) &&
|
| - dictionary->GetDictionary("args", &args)) {
|
| -
|
| - phase = base::debug::TraceEvent::GetPhase(phase_str.c_str());
|
| -
|
| - // For each argument, copy the type and create a trace_analyzer::TraceValue.
|
| - base::DictionaryValue::key_iterator keyi = args->begin_keys();
|
| - for (; keyi != args->end_keys(); ++keyi) {
|
| - std::string str;
|
| - bool boolean = false;
|
| - int int_num = 0;
|
| - double double_num = 0.0;
|
| - Value* value = NULL;
|
| - if (args->GetWithoutPathExpansion(*keyi, &value)) {
|
| - if (value->GetAsString(&str))
|
| - arg_strings[*keyi] = str;
|
| - else if (value->GetAsInteger(&int_num))
|
| - arg_numbers[*keyi] = static_cast<double>(int_num);
|
| - else if (value->GetAsBoolean(&boolean))
|
| - arg_numbers[*keyi] = static_cast<double>(boolean ? 1 : 0);
|
| - else if (value->GetAsDouble(&double_num))
|
| - arg_numbers[*keyi] = double_num;
|
| - else
|
| - return false; // Invalid trace event JSON format.
|
| - }
|
| - }
|
| -
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -bool TraceEvent::GetAbsTimeToOtherEvent(double* duration) const {
|
| - if (!other_event)
|
| - return false;
|
| -
|
| - *duration = fabs(other_event->timestamp - timestamp);
|
| - return true;
|
| -}
|
| -
|
| -bool TraceEvent::GetArgAsString(const std::string& name,
|
| - std::string* arg) const {
|
| - std::map<std::string, std::string>::const_iterator i = arg_strings.find(name);
|
| - if (i != arg_strings.end()) {
|
| - *arg = i->second;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool TraceEvent::GetArgAsNumber(const std::string& name,
|
| - double* arg) const {
|
| - std::map<std::string, double>::const_iterator i = arg_numbers.find(name);
|
| - if (i != arg_numbers.end()) {
|
| - *arg = i->second;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -// QueryNode
|
| -
|
| -QueryNode::QueryNode(const Query& query) : query_(query) {
|
| -}
|
| -
|
| -QueryNode::~QueryNode() {
|
| -}
|
| -
|
| -// Query
|
| -
|
| -Query::Query(TraceEventMember member)
|
| - : type_(QUERY_EVENT_MEMBER),
|
| - operator_(OP_INVALID),
|
| - member_(member),
|
| - number_(0),
|
| - is_pattern_(false) {
|
| -}
|
| -
|
| -Query::Query(TraceEventMember member, const std::string& arg_name)
|
| - : type_(QUERY_EVENT_MEMBER),
|
| - operator_(OP_INVALID),
|
| - member_(member),
|
| - number_(0),
|
| - string_(arg_name),
|
| - is_pattern_(false) {
|
| -}
|
| -
|
| -Query::Query(const Query& query)
|
| - : type_(query.type_),
|
| - operator_(query.operator_),
|
| - left_(query.left_),
|
| - right_(query.right_),
|
| - member_(query.member_),
|
| - number_(query.number_),
|
| - string_(query.string_),
|
| - is_pattern_(query.is_pattern_) {
|
| -}
|
| -
|
| -Query::~Query() {
|
| -}
|
| -
|
| -Query Query::String(const std::string& str) {
|
| - return Query(str);
|
| -}
|
| -
|
| -Query Query::Double(double num) {
|
| - return Query(num);
|
| -}
|
| -
|
| -Query Query::Int(int32 num) {
|
| - return Query(static_cast<double>(num));
|
| -}
|
| -
|
| -Query Query::Uint(uint32 num) {
|
| - return Query(static_cast<double>(num));
|
| -}
|
| -
|
| -Query Query::Bool(bool boolean) {
|
| - return Query(boolean ? 1.0 : 0.0);
|
| -}
|
| -
|
| -Query Query::Phase(base::debug::TraceEventPhase phase) {
|
| - return Query(static_cast<double>(phase));
|
| -}
|
| -
|
| -Query Query::Pattern(const std::string& pattern) {
|
| - Query query(pattern);
|
| - query.is_pattern_ = true;
|
| - return query;
|
| -}
|
| -
|
| -bool Query::Evaluate(const TraceEvent& event) const {
|
| - // First check for values that can convert to bool.
|
| -
|
| - // double is true if != 0:
|
| - double bool_value = 0.0;
|
| - bool is_bool = GetAsDouble(event, &bool_value);
|
| - if (is_bool)
|
| - return (bool_value != 0.0);
|
| -
|
| - // string is true if it is non-empty:
|
| - std::string str_value;
|
| - bool is_str = GetAsString(event, &str_value);
|
| - if (is_str)
|
| - return !str_value.empty();
|
| -
|
| - DCHECK(type_ == QUERY_BOOLEAN_OPERATOR)
|
| - << "Invalid query: missing boolean expression";
|
| - DCHECK(left_.get() && (right_.get() || is_unary_operator()));
|
| -
|
| - if (is_comparison_operator()) {
|
| - DCHECK(left().is_value() && right().is_value())
|
| - << "Invalid query: comparison operator used between event member and "
|
| - "value.";
|
| - bool compare_result = false;
|
| - if (CompareAsDouble(event, &compare_result))
|
| - return compare_result;
|
| - else if (CompareAsString(event, &compare_result))
|
| - return compare_result;
|
| - return false;
|
| - } else {
|
| - switch (operator_) {
|
| - case OP_AND:
|
| - return left().Evaluate(event) && right().Evaluate(event);
|
| - case OP_OR:
|
| - return left().Evaluate(event) || right().Evaluate(event);
|
| - case OP_NOT:
|
| - return !left().Evaluate(event);
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| - }
|
| -
|
| - NOTREACHED();
|
| - return false;
|
| -}
|
| -
|
| -bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const {
|
| - double lhs, rhs;
|
| - if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs))
|
| - return false;
|
| - switch (operator_) {
|
| - case OP_EQ:
|
| - *result = (lhs == rhs);
|
| - return true;
|
| - case OP_NE:
|
| - *result = (lhs != rhs);
|
| - return true;
|
| - case OP_LT:
|
| - *result = (lhs < rhs);
|
| - return true;
|
| - case OP_LE:
|
| - *result = (lhs <= rhs);
|
| - return true;
|
| - case OP_GT:
|
| - *result = (lhs > rhs);
|
| - return true;
|
| - case OP_GE:
|
| - *result = (lhs >= rhs);
|
| - return true;
|
| - default:
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool Query::CompareAsString(const TraceEvent& event, bool* result) const {
|
| - std::string lhs, rhs;
|
| - if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs))
|
| - return false;
|
| - switch (operator_) {
|
| - case OP_EQ:
|
| - if (right().is_pattern_)
|
| - *result = MatchPattern(lhs, rhs);
|
| - else if (left().is_pattern_)
|
| - *result = MatchPattern(rhs, lhs);
|
| - else
|
| - *result = (lhs == rhs);
|
| - return true;
|
| - case OP_NE:
|
| - if (right().is_pattern_)
|
| - *result = !MatchPattern(lhs, rhs);
|
| - else if (left().is_pattern_)
|
| - *result = !MatchPattern(rhs, lhs);
|
| - else
|
| - *result = (lhs != rhs);
|
| - return true;
|
| - case OP_LT:
|
| - *result = (lhs < rhs);
|
| - return true;
|
| - case OP_LE:
|
| - *result = (lhs <= rhs);
|
| - return true;
|
| - case OP_GT:
|
| - *result = (lhs > rhs);
|
| - return true;
|
| - case OP_GE:
|
| - *result = (lhs >= rhs);
|
| - return true;
|
| - default:
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
|
| - double* num) const {
|
| - DCHECK(type_ == QUERY_ARITHMETIC_OPERATOR);
|
| - DCHECK(left_.get() && (right_.get() || is_unary_operator()));
|
| -
|
| - double lhs = 0, rhs = 0;
|
| - if (!left().GetAsDouble(event, &lhs))
|
| - return false;
|
| - if (!is_unary_operator() && !right().GetAsDouble(event, &rhs))
|
| - return false;
|
| -
|
| - switch (operator_) {
|
| - case OP_ADD:
|
| - *num = lhs + rhs;
|
| - return true;
|
| - case OP_SUB:
|
| - *num = lhs - rhs;
|
| - return true;
|
| - case OP_MUL:
|
| - *num = lhs * rhs;
|
| - return true;
|
| - case OP_DIV:
|
| - *num = lhs / rhs;
|
| - return true;
|
| - case OP_MOD:
|
| - *num = static_cast<double>(static_cast<int64>(lhs) %
|
| - static_cast<int64>(rhs));
|
| - return true;
|
| - case OP_NEGATE:
|
| - *num = -lhs;
|
| - return true;
|
| - default:
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
|
| - base::debug::TraceValue value;
|
| - switch (type_) {
|
| - case QUERY_ARITHMETIC_OPERATOR:
|
| - return EvaluateArithmeticOperator(event, num);
|
| - case QUERY_EVENT_MEMBER:
|
| - value = GetMemberValue(event);
|
| - if (value.type() == base::debug::TraceValue::TRACE_TYPE_DOUBLE) {
|
| - *num = value.as_double();
|
| - return true;
|
| - }
|
| - return false;
|
| - case QUERY_NUMBER:
|
| - *num = number_;
|
| - return true;
|
| - default:
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
|
| - base::debug::TraceValue value;
|
| - switch (type_) {
|
| - case QUERY_EVENT_MEMBER:
|
| - value = GetMemberValue(event);
|
| - if (value.is_string()) {
|
| - *str = value.as_string();
|
| - return true;
|
| - }
|
| - return false;
|
| - case QUERY_STRING:
|
| - *str = string_;
|
| - return true;
|
| - default:
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -base::debug::TraceValue Query::GetMemberValue(const TraceEvent& event) const {
|
| - DCHECK(type_ == QUERY_EVENT_MEMBER);
|
| -
|
| - // This could be a request for a member of |event| or a member of |event|'s
|
| - // associated event. Store the target event in the_event:
|
| - const TraceEvent* the_event = (member_ < OTHER_PID) ?
|
| - &event : event.other_event;
|
| -
|
| - // Request for member of associated event, but there is no associated event.
|
| - if (!the_event)
|
| - return base::debug::TraceValue();
|
| -
|
| - switch (member_) {
|
| - case EVENT_PID:
|
| - case OTHER_PID:
|
| - return static_cast<double>(the_event->thread.process_id);
|
| - case EVENT_TID:
|
| - case OTHER_TID:
|
| - return static_cast<double>(the_event->thread.thread_id);
|
| - case EVENT_TIME:
|
| - case OTHER_TIME:
|
| - return the_event->timestamp;
|
| - case EVENT_DURATION:
|
| - {
|
| - double duration;
|
| - if (the_event->GetAbsTimeToOtherEvent(&duration))
|
| - return duration;
|
| - else
|
| - return base::debug::TraceValue();
|
| - }
|
| - case EVENT_PHASE:
|
| - case OTHER_PHASE:
|
| - return static_cast<double>(the_event->phase);
|
| - case EVENT_CATEGORY:
|
| - case OTHER_CATEGORY:
|
| - return the_event->category;
|
| - case EVENT_NAME:
|
| - case OTHER_NAME:
|
| - return the_event->name;
|
| - case EVENT_HAS_ARG:
|
| - case OTHER_HAS_ARG:
|
| - // Search for the argument name and return true if found.
|
| - return static_cast<double>((the_event->arg_strings.find(string_) !=
|
| - the_event->arg_strings.end()) ||
|
| - (the_event->arg_numbers.find(string_) !=
|
| - the_event->arg_numbers.end()) ? 1 : 0);
|
| - case EVENT_ARG:
|
| - case OTHER_ARG:
|
| - {
|
| - // Search for the argument name and return its value if found.
|
| -
|
| - std::map<std::string, std::string>::const_iterator str_i =
|
| - the_event->arg_strings.find(string_);
|
| - if (str_i != the_event->arg_strings.end())
|
| - return str_i->second;
|
| -
|
| - std::map<std::string, double>::const_iterator num_i =
|
| - the_event->arg_numbers.find(string_);
|
| - if (num_i != the_event->arg_numbers.end())
|
| - return num_i->second;
|
| -
|
| - return base::debug::TraceValue();
|
| - }
|
| - case EVENT_HAS_OTHER:
|
| - {
|
| - // return 1.0 (true) if the other event exists
|
| - double result = event.other_event ? 1.0 : 0.0;
|
| - return result;
|
| - }
|
| - default:
|
| - NOTREACHED();
|
| - return base::debug::TraceValue();
|
| - }
|
| -}
|
| -
|
| -Query::Query(const std::string& str)
|
| - : type_(QUERY_STRING),
|
| - operator_(OP_INVALID),
|
| - member_(EVENT_INVALID),
|
| - number_(0),
|
| - string_(str),
|
| - is_pattern_(false) {
|
| -}
|
| -
|
| -Query::Query(double num)
|
| - : type_(QUERY_NUMBER),
|
| - operator_(OP_INVALID),
|
| - member_(EVENT_INVALID),
|
| - number_(num),
|
| - is_pattern_(false) {
|
| -}
|
| -const Query& Query::left() const {
|
| - return left_->query();
|
| -}
|
| -
|
| -const Query& Query::right() const {
|
| - return right_->query();
|
| -}
|
| -
|
| -Query Query::operator==(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_EQ);
|
| -}
|
| -
|
| -Query Query::operator!=(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_NE);
|
| -}
|
| -
|
| -Query Query::operator<(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_LT);
|
| -}
|
| -
|
| -Query Query::operator<=(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_LE);
|
| -}
|
| -
|
| -Query Query::operator>(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_GT);
|
| -}
|
| -
|
| -Query Query::operator>=(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_GE);
|
| -}
|
| -
|
| -Query Query::operator&&(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_AND);
|
| -}
|
| -
|
| -Query Query::operator||(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_OR);
|
| -}
|
| -
|
| -Query Query::operator!() const {
|
| - return Query(*this, OP_NOT);
|
| -}
|
| -
|
| -Query Query::operator+(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_ADD);
|
| -}
|
| -
|
| -Query Query::operator-(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_SUB);
|
| -}
|
| -
|
| -Query Query::operator*(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_MUL);
|
| -}
|
| -
|
| -Query Query::operator/(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_DIV);
|
| -}
|
| -
|
| -Query Query::operator%(const Query& rhs) const {
|
| - return Query(*this, rhs, OP_MOD);
|
| -}
|
| -
|
| -Query Query::operator-() const {
|
| - return Query(*this, OP_NEGATE);
|
| -}
|
| -
|
| -
|
| -Query::Query(const Query& left, const Query& right, Operator binary_op)
|
| - : operator_(binary_op),
|
| - left_(new QueryNode(left)),
|
| - right_(new QueryNode(right)),
|
| - member_(EVENT_INVALID),
|
| - number_(0) {
|
| - type_ = (binary_op < OP_ADD ?
|
| - QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
|
| -}
|
| -
|
| -Query::Query(const Query& left, Operator unary_op)
|
| - : operator_(unary_op),
|
| - left_(new QueryNode(left)),
|
| - member_(EVENT_INVALID),
|
| - number_(0) {
|
| - type_ = (unary_op < OP_ADD ?
|
| - QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
|
| -}
|
| -
|
| -namespace {
|
| -
|
| -// Search |events| for |query| and add matches to |output|.
|
| -size_t FindMatchingEvents(const std::vector<TraceEvent>& events,
|
| - const Query& query,
|
| - TraceAnalyzer::TraceEventVector* output) {
|
| - for (size_t i = 0; i < events.size(); ++i) {
|
| - if (query.Evaluate(events[i]))
|
| - output->push_back(&events[i]);
|
| - }
|
| - return output->size();
|
| -}
|
| -
|
| -bool ParseEventsFromJson(const std::string& json,
|
| - std::vector<TraceEvent>* output) {
|
| - scoped_ptr<base::Value> root;
|
| - root.reset(base::JSONReader::Read(json, false));
|
| -
|
| - ListValue* root_list = NULL;
|
| - if (!root.get() || !root->GetAsList(&root_list))
|
| - return false;
|
| -
|
| - for (size_t i = 0; i < root_list->GetSize(); ++i) {
|
| - Value* item = NULL;
|
| - if (root_list->Get(i, &item)) {
|
| - TraceEvent event;
|
| - if (event.SetFromJSON(item))
|
| - output->push_back(event);
|
| - else
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// TraceAnalyzer
|
| -
|
| -TraceAnalyzer::TraceAnalyzer() : allow_assocation_changes_(true) {
|
| -}
|
| -
|
| -TraceAnalyzer::~TraceAnalyzer() {
|
| -}
|
| -
|
| -// static
|
| -TraceAnalyzer* TraceAnalyzer::Create(const std::string& json_events) {
|
| - scoped_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer());
|
| - if (analyzer->SetEvents(json_events))
|
| - return analyzer.release();
|
| - return NULL;
|
| -}
|
| -
|
| -bool TraceAnalyzer::SetEvents(const std::string& json_events) {
|
| - raw_events_.clear();
|
| - if (!ParseEventsFromJson(json_events, &raw_events_))
|
| - return false;
|
| - std::stable_sort(raw_events_.begin(), raw_events_.end());
|
| - ParseMetadata();
|
| - return true;
|
| -}
|
| -
|
| -void TraceAnalyzer::AssociateBeginEndEvents() {
|
| - using namespace trace_analyzer;
|
| -
|
| - Query begin(Query(EVENT_PHASE) ==
|
| - Query::Phase(base::debug::TRACE_EVENT_PHASE_BEGIN));
|
| - Query end(Query(EVENT_PHASE) ==
|
| - Query::Phase(base::debug::TRACE_EVENT_PHASE_END));
|
| - Query match(Query(EVENT_NAME) == Query(OTHER_NAME) &&
|
| - Query(EVENT_CATEGORY) == Query(OTHER_CATEGORY) &&
|
| - Query(EVENT_TID) == Query(OTHER_TID) &&
|
| - Query(EVENT_PID) == Query(OTHER_PID));
|
| -
|
| - AssociateEvents(begin, end, match);
|
| -}
|
| -
|
| -void TraceAnalyzer::AssociateEvents(const Query& first,
|
| - const Query& second,
|
| - const Query& match) {
|
| - DCHECK(allow_assocation_changes_) << "AssociateEvents not allowed after "
|
| - "FindEvents";
|
| -
|
| - // Search for matching begin/end event pairs. When a matching end is found,
|
| - // it is associated with the begin event.
|
| - std::vector<TraceEvent*> begin_stack;
|
| - for (size_t event_index = 0; event_index < raw_events_.size();
|
| - ++event_index) {
|
| -
|
| - TraceEvent& this_event = raw_events_[event_index];
|
| -
|
| - if (first.Evaluate(this_event)) {
|
| - begin_stack.push_back(&this_event);
|
| - } else if (second.Evaluate(this_event)) {
|
| - // Search stack for matching begin, starting from end.
|
| - for (int stack_index = static_cast<int>(begin_stack.size()) - 1;
|
| - stack_index >= 0; --stack_index) {
|
| - TraceEvent& begin_event = *begin_stack[stack_index];
|
| -
|
| - // Temporarily set other to test against the match query.
|
| - const TraceEvent* other_backup = begin_event.other_event;
|
| - begin_event.other_event = &this_event;
|
| - if (match.Evaluate(begin_event)) {
|
| - // Found a matching begin/end pair.
|
| - // Set event association:
|
| - this_event.other_event = &begin_event;
|
| - // Erase the matching begin event index from the stack.
|
| - begin_stack.erase(begin_stack.begin() + stack_index);
|
| - break;
|
| - }
|
| -
|
| - // Not a match, restore original other and continue.
|
| - begin_event.other_event = other_backup;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) {
|
| - allow_assocation_changes_ = false;
|
| - output->clear();
|
| - return FindMatchingEvents(raw_events_, query, output);
|
| -}
|
| -
|
| -const TraceEvent* TraceAnalyzer::FindOneEvent(const Query& query) {
|
| - TraceEventVector output;
|
| - if (FindEvents(query, &output) > 0)
|
| - return output.front();
|
| - return NULL;
|
| -}
|
| -
|
| -const std::string& TraceAnalyzer::GetThreadName(
|
| - const TraceEvent::ProcessThreadID& thread) {
|
| - // If thread is not found, just add and return empty string.
|
| - return thread_names_[thread];
|
| -}
|
| -
|
| -void TraceAnalyzer::ParseMetadata() {
|
| - for (size_t i = 0; i < raw_events_.size(); ++i) {
|
| - TraceEvent& this_event = raw_events_[i];
|
| - // Check for thread name metadata.
|
| - if (this_event.phase != base::debug::TRACE_EVENT_PHASE_METADATA ||
|
| - this_event.name != "thread_name")
|
| - continue;
|
| - std::map<std::string, std::string>::const_iterator string_it =
|
| - this_event.arg_strings.find("name");
|
| - if (string_it != this_event.arg_strings.end())
|
| - thread_names_[this_event.thread] = string_it->second;
|
| - }
|
| -}
|
| -
|
| -} // namespace trace_analyzer
|
| -
|
|
|