xref: /aosp_15_r20/external/cronet/components/metrics/metrics_service_observer.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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