OLD | NEW |
| (Empty) |
1 // Copyright 2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Declaration of a Windows event trace consumer base class. | |
17 #ifndef BASE_EVENT_TRACE_CONSUMER_H_ | |
18 #define BASE_EVENT_TRACE_CONSUMER_H_ | |
19 | |
20 #include <windows.h> | |
21 #include <wmistr.h> | |
22 #include <evntrace.h> | |
23 #include <vector> | |
24 #include "base/basictypes.h" | |
25 | |
26 namespace omaha { | |
27 | |
28 // This class is a base class that makes it easier to consume events | |
29 // from realtime or file sessions. Concrete consumers need to sublass | |
30 // a specialization of this class and override the ProcessEvent and/or | |
31 // the ProcessBuffer methods to implement the event consumption logic. | |
32 // Usage might look like: | |
33 // class MyConsumer: public EtwTraceConsumerBase<MyConsumer, 1> { | |
34 // protected: | |
35 // static VOID WINAPI ProcessEvent(PEVENT_TRACE event); | |
36 // }; | |
37 // | |
38 // MyConsumer consumer; | |
39 // consumer.OpenFileSession(file_path); | |
40 // consumer.Consume(); | |
41 template <class ImplClass> | |
42 class EtwTraceConsumerBase { | |
43 public: | |
44 // Constructs a closed consumer. | |
45 EtwTraceConsumerBase() { | |
46 } | |
47 | |
48 ~EtwTraceConsumerBase() { | |
49 Close(); | |
50 } | |
51 | |
52 // Opens the named realtime session, which must be existent. | |
53 // Note: You can use OpenRealtimeSession or OpenFileSession | |
54 // to open as many as MAXIMUM_WAIT_OBJECTS (63) sessions at | |
55 // any one time, though only one of them may be a realtime | |
56 // session. | |
57 HRESULT OpenRealtimeSession(const wchar_t* session_name); | |
58 | |
59 // Opens the event trace log in "file_name", which must be a full or | |
60 // relative path to an existing event trace log file. | |
61 // Note: You can use OpenRealtimeSession or OpenFileSession | |
62 // to open as many as kNumSessions at any one time. | |
63 HRESULT OpenFileSession(const wchar_t* file_name); | |
64 | |
65 // Consume all open sessions from beginning to end. | |
66 HRESULT Consume(); | |
67 | |
68 // Close all open sessions. | |
69 HRESULT Close(); | |
70 | |
71 protected: | |
72 // Override in subclasses to handle events. | |
73 static void ProcessEvent(EVENT_TRACE* event) { | |
74 } | |
75 // Override in subclasses to handle buffers. | |
76 static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) { | |
77 buffer; | |
78 return true; // keep going | |
79 } | |
80 | |
81 protected: | |
82 // Currently open sessions. | |
83 std::vector<TRACEHANDLE> trace_handles_; | |
84 | |
85 private: | |
86 // These delegate to ImplClass callbacks with saner signatures. | |
87 static void WINAPI ProcessEventCallback(EVENT_TRACE* event) { | |
88 ImplClass::ProcessEvent(event); | |
89 } | |
90 static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) { | |
91 return ImplClass::ProcessBuffer(buffer); | |
92 } | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(EtwTraceConsumerBase); | |
95 }; | |
96 | |
97 template <class ImplClass> inline | |
98 HRESULT EtwTraceConsumerBase<ImplClass>::OpenRealtimeSession( | |
99 const wchar_t* session_name) { | |
100 EVENT_TRACE_LOGFILE logfile = {}; | |
101 logfile.LoggerName = const_cast<wchar_t*>(session_name); | |
102 logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; | |
103 logfile.BufferCallback = &ProcessBufferCallback; | |
104 logfile.EventCallback = &ProcessEventCallback; | |
105 logfile.Context = this; | |
106 TRACEHANDLE trace_handle = ::OpenTrace(&logfile); | |
107 if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle) | |
108 return HRESULT_FROM_WIN32(::GetLastError()); | |
109 | |
110 trace_handles_.push_back(trace_handle); | |
111 return S_OK; | |
112 } | |
113 | |
114 template <class ImplClass> inline | |
115 HRESULT EtwTraceConsumerBase<ImplClass>::OpenFileSession( | |
116 const wchar_t* file_name) { | |
117 EVENT_TRACE_LOGFILE logfile = {}; | |
118 logfile.LogFileName = const_cast<wchar_t*>(file_name); | |
119 logfile.BufferCallback = &ProcessBufferCallback; | |
120 logfile.EventCallback = &ProcessEventCallback; | |
121 logfile.Context = this; | |
122 TRACEHANDLE trace_handle = ::OpenTrace(&logfile); | |
123 if (reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE) == trace_handle) | |
124 return HRESULT_FROM_WIN32(::GetLastError()); | |
125 | |
126 trace_handles_.push_back(trace_handle); | |
127 return S_OK; | |
128 } | |
129 | |
130 template <class ImplClass> inline | |
131 HRESULT EtwTraceConsumerBase<ImplClass>::Consume() { | |
132 ULONG err = ::ProcessTrace(&trace_handles_[0], | |
133 trace_handles_.size(), | |
134 NULL, | |
135 NULL); | |
136 return HRESULT_FROM_WIN32(err); | |
137 } | |
138 | |
139 template <class ImplClass> inline | |
140 HRESULT EtwTraceConsumerBase<ImplClass>::Close() { | |
141 HRESULT hr = S_OK; | |
142 for (size_t i = 0; i < trace_handles_.size(); ++i) { | |
143 if (NULL != trace_handles_[i]) { | |
144 ULONG ret = ::CloseTrace(trace_handles_[i]); | |
145 trace_handles_[i] = NULL; | |
146 | |
147 if (FAILED(HRESULT_FROM_WIN32(ret))) | |
148 hr = HRESULT_FROM_WIN32(ret); | |
149 } | |
150 | |
151 trace_handles_.clear(); | |
152 } | |
153 | |
154 return hr; | |
155 } | |
156 | |
157 } // namespace omaha | |
158 | |
159 #endif // BASE_EVENT_TRACE_CONSUMER_H_ | |
OLD | NEW |