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