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.
5 #ifndef COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_
6 #define COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_
12 #include "base/callback_list.h"
13 #include "base/containers/flat_map.h"
14 #include "base/files/file_path.h"
15 #include "base/strings/string_piece.h"
16 #include "components/metrics/metrics_logs_event_manager.h"
17 #include "third_party/abseil-cpp/absl/types/optional.h"
21 // Observes logs generated by a metrics collection system (UMA and UKM) and
22 // stores them in-memory. This class also provides a way to export the logs in a
23 // JSON format, which includes metadata, proto data, as well as the events
24 // describing the lifecycle of the logs.
25 class MetricsServiceObserver : public MetricsLogsEventManager::Observer {
27 // Possible metrics service types.
28 enum class MetricsServiceType {
33 // Represents a log and its data. Exposed for testing.
35 // Represents an event that occurred on the log. An optional message may
36 // be associated with the event. For example, the event may be
37 // |kLogTrimmed|, with |message| being "Log size too large".
42 Event& operator=(const Event&);
47 MetricsLogsEventManager::LogEvent event;
49 // The timestamp at which the event occurred. This is the number of
50 // milliseconds since Epoch.
53 // An optional message associated with the event.
54 absl::optional<std::string> message;
60 Log& operator=(const Log&);
64 // The SHA1 hash of the log's data, used to uniquely identify it.
67 // The time at which the log was closed. This is the number of seconds since
69 std::string timestamp;
71 // The log's compressed (gzipped) serialized protobuf.
74 // A list of the events that occurred throughout the log's lifetime.
75 std::vector<Event> events;
77 // The type of log (stability, ongoing, independent). This is only set if
78 // this log is a UMA log.
79 absl::optional<MetricsLog::LogType> type;
82 // |service_type| is the type of service this observer will be observing from.
83 explicit MetricsServiceObserver(MetricsServiceType service_type);
85 MetricsServiceObserver(const MetricsServiceObserver&) = delete;
86 MetricsServiceObserver& operator=(const MetricsServiceObserver&) = delete;
88 ~MetricsServiceObserver() override;
90 // MetricsLogsEventManager::Observer:
92 base::StringPiece log_hash,
93 base::StringPiece log_data,
94 base::StringPiece log_timestamp,
95 metrics::MetricsLogsEventManager::CreateReason reason) override;
96 void OnLogEvent(MetricsLogsEventManager::LogEvent event,
97 base::StringPiece log_hash,
98 base::StringPiece message) override;
99 void OnLogType(absl::optional<MetricsLog::LogType> log_type) override;
101 // Exports |logs_| to a JSON string and writes it to |json_output|. If
102 // |include_log_proto_data| is true, the protos of the logs will be included.
103 // The format of the JSON object is as follows:
106 // logType: string, // e.g. "UMA" or "UKM"
109 // type?: string, // e.g. "Ongoing" (set only for UMA logs)
111 // timestamp: string,
112 // data: string, // set if |include_log_proto_data| is true
116 // event: string, // e.g. "Trimmed"
117 // timestamp: number,
127 // The "hash" field is the hex representation of the log's hash. The
128 // "data" field is a base64 encoding of the log's compressed (gzipped)
129 // serialized protobuf. The "size" field is the size (in bytes) of the log.
130 bool ExportLogsAsJson(bool include_log_proto_data, std::string* json_output);
132 // Exports logs data (see ExportLogsAsJson() above) to the passed |path|. If
133 // the file pointed by |path| does not exist, it will be created. If it
134 // already exists, its contents will be overwritten.
135 void ExportLogsToFile(const base::FilePath& path);
137 // Registers a callback. This callback will be run every time this observer is
138 // notified through OnLogCreated() or OnLogEvent(). When the returned
139 // CallbackListSubscription is destroyed, the callback is automatically
141 [[nodiscard]] base::CallbackListSubscription AddNotifiedCallback(
142 base::RepeatingClosure callback);
145 std::vector<std::unique_ptr<Log>>* logs_for_testing() { return &logs_; }
148 // Returns the Log object from |logs_| with the given |log_hash| if one
149 // exists. Returns nullptr otherwise.
150 Log* GetLogFromHash(base::StringPiece log_hash);
152 // The type of service this observer is observing. This has no impact on how
153 // the logs are stored. This is only used when exporting the logs (see
154 // ExportLogsAsJson() above) so that the type of logs is easily identifiable.
155 const MetricsServiceType service_type_;
157 // The list of logs that are being kept track of. It is a vector so that we
158 // can keep the ordering of the logs as they are inserted.
159 std::vector<std::unique_ptr<Log>> logs_;
161 // An overlay on |logs_| that allows for a log to be located based on its
163 base::flat_map<base::StringPiece, Log*> indexed_logs_;
165 // Keeps track of the type of UMA logs (ongoing, stability, independent) that
166 // are being created. This should only be set for UMA logs, since the concept
167 // of log type only exists in UMA.
168 absl::optional<MetricsLog::LogType> uma_log_type_;
170 // List of callbacks to run whenever this observer is notified. Note that
171 // OnLogType() will not trigger the callbacks.
172 base::RepeatingClosureList notified_callbacks_;
175 } // namespace metrics
177 #endif // COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_