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

Side by Side Diff: remoting/base/tracer.h

Issue 3169047: Add in some infrastructure to make tracing of logical requests broken over async callbacks easier. (Closed) Base URL: git://codf21.jail.google.com/chromium.git
Patch Set: sent Created 10 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
« no previous file with comments | « remoting/base/protocol/trace.proto ('k') | remoting/base/tracer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 // Tracer objects uresed to record an annotated timeline of events for use in
6 // gathering performance data. It wraps a TraceBuffer which is the raw data
7 // for a trace. Tracer is threadsafe.
8 //
9 // TraceContext is a singleton that is used to give information for the current
10 // trace. Clients should query TraceContext to find the current tracer and then
11 // use that for logging annotations. TraceContext is threadsafe.
12 //
13 // ScopedTracer pushes a new Tracer on the TraceContext. It's scoped in that
14 // this tracer is popped off the context when ScopedTracer goes out of scope.
15 // However, if a call to NewTracedMethod is made while the ScopedTracer is in
16 // scope, then a reference to the Tracer will be kept in the resulting Task and
17 // repushed onto the stack when the Task is run. Conceptually, this simulates
18 // the current context being continued when the Task is invoked. You usually
19 // will want to declare a ScopedTracer at the start of a logical flow of
20 // operations.
21 //
22 // Example Usage:
23 //
24 // void Decoder::StartDecode() {
25 // ScopedTracer tracer("decode_start");
26 //
27 // TraceContext::current()->PrintString("Decode starting");
28 //
29 // // DoDecode takes 2 parameters. The first is a callback invoked for each
30 // // finished frame of output. The second is invoked when the task is done.
31 // DoDecode(NewTracedMethod(this, &Decoder::OnFrameOutput),
32 // NewTracedMethod(this, &Decoder::DecodeDone));
33 // }
34 // }
35 //
36 // void Decoder::OnFrameOutput() {
37 // TraceContext::current()->PrintString("Frame outputed");
38 // ...
39 // }
40 //
41 // void Decoder::DecodeDone() {
42 // TraceContext::current()->PrintString("decode done");
43 // ...
44 // }
45 //
46 // For each call of StartDecode(), the related calls to OnFrameOutput() and
47 // DecodeDone() will be annotated to the Tracer created by the ScopedTracer
48 // declaration allowing for creating of timing information over the related
49 // asynchronous Task invocations.
50
51 #ifndef REMOTING_BASE_TRACER_H_
52 #define REMOTING_BASE_TRACER_H_
53
54 #include <string>
55
56 #include "base/lock.h"
57 #include "base/ref_counted.h"
58 #include "base/singleton.h"
59 #include "base/task.h"
60 #include "base/scoped_ptr.h"
61 #include "base/thread_local.h"
62 #include "remoting/base/protocol/trace.pb.h"
63
64 namespace remoting {
65
66 class Tracer : public base::RefCountedThreadSafe<Tracer> {
67 public:
68 // The |name| is just a label for the given tracer. It is recorder into the
69 // trace buffer and printed at the end. Use it specify one logical flow such
70 // as "Host Update Request". The sample_percent is to allow for gathering a
71 // random sampling of the traces. This allows the tracer to be used in a
72 // high-frequency code path without spamming the log, or putting undo load on
73 // the system. Use 0.0 to disable the tracer completely, and 1.0 to log
74 // everything.
75 Tracer(const std::string& name, double sample_percent);
76
77 // TODO(ajwong): Consider using an ostream interface similar to DLOG.
78 void PrintString(const std::string& s);
79
80 void OutputTrace();
81
82 private:
83 friend class base::RefCountedThreadSafe<Tracer>;
84 virtual ~Tracer();
85
86 Lock lock_;
87 scoped_ptr<TraceBuffer> buffer_;
88
89 DISALLOW_COPY_AND_ASSIGN(Tracer);
90 };
91
92 class TraceContext {
93 public:
94 // Set the current tracer.
95 static Tracer* tracer() {
96 return Get()->GetTracerInternal();
97 }
98
99 static void PushTracer(Tracer* tracer) {
100 Get()->PushTracerInternal(tracer);
101 }
102
103 static void PopTracer() {
104 Get()->PopTracerInternal();
105 }
106
107 static TraceContext* Get() {
108 TraceContext* context =
109 Singleton<base::ThreadLocalPointer<TraceContext> >::get()->Get();
110 if (context == NULL) {
111 context = new TraceContext();
112 context->PushTracerInternal(new Tracer("default", 0.0));
113 Singleton<base::ThreadLocalPointer<TraceContext> >::get()->Set(context);
114 }
115 return context;
116 }
117
118 private:
119 TraceContext() {
120 }
121
122 ~TraceContext() {}
123
124 void PushTracerInternal(Tracer* tracer) { tracers_.push_back(tracer); }
125
126 void PopTracerInternal() { tracers_.pop_back(); }
127
128 Tracer* GetTracerInternal() { return tracers_.back(); }
129
130 std::vector<scoped_refptr<Tracer> > tracers_;
131
132 DISALLOW_COPY_AND_ASSIGN(TraceContext);
133 };
134
135 // Used to create a new tracer that NewRunnableMethod can propogate from.
136 //
137 // Declare this at the logical start of a "trace." Calls to NewTracedMethod
138 // that are done with the ScopedTracer object is alive will take a reference
139 // to this tracer. When such a method is invoked, it will push the trace back
140 // onto the top of the TraceContext stack. The result is that all asynchronous
141 // tasks that are part of one logical flow will share the same trace.
142 class ScopedTracer {
143 public:
144 ScopedTracer(const std::string& name) {
145 scoped_refptr<Tracer> tracer = new Tracer(name, 1.00);
146 TraceContext::PushTracer(tracer);
147 }
148
149 ~ScopedTracer() {
150 TraceContext::PopTracer();
151 }
152 };
153
154 // This is experimental code. I'm creating a set of analogues to
155 // the NewRunnableMethod functions called NewTracedMethod, which should be
156 // API equivalent to the former. In fact, they must be enabled by setting
157 // USE_TRACE 1 for now.
158 //
159 // The idea is to add hooks for performance traces into the Task/Callback
160 // mechanisms. If it works well enough, will think about generalizing into the
161 // original NewRunnableMethod and NewCallback systems.
162 #if defined(USE_TRACE)
163
164 template <class T, class Method, class Params>
165 class TracedMethod : public RunnableMethod<T, Method, Params> {
166 public:
167 TracedMethod(T* obj, Method meth, const Params& params)
168 : RunnableMethod<T, Method, Params>(obj, meth, params),
169 tracer_(TraceContext::tracer()) {
170 }
171
172 virtual ~TracedMethod() {
173 }
174
175 virtual void Run() {
176 TraceContext::PushTracer(tracer_);
177 RunnableMethod<T, Method, Params>::Run();
178 TraceContext::PopTracer();
179 }
180
181 private:
182 scoped_refptr<Tracer> tracer_;
183 };
184
185 template <class T, class Method>
186 inline CancelableTask* NewTracedMethod(T* object, Method method) {
187 return new TracedMethod<T, Method, Tuple0>(object, method, MakeTuple());
188 }
189
190 template <class T, class Method, class A>
191 inline CancelableTask* NewTracedMethod(T* object, Method method, const A& a) {
192 return new TracedMethod<T, Method, Tuple1<A> >(object,
193 method,
194 MakeTuple(a));
195 }
196
197 template <class T, class Method, class A, class B>
198 inline CancelableTask* NewTracedMethod(T* object, Method method,
199 const A& a, const B& b) {
200 return new TracedMethod<T, Method, Tuple2<A, B> >(object, method,
201 MakeTuple(a, b));
202 }
203
204 template <class T, class Method, class A, class B, class C>
205 inline CancelableTask* NewTracedMethod(T* object, Method method,
206 const A& a, const B& b, const C& c) {
207 return new TracedMethod<T, Method, Tuple3<A, B, C> >(object, method,
208 MakeTuple(a, b, c));
209 }
210
211 template <class T, class Method, class A, class B, class C, class D>
212 inline CancelableTask* NewTracedMethod(T* object, Method method,
213 const A& a, const B& b,
214 const C& c, const D& d) {
215 return new TracedMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
216 MakeTuple(a, b,
217 c, d));
218 }
219
220 template <class T, class Method, class A, class B, class C, class D, class E>
221 inline CancelableTask* NewTracedMethod(T* object, Method method,
222 const A& a, const B& b,
223 const C& c, const D& d, const E& e) {
224 return new TracedMethod<T,
225 Method,
226 Tuple5<A, B, C, D, E> >(object,
227 method,
228 MakeTuple(a, b, c, d, e));
229 }
230
231 template <class T, class Method, class A, class B, class C, class D, class E,
232 class F>
233 inline CancelableTask* NewTracedMethod(T* object, Method method,
234 const A& a, const B& b,
235 const C& c, const D& d,
236 const E& e, const F& f) {
237 return new TracedMethod<T,
238 Method,
239 Tuple6<A, B, C, D, E, F> >(object,
240 method,
241 MakeTuple(a, b, c, d, e,
242 f));
243 }
244
245 template <class T, class Method, class A, class B, class C, class D, class E,
246 class F, class G>
247 inline CancelableTask* NewTracedMethod(T* object, Method method,
248 const A& a, const B& b,
249 const C& c, const D& d, const E& e,
250 const F& f, const G& g) {
251 return new TracedMethod<T,
252 Method,
253 Tuple7<A, B, C, D, E, F, G> >(object,
254 method,
255 MakeTuple(a, b, c, d,
256 e, f, g));
257 }
258
259 #else
260 # define NewTracedMethod NewRunnableMethod
261 #endif
262
263 } // namespace remoting
264
265 #endif // REMOTING_BASE_TRACER_H_
OLDNEW
« no previous file with comments | « remoting/base/protocol/trace.proto ('k') | remoting/base/tracer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698