Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: base/debug/trace_event_test_utils.h

Issue 7981004: add classes trace_analyzer::Query and TraceAnalyzer to make it easy to search through trace data (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more comments Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Use trace::Query with TraceAnalyzer to search for specific trace events.
6 // Queries can be combined using boolean and comparison operators.
7 //
8 // Construct TraceAnalyzer with the json trace string retrieved from TraceLog:
9 // TraceAnalyzer analyzer(json_events);
10 // ConstEventPtrVector events;
11 //
12 // To find begin events called "my_event" with duration > 1 second:
13 // Query q = (Query(EVENT_NAME) == "my_event" &&
14 // Query(EVENT_PHASE) == TRACE_EVENT_PHASE_BEGIN &&
15 // Query(EVENT_DURATION) > 1000000.0);
16 // analyzer.FindEvents(q, &events);
17 //
18 // By default, only begin/end events on the same thread will ever be associated.
19 // If the test needs to analyze events that begin and end on different threads,
20 // it can specify custom assocations. The typical procedure is to include a
21 // unique ID as one of the TRACE_EVENT arguments that only matches a single
22 // begin/end pair across all Chrome processes and threads.
23 //
24 // For example:
25 // [Thread 1]
26 // TRACE_EVENT_BEGIN1("test_latency", "timing1", "id", 3);
27 // [Later, on Thread 2]
28 // TRACE_EVENT_END1("test_latency", "timing1", "id", 3);
29 // Then, to associate these begin/end pairs:
30 // Query begin(Query(EVENT_PHASE) == TRACE_EVENT_PHASE_BEGIN);
31 // Query end(Query(EVENT_PHASE) == TRACE_EVENT_PHASE_END);
32 // Query match(Query(EVENT_NAME) == Query(OTHER_NAME) &&
33 // Query(EVENT_ARG, "id") == Query(OTHER_ARG, "id"));
34 // analyzer.AssociateEvents(begin, end, match);
35 // Then you can search for "timing1" events and evaluate their durations.
36
37
38 #ifndef BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_
39 #define BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_
40 #pragma once
41
42 #include "base/debug/trace_event.h"
43
44 namespace base {
45 namespace debug {
46
47 // By using the trace namespace, tests can use short terms like "Query".
48 namespace trace {
49
50 class QueryNode;
51
52 // Pass these values to Query to compare with the corresponding member of a
53 // TestTraceEvent.
54 enum TraceEventMember {
55 EVENT_INVALID,
56 // Use these to access the event members:
57 EVENT_PID,
58 EVENT_TID,
59 // Return the timestamp of the event in microseconds since epoch.
60 EVENT_TIME,
61 // Return the duration of an event in seconds.
62 // Only works for events with associated BEGIN/END: Query(OTHER_EXISTS).
63 EVENT_DURATION,
64 EVENT_PHASE,
65 EVENT_CATEGORY,
66 EVENT_NAME,
67 EVENT_HAS_ARG,
68 EVENT_ARG,
69 // Return true if associated event exists.
70 // (Typically BEGIN for END or END for BEGIN).
71 EVENT_HAS_OTHER,
72 // Use these to access the associated event's members:
73 OTHER_PID,
74 OTHER_TID,
75 OTHER_TIME,
76 OTHER_PHASE,
77 OTHER_CATEGORY,
78 OTHER_NAME,
79 OTHER_HAS_ARG,
80 OTHER_ARG
81 };
82
83 class Query {
84 public:
85 // Compare with the given member.
86 Query(TraceEventMember member);
87
88 // Compare with the given member argument value.
89 Query(TraceEventMember member, const std::string& arg_name);
90
91 // Compare with the given string.
92 Query(const std::string& str);
93 Query(const char* str);
94
95 // Compare with the given number.
96 Query(double num);
97 Query(float num);
98 Query(int num);
99 Query(uint32 num);
100
101 // Compare with the given bool.
102 Query(bool boolean);
103
104 // Compare with the given phase.
105 Query(TraceEventPhase phase);
106
107 Query(const Query& query);
108
109 ~Query();
110
111 // Compare with the given string pattern. Only works with == and != operators.
112 // Example: Query(EVENT_NAME) == Query::Pattern("bla_*")
113 static Query Pattern(const std::string& pattern);
114
115 // Common queries:
116
117 // Find BEGIN events that have a corresponding END event.
118 static Query MatchBeginWithEnd() {
119 return (Query(EVENT_PHASE) == TRACE_EVENT_PHASE_BEGIN) &&
120 Query(EVENT_HAS_OTHER);
121 }
122
123 // Find END events that have a corresponding BEGIN event.
124 static Query MatchEndWithBegin() {
125 return (Query(EVENT_PHASE) == TRACE_EVENT_PHASE_END) &&
126 Query(EVENT_HAS_OTHER);
127 }
128
129 // Find BEGIN events of given |name| which also have associated END events.
130 static Query MatchBeginName(const std::string& name) {
131 return (Query(EVENT_NAME) == name) && MatchBeginWithEnd();
132 }
133
134 // Match given Process ID and Thread ID.
135 static Query MatchPidTid(base::debug::TestTraceEvent::PidTid pid_tid) {
136 return (Query(EVENT_PID) == pid_tid.pid) &&
137 (Query(EVENT_TID) == pid_tid.tid);
138 }
139
140 // Match BEGIN/END event pair that spans multiple threads.
141 static Query MatchCrossPidTid() {
142 return (Query(EVENT_PID) != Query(OTHER_PID)) ||
143 (Query(EVENT_TID) != Query(OTHER_TID));
144 }
145
146 // Boolean operators:
147 Query operator==(const Query& rhs) const;
148 Query operator!=(const Query& rhs) const;
149 Query operator< (const Query& rhs) const;
150 Query operator<=(const Query& rhs) const;
151 Query operator> (const Query& rhs) const;
152 Query operator>=(const Query& rhs) const;
153 Query operator&&(const Query& rhs) const;
154 Query operator||(const Query& rhs) const;
155 Query operator! () const;
156
157 // Arithmetic operators:
158 Query operator+(const Query& rhs) const;
159 Query operator-(const Query& rhs) const;
160 Query operator*(const Query& rhs) const;
161 Query operator/(const Query& rhs) const;
162 Query operator%(const Query& rhs) const;
163 Query operator-() const;
164
165 // Return true if the given event matches this query tree.
166 // This is a recursive method that walks the query tree.
167 bool Evaluate(const TestTraceEvent& event) const;
168
169 private:
170 enum Operator {
171 OP_INVALID,
172 // Boolean operators:
173 OP_EQ,
174 OP_NE,
175 OP_LT,
176 OP_LE,
177 OP_GT,
178 OP_GE,
179 OP_AND,
180 OP_OR,
181 OP_NOT,
182 // Arithmetic operators:
183 OP_ADD,
184 OP_SUB,
185 OP_MUL,
186 OP_DIV,
187 OP_MOD,
188 OP_NEGATE
189 };
190
191 enum QueryType {
192 QUERY_BOOLEAN_OPERATOR,
193 QUERY_ARITHMETIC_OPERATOR,
194 QUERY_EVENT_MEMBER,
195 QUERY_NUMBER,
196 QUERY_STRING
197 };
198
199 // Construct a boolean Query that returns (left <binary_op> right).
200 Query(const Query& left, const Query& right, Operator binary_op);
201
202 // Construct a boolean Query that returns (<binary_op> left).
203 Query(const Query& left, Operator unary_op);
204
205 // Try to compare left_ against right_ based on operator_.
206 // If either left or right does not convert to double, false is returned.
207 // Otherwise, true is returned and |result| is set to the comparison result.
208 bool CompareAsDouble(const TestTraceEvent& event, bool* result) const;
209
210 // Try to compare left_ against right_ based on operator_.
211 // If either left or right does not convert to string, false is returned.
212 // Otherwise, true is returned and |result| is set to the comparison result.
213 bool CompareAsString(const TestTraceEvent& event, bool* result) const;
214
215 // Attempt to convert this Query to a double. On success, true is returned
216 // and the double value is stored in |num|.
217 bool GetAsDouble(const TestTraceEvent& event, double* num) const;
218
219 // Attempt to convert this Query to a string. On success, true is returned
220 // and the string value is stored in |str|.
221 bool GetAsString(const TestTraceEvent& event, std::string* str) const;
222
223 // Evaluate this Query as an arithmetic operator on left_ and right_.
224 bool EvaluateArithmeticOperator(const TestTraceEvent& event,
225 double* num) const;
226
227 // For QUERY_EVENT_MEMBER Query: attempt to get the value of the Query.
228 // The TraceValue will either be TRACE_TYPE_DOUBLE, TRACE_TYPE_STRING,
229 // or if requested member does not exist, it will be TRACE_TYPE_UNDEFINED.
230 TraceValue GetMemberValue(const TestTraceEvent& event) const;
231
232 // Does this Query represent a value?
233 bool is_value() const { return type_ != QUERY_BOOLEAN_OPERATOR; }
234
235 bool is_unary_operator() const {
236 return operator_ == OP_NOT || operator_ == OP_NEGATE;
237 }
238
239 const Query& left() const;
240 const Query& right() const;
241
242 QueryType type_;
243 Operator operator_;
244 scoped_refptr<QueryNode> left_;
245 scoped_refptr<QueryNode> right_;
246 TraceEventMember member_;
247 double number_;
248 std::string string_;
249 bool is_pattern_;
250 };
251
252 // QueryNode allows Query to store a ref-counted query tree.
253 class QueryNode : public RefCounted<QueryNode> {
254 public:
255 QueryNode(const Query& query);
256 const Query& query() const { return query_; }
257
258 private:
259 friend class RefCounted<QueryNode>;
260 ~QueryNode();
261
262 Query query_;
263 };
264
265 } // namespace trace
266
267 // TraceAnalyzer is designed to make tracing-based tests easier to write.
268 class TraceAnalyzer {
269 public:
270 typedef std::vector<base::debug::TestTraceEvent> EventVector;
271 typedef std::vector<const base::debug::TestTraceEvent*> ConstEventPtrVector;
272
273 TraceAnalyzer();
274 TraceAnalyzer(const std::string& json_events);
275 TraceAnalyzer(const EventVector& events);
276 ~TraceAnalyzer();
277
278 // Replace all events with |json_events|.
279 void SetEvents(const std::string& json_events);
280 // Replace all events with |events|.
281 void SetEvents(const EventVector& events);
282
283 // SetEvents calls this internally to match up typical begin/end pairs of
284 // events. This allows Query(OTHER_*) to access the associated event and
285 // enables Query(EVENT_DURATION).
286 // By default, an end event will match the most recent begin event with the
287 // same name, category, process ID and thread ID.
288 void SetDefaultAssociations();
289
290 // Clear existing event associations.
291 void ClearAssociations();
292
293 // By default, matching begin and end events are associated with each other as
294 // described in SetDefaultAssociations.
295 // AssociateEvents can be used to customize begin/end event associations.
296 // The only assumption is that end events occur after begin events.
297 //
298 // |begin| - Eligible begin events match this query.
299 // |end| - Eligible end events match this query.
300 // |match| - This query is run on the begin event. The OTHER event members
301 // will point to an eligible end event. The query should evaluate to
302 // true if the begin/end pair is a match.
303 //
304 // When a match is found, the pair will be associated by having their
305 // other_event member point to each other. Non-matching events are left with
306 // their existing assocations, so you may also want to call ClearAssociations.
307 void AssociateEvents(const trace::Query& begin,
308 const trace::Query& end,
309 const trace::Query& match);
310
311 const EventVector& events() { return raw_events_; }
312
313 const std::string& GetThreadName(const base::debug::TestTraceEvent::PidTid&
314 pid_tid);
315
316 // Find all events that match query and replace output vector.
317 size_t FindEvents(const trace::Query& query,
318 ConstEventPtrVector* output) const;
319
320 // Helper method: find first event that matches query
321 const base::debug::TestTraceEvent* FindEvent(
322 const trace::Query& query) const;
323
324 private:
325 // Read metadata (thread names, etc) from events.
326 void ParseMetadata();
327
328 std::map<base::debug::TestTraceEvent::PidTid, std::string> thread_names_;
329 EventVector raw_events_;
330 };
331
332 } // namespace debug
333 } // namespace base
334
335 #endif // BASE_DEBUG_TRACE_EVENT_TEST_UTILS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698