1 // Copyright 2022 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_METRICS_LOGS_EVENT_MANAGER_H_ 6 #define COMPONENTS_METRICS_METRICS_LOGS_EVENT_MANAGER_H_ 7 8 #include "base/memory/raw_ptr.h" 9 #include "base/observer_list.h" 10 #include "base/strings/string_piece.h" 11 #include "components/metrics/metrics_log.h" 12 #include "third_party/abseil-cpp/absl/types/optional.h" 13 14 namespace metrics { 15 16 // TODO(crbug/1363747): Add unit tests for the various calls to the notify 17 // functions in ReportingService and UnsentLogStore. 18 class MetricsLogsEventManager { 19 public: 20 enum class LogEvent { 21 // The log was staged (queued to be uploaded). 22 kLogStaged, 23 // The log was discarded. 24 kLogDiscarded, 25 // The log was trimmed. 26 kLogTrimmed, 27 // The log has been sent out and is currently being uploaded. 28 kLogUploading, 29 // The log was successfully uploaded. 30 kLogUploaded, 31 // The log was created. 32 kLogCreated, 33 }; 34 35 enum class CreateReason { 36 kUnknown, 37 // The log is a periodic log, which are created at regular intervals. 38 kPeriodic, 39 // The log was created due to the UMA/UKM service shutting down. 40 kServiceShutdown, 41 // The log was loaded from a previous session. 42 kLoadFromPreviousSession, 43 // The log was created due to the browser being backgrounded. 44 kBackgrounded, 45 // The log was created due to the browser being foregrounded. 46 kForegrounded, 47 // The log was created due to a new alternate ongoing log store being set. 48 kAlternateOngoingLogStoreSet, 49 // The log was created due to the alternate ongoing log store being unset. 50 kAlternateOngoingLogStoreUnset, 51 // The log was created due to the previous session having stability metrics 52 // to report. 53 kStability, 54 // The log was fully created and provided by a metrics provider. 55 kIndependent, 56 }; 57 58 class Observer : public base::CheckedObserver { 59 public: 60 virtual void OnLogCreated(base::StringPiece log_hash, 61 base::StringPiece log_data, 62 base::StringPiece log_timestamp, 63 CreateReason reason) = 0; 64 virtual void OnLogEvent(MetricsLogsEventManager::LogEvent event, 65 base::StringPiece log_hash, 66 base::StringPiece message) = 0; OnLogType(absl::optional<MetricsLog::LogType> log_type)67 virtual void OnLogType(absl::optional<MetricsLog::LogType> log_type) {} 68 69 protected: 70 Observer() = default; 71 ~Observer() override = default; 72 }; 73 74 // Helper class used to indicate that UMA logs created while an instance of 75 // this class is in scope are of a certain type. Only one instance of this 76 // class should exist at a time. 77 class ScopedNotifyLogType { 78 public: 79 ScopedNotifyLogType(MetricsLogsEventManager* logs_event_manager, 80 MetricsLog::LogType log_type); 81 82 ScopedNotifyLogType(const ScopedNotifyLogType& other) = delete; 83 ScopedNotifyLogType& operator=(const ScopedNotifyLogType& other) = delete; 84 85 ~ScopedNotifyLogType(); 86 87 private: 88 const raw_ptr<MetricsLogsEventManager> logs_event_manager_; 89 90 // Used to ensure that only one instance of this class exists at a time. 91 static bool instance_exists_; 92 }; 93 94 MetricsLogsEventManager(); 95 96 MetricsLogsEventManager(const MetricsLogsEventManager&) = delete; 97 MetricsLogsEventManager& operator=(const MetricsLogsEventManager&) = delete; 98 99 ~MetricsLogsEventManager(); 100 101 void AddObserver(Observer* observer); 102 void RemoveObserver(Observer* observer); 103 104 // Notifies observers that a log was newly created and is now known by the 105 // metrics service. This may occur when closing a log, or when loading a log 106 // from persistent storage. |log_hash| is the SHA1 hash of the log data, used 107 // to uniquely identify the log. This hash may be re-used to notify that an 108 // event occurred on the log (e.g., the log was trimmed, uploaded, etc.). See 109 // NotifyLogEvent(). |log_data| is the compressed serialized log protobuf 110 // (see UnsentLogStore::LogInfo for more details on the compression). 111 // |log_timestamp| is the time at which the log was closed. 112 void NotifyLogCreated(base::StringPiece log_hash, 113 base::StringPiece log_data, 114 base::StringPiece log_timestamp, 115 CreateReason reason); 116 117 // Notifies observers that an event |event| occurred on the log associated 118 // with |log_hash|. Optionally, a |message| can be associated with the event. 119 // In particular, for |kLogDiscarded|, |message| is the reason the log was 120 // discarded (e.g., log is ill-formed). For |kLogTrimmed|, |message| is the 121 // reason why the log was trimmed (e.g., log is too large). 122 void NotifyLogEvent(LogEvent event, 123 base::StringPiece log_hash, 124 base::StringPiece message = ""); 125 126 // Notifies observers that logs that are created after this function is called 127 // are of the type |log_type|. This should only be used in UMA. This info is 128 // not passed through NotifyLogCreated() because the concept of a log type 129 // only exists in UMA, and this class is intended to be re-used across 130 // different metrics collection services (e.g., UKM). 131 // Note: Typically, this should not be called directly. Consider using 132 // ScopedNotifyLogType. 133 void NotifyLogType(absl::optional<MetricsLog::LogType> log_type); 134 135 private: 136 base::ObserverList<Observer> observers_; 137 }; 138 139 } // namespace metrics 140 141 #endif // COMPONENTS_METRICS_METRICS_LOG_EVENT_MANAGER_H_ 142