1 // Copyright 2017 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_METRICS_SYSTEM_SESSION_ANALYZER_SYSTEM_SESSION_ANALYZER_WIN_H_ 6 #define COMPONENTS_METRICS_SYSTEM_SESSION_ANALYZER_SYSTEM_SESSION_ANALYZER_WIN_H_ 7 8 #include <windows.h> 9 10 #include <winevt.h> 11 12 #include <map> 13 #include <memory> 14 #include <utility> 15 #include <vector> 16 17 #include "base/gtest_prod_util.h" 18 #include "base/time/time.h" 19 20 namespace metrics { 21 22 // Analyzes system session events for unclean sessions. Initialization is 23 // expensive and therefore done lazily, as the analyzer is instantiated before 24 // knowing whether it will be used. 25 class SystemSessionAnalyzer { 26 public: 27 enum Status { 28 CLEAN = 0, 29 UNCLEAN = 1, 30 OUTSIDE_RANGE = 2, 31 INITIALIZE_FAILED = 3, 32 FETCH_EVENTS_FAILED = 4, 33 PROCESS_SESSION_FAILED = 5, 34 INSUFFICIENT_DATA = 6, 35 }; 36 37 // Track internal details of what went wrong. 38 enum class ExtendedStatus { 39 NO_FAILURE = 0, 40 RENDER_EVENT_FAILURE = 1, 41 ATTRIBUTE_CNT_MISMATCH = 2, 42 EXPECTED_INT16_TYPE = 3, 43 EXPECTED_FILETIME_TYPE = 4, 44 RETRIEVE_EVENTS_FAILURE = 5, 45 GET_EVENT_INFO_FAILURE = 6, 46 EVTQUERY_FAILED = 7, 47 CREATE_RENDER_CONTEXT_FAILURE = 8, 48 FETCH_EVENTS_FAILURE = 9, 49 EVENT_COUNT_MISMATCH = 10, 50 SESSION_START_MISMATCH = 11, 51 COVERAGE_START_ORDER_FAILURE = 12, 52 EVENT_ORDER_FAILURE = 13, 53 UNEXPECTED_START_EVENT_TYPE = 14, 54 UNEXPECTED_END_EVENT_TYPE = 15, 55 }; 56 57 ExtendedStatus GetExtendedFailureStatus() const; 58 // Set an extended failure status code for easier diagnosing of test failures. 59 // The first extended status code is retained. 60 void SetExtendedFailureStatus(ExtendedStatus); 61 62 // Minimal information about a log event. 63 struct EventInfo { 64 uint16_t event_id; 65 base::Time event_time; 66 }; 67 68 // Creates a SystemSessionAnalyzer that will analyze system sessions based on 69 // events pertaining to as many as |max_session_cnt| of the most recent system 70 // sessions. 71 explicit SystemSessionAnalyzer(uint32_t max_session_cnt); 72 73 SystemSessionAnalyzer(const SystemSessionAnalyzer&) = delete; 74 SystemSessionAnalyzer& operator=(const SystemSessionAnalyzer&) = delete; 75 76 virtual ~SystemSessionAnalyzer(); 77 78 // Returns an analysis status for the system session that contains 79 // |timestamp|. 80 virtual Status IsSessionUnclean(base::Time timestamp); 81 82 protected: 83 // Queries for the next |requested_events|. On success, returns true and 84 // |event_infos| contains up to |requested_events| events ordered from newest 85 // to oldest. 86 // Returns false otherwise. Virtual for unit testing. 87 virtual bool FetchEvents(size_t requested_events, 88 std::vector<EventInfo>* event_infos); 89 90 private: 91 struct EvtHandleCloser { 92 using pointer = EVT_HANDLE; operatorEvtHandleCloser93 void operator()(EVT_HANDLE handle) const { 94 if (handle) 95 ::EvtClose(handle); 96 } 97 }; 98 using EvtHandle = std::unique_ptr<EVT_HANDLE, EvtHandleCloser>; 99 100 FRIEND_TEST_ALL_PREFIXES(SystemSessionAnalyzerTest, FetchEvents); 101 102 bool EnsureInitialized(); 103 bool EnsureHandlesOpened(); 104 bool Initialize(); 105 // Validates that |end| and |start| have sane event IDs and event times. 106 // Updates |coverage_start_| and adds the session to unclean_sessions_ 107 // as appropriate. 108 bool ProcessSession(const EventInfo& end, const EventInfo& start); 109 110 bool GetEventInfo(EVT_HANDLE context, 111 EVT_HANDLE event, 112 SystemSessionAnalyzer::EventInfo* info); 113 EvtHandle CreateRenderContext(); 114 115 // The maximal number of sessions to query events for. 116 uint32_t max_session_cnt_; 117 uint32_t sessions_queried_; 118 119 bool initialized_ = false; 120 bool init_success_ = false; 121 122 // A handle to the query, valid after a successful initialize. 123 EvtHandle query_handle_; 124 // A handle to the event render context, valid after a successful initialize. 125 EvtHandle render_context_; 126 127 // Information about unclean sessions: start time to session duration. 128 std::map<base::Time, base::TimeDelta> unclean_sessions_; 129 130 // Timestamp of the oldest event. 131 base::Time coverage_start_; 132 133 // Track details of what failures occurred. 134 ExtendedStatus extended_status_ = ExtendedStatus::NO_FAILURE; 135 }; 136 137 } // namespace metrics 138 139 #endif // COMPONENTS_METRICS_SYSTEM_SESSION_ANALYZER_SYSTEM_SESSION_ANALYZER_WIN_H_ 140