1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_ 6*6777b538SAndroid Build Coastguard Worker #define COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <memory> 9*6777b538SAndroid Build Coastguard Worker #include <optional> 10*6777b538SAndroid Build Coastguard Worker #include <string> 11*6777b538SAndroid Build Coastguard Worker #include <vector> 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker #include "base/callback_list.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/containers/flat_map.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h" 17*6777b538SAndroid Build Coastguard Worker #include "components/metrics/metrics_logs_event_manager.h" 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Worker namespace metrics { 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker // Observes logs generated by a metrics collection system (UMA and UKM) and 22*6777b538SAndroid Build Coastguard Worker // stores them in-memory. This class also provides a way to export the logs in a 23*6777b538SAndroid Build Coastguard Worker // JSON format, which includes metadata, proto data, as well as the events 24*6777b538SAndroid Build Coastguard Worker // describing the lifecycle of the logs. 25*6777b538SAndroid Build Coastguard Worker class MetricsServiceObserver : public MetricsLogsEventManager::Observer { 26*6777b538SAndroid Build Coastguard Worker public: 27*6777b538SAndroid Build Coastguard Worker // Possible metrics service types. 28*6777b538SAndroid Build Coastguard Worker enum class MetricsServiceType { 29*6777b538SAndroid Build Coastguard Worker UMA, 30*6777b538SAndroid Build Coastguard Worker UKM, 31*6777b538SAndroid Build Coastguard Worker }; 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker // Represents a log and its data. Exposed for testing. 34*6777b538SAndroid Build Coastguard Worker struct Log { 35*6777b538SAndroid Build Coastguard Worker // Represents an event that occurred on the log. An optional message may 36*6777b538SAndroid Build Coastguard Worker // be associated with the event. For example, the event may be 37*6777b538SAndroid Build Coastguard Worker // |kLogTrimmed|, with |message| being "Log size too large". 38*6777b538SAndroid Build Coastguard Worker struct Event { 39*6777b538SAndroid Build Coastguard Worker Event(); 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker Event(const Event&); 42*6777b538SAndroid Build Coastguard Worker Event& operator=(const Event&); 43*6777b538SAndroid Build Coastguard Worker 44*6777b538SAndroid Build Coastguard Worker ~Event(); 45*6777b538SAndroid Build Coastguard Worker 46*6777b538SAndroid Build Coastguard Worker // The type of event. 47*6777b538SAndroid Build Coastguard Worker MetricsLogsEventManager::LogEvent event; 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Worker // The timestamp at which the event occurred. This is the number of 50*6777b538SAndroid Build Coastguard Worker // milliseconds since Epoch. 51*6777b538SAndroid Build Coastguard Worker double timestampMs; 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker // An optional message associated with the event. 54*6777b538SAndroid Build Coastguard Worker std::optional<std::string> message; 55*6777b538SAndroid Build Coastguard Worker }; 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard Worker Log(); 58*6777b538SAndroid Build Coastguard Worker 59*6777b538SAndroid Build Coastguard Worker Log(const Log&); 60*6777b538SAndroid Build Coastguard Worker Log& operator=(const Log&); 61*6777b538SAndroid Build Coastguard Worker 62*6777b538SAndroid Build Coastguard Worker ~Log(); 63*6777b538SAndroid Build Coastguard Worker 64*6777b538SAndroid Build Coastguard Worker // The SHA1 hash of the log's data, used to uniquely identify it. 65*6777b538SAndroid Build Coastguard Worker std::string hash; 66*6777b538SAndroid Build Coastguard Worker 67*6777b538SAndroid Build Coastguard Worker // The time at which the log was closed. This is the number of seconds since 68*6777b538SAndroid Build Coastguard Worker // Epoch. 69*6777b538SAndroid Build Coastguard Worker std::string timestamp; 70*6777b538SAndroid Build Coastguard Worker 71*6777b538SAndroid Build Coastguard Worker // The log's compressed (gzipped) serialized protobuf. 72*6777b538SAndroid Build Coastguard Worker std::string data; 73*6777b538SAndroid Build Coastguard Worker 74*6777b538SAndroid Build Coastguard Worker // A list of the events that occurred throughout the log's lifetime. 75*6777b538SAndroid Build Coastguard Worker std::vector<Event> events; 76*6777b538SAndroid Build Coastguard Worker 77*6777b538SAndroid Build Coastguard Worker // The type of log (stability, ongoing, independent). This is only set if 78*6777b538SAndroid Build Coastguard Worker // this log is a UMA log. 79*6777b538SAndroid Build Coastguard Worker std::optional<MetricsLog::LogType> type; 80*6777b538SAndroid Build Coastguard Worker }; 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker // |service_type| is the type of service this observer will be observing from. 83*6777b538SAndroid Build Coastguard Worker explicit MetricsServiceObserver(MetricsServiceType service_type); 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Worker MetricsServiceObserver(const MetricsServiceObserver&) = delete; 86*6777b538SAndroid Build Coastguard Worker MetricsServiceObserver& operator=(const MetricsServiceObserver&) = delete; 87*6777b538SAndroid Build Coastguard Worker 88*6777b538SAndroid Build Coastguard Worker ~MetricsServiceObserver() override; 89*6777b538SAndroid Build Coastguard Worker 90*6777b538SAndroid Build Coastguard Worker // MetricsLogsEventManager::Observer: 91*6777b538SAndroid Build Coastguard Worker void OnLogCreated( 92*6777b538SAndroid Build Coastguard Worker base::StringPiece log_hash, 93*6777b538SAndroid Build Coastguard Worker base::StringPiece log_data, 94*6777b538SAndroid Build Coastguard Worker base::StringPiece log_timestamp, 95*6777b538SAndroid Build Coastguard Worker metrics::MetricsLogsEventManager::CreateReason reason) override; 96*6777b538SAndroid Build Coastguard Worker void OnLogEvent(MetricsLogsEventManager::LogEvent event, 97*6777b538SAndroid Build Coastguard Worker base::StringPiece log_hash, 98*6777b538SAndroid Build Coastguard Worker base::StringPiece message) override; 99*6777b538SAndroid Build Coastguard Worker void OnLogType(std::optional<MetricsLog::LogType> log_type) override; 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker // Exports |logs_| to a JSON string and writes it to |json_output|. If 102*6777b538SAndroid Build Coastguard Worker // |include_log_proto_data| is true, the protos of the logs will be included. 103*6777b538SAndroid Build Coastguard Worker // The format of the JSON object is as follows: 104*6777b538SAndroid Build Coastguard Worker // 105*6777b538SAndroid Build Coastguard Worker // { 106*6777b538SAndroid Build Coastguard Worker // logType: string, // e.g. "UMA" or "UKM" 107*6777b538SAndroid Build Coastguard Worker // logs: [ 108*6777b538SAndroid Build Coastguard Worker // { 109*6777b538SAndroid Build Coastguard Worker // type?: string, // e.g. "Ongoing" (set only for UMA logs) 110*6777b538SAndroid Build Coastguard Worker // hash: string, 111*6777b538SAndroid Build Coastguard Worker // timestamp: string, 112*6777b538SAndroid Build Coastguard Worker // data: string, // set if |include_log_proto_data| is true 113*6777b538SAndroid Build Coastguard Worker // size: number, 114*6777b538SAndroid Build Coastguard Worker // events: [ 115*6777b538SAndroid Build Coastguard Worker // { 116*6777b538SAndroid Build Coastguard Worker // event: string, // e.g. "Trimmed" 117*6777b538SAndroid Build Coastguard Worker // timestamp: number, 118*6777b538SAndroid Build Coastguard Worker // message?: string 119*6777b538SAndroid Build Coastguard Worker // }, 120*6777b538SAndroid Build Coastguard Worker // ... 121*6777b538SAndroid Build Coastguard Worker // ] 122*6777b538SAndroid Build Coastguard Worker // }, 123*6777b538SAndroid Build Coastguard Worker // ... 124*6777b538SAndroid Build Coastguard Worker // ] 125*6777b538SAndroid Build Coastguard Worker // } 126*6777b538SAndroid Build Coastguard Worker // 127*6777b538SAndroid Build Coastguard Worker // The "hash" field is the hex representation of the log's hash. The 128*6777b538SAndroid Build Coastguard Worker // "data" field is a base64 encoding of the log's compressed (gzipped) 129*6777b538SAndroid Build Coastguard Worker // serialized protobuf. The "size" field is the size (in bytes) of the log. 130*6777b538SAndroid Build Coastguard Worker bool ExportLogsAsJson(bool include_log_proto_data, std::string* json_output); 131*6777b538SAndroid Build Coastguard Worker 132*6777b538SAndroid Build Coastguard Worker // Exports logs data (see ExportLogsAsJson() above) to the passed |path|. If 133*6777b538SAndroid Build Coastguard Worker // the file pointed by |path| does not exist, it will be created. If it 134*6777b538SAndroid Build Coastguard Worker // already exists, its contents will be overwritten. 135*6777b538SAndroid Build Coastguard Worker void ExportLogsToFile(const base::FilePath& path); 136*6777b538SAndroid Build Coastguard Worker 137*6777b538SAndroid Build Coastguard Worker // Registers a callback. This callback will be run every time this observer is 138*6777b538SAndroid Build Coastguard Worker // notified through OnLogCreated() or OnLogEvent(). When the returned 139*6777b538SAndroid Build Coastguard Worker // CallbackListSubscription is destroyed, the callback is automatically 140*6777b538SAndroid Build Coastguard Worker // de-registered. 141*6777b538SAndroid Build Coastguard Worker [[nodiscard]] base::CallbackListSubscription AddNotifiedCallback( 142*6777b538SAndroid Build Coastguard Worker base::RepeatingClosure callback); 143*6777b538SAndroid Build Coastguard Worker 144*6777b538SAndroid Build Coastguard Worker // Returns |logs_|. logs_for_testing()145*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Log>>* logs_for_testing() { return &logs_; } 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker private: 148*6777b538SAndroid Build Coastguard Worker // Returns the Log object from |logs_| with the given |log_hash| if one 149*6777b538SAndroid Build Coastguard Worker // exists. Returns nullptr otherwise. 150*6777b538SAndroid Build Coastguard Worker Log* GetLogFromHash(base::StringPiece log_hash); 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker // The type of service this observer is observing. This has no impact on how 153*6777b538SAndroid Build Coastguard Worker // the logs are stored. This is only used when exporting the logs (see 154*6777b538SAndroid Build Coastguard Worker // ExportLogsAsJson() above) so that the type of logs is easily identifiable. 155*6777b538SAndroid Build Coastguard Worker const MetricsServiceType service_type_; 156*6777b538SAndroid Build Coastguard Worker 157*6777b538SAndroid Build Coastguard Worker // The list of logs that are being kept track of. It is a vector so that we 158*6777b538SAndroid Build Coastguard Worker // can keep the ordering of the logs as they are inserted. 159*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Log>> logs_; 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker // An overlay on |logs_| that allows for a log to be located based on its 162*6777b538SAndroid Build Coastguard Worker // hash. 163*6777b538SAndroid Build Coastguard Worker base::flat_map<base::StringPiece, Log*> indexed_logs_; 164*6777b538SAndroid Build Coastguard Worker 165*6777b538SAndroid Build Coastguard Worker // Keeps track of the type of UMA logs (ongoing, stability, independent) that 166*6777b538SAndroid Build Coastguard Worker // are being created. This should only be set for UMA logs, since the concept 167*6777b538SAndroid Build Coastguard Worker // of log type only exists in UMA. 168*6777b538SAndroid Build Coastguard Worker std::optional<MetricsLog::LogType> uma_log_type_; 169*6777b538SAndroid Build Coastguard Worker 170*6777b538SAndroid Build Coastguard Worker // List of callbacks to run whenever this observer is notified. Note that 171*6777b538SAndroid Build Coastguard Worker // OnLogType() will not trigger the callbacks. 172*6777b538SAndroid Build Coastguard Worker base::RepeatingClosureList notified_callbacks_; 173*6777b538SAndroid Build Coastguard Worker }; 174*6777b538SAndroid Build Coastguard Worker 175*6777b538SAndroid Build Coastguard Worker } // namespace metrics 176*6777b538SAndroid Build Coastguard Worker 177*6777b538SAndroid Build Coastguard Worker #endif // COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_ 178