blob: 001b9ee0fdb4dc3946c2f2f2fa8fabd8ecd3a8e5 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_
#define COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "base/callback_list.h"
#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "components/metrics/metrics_logs_event_manager.h"
namespace metrics {
// Observes logs generated by a metrics collection system (UMA and UKM) and
// stores them in-memory. This class also provides a way to export the logs in a
// JSON format, which includes metadata, proto data, as well as the events
// describing the lifecycle of the logs.
class MetricsServiceObserver : public MetricsLogsEventManager::Observer {
public:
// Possible metrics service types.
enum class MetricsServiceType {
UMA,
UKM,
};
// Represents a log and its data. Exposed for testing.
struct Log {
// Represents an event that occurred on the log. An optional message may
// be associated with the event. For example, the event may be
// |kLogTrimmed|, with |message| being "Log size too large".
struct Event {
Event();
Event(const Event&);
Event& operator=(const Event&);
~Event();
// The type of event.
MetricsLogsEventManager::LogEvent event;
// The timestamp at which the event occurred. This is the number of
// milliseconds since Epoch.
double timestampMs;
// An optional message associated with the event.
std::optional<std::string> message;
};
Log();
Log(const Log&);
Log& operator=(const Log&);
~Log();
// The SHA1 hash of the log's data, used to uniquely identify it.
std::string hash;
// The time at which the log was closed. This is the number of seconds since
// Epoch.
std::string timestamp;
// The log's compressed (gzipped) serialized protobuf.
std::string data;
// A list of the events that occurred throughout the log's lifetime.
std::vector<Event> events;
// The type of log (stability, ongoing, independent). This is only set if
// this log is a UMA log.
std::optional<MetricsLog::LogType> type;
};
// |service_type| is the type of service this observer will be observing from.
explicit MetricsServiceObserver(MetricsServiceType service_type);
MetricsServiceObserver(const MetricsServiceObserver&) = delete;
MetricsServiceObserver& operator=(const MetricsServiceObserver&) = delete;
~MetricsServiceObserver() override;
// MetricsLogsEventManager::Observer:
void OnLogCreated(
std::string_view log_hash,
std::string_view log_data,
std::string_view log_timestamp,
metrics::MetricsLogsEventManager::CreateReason reason) override;
void OnLogEvent(MetricsLogsEventManager::LogEvent event,
std::string_view log_hash,
std::string_view message) override;
void OnLogType(std::optional<MetricsLog::LogType> log_type) override;
// Exports |logs_| to a JSON string and writes it to |json_output|. If
// |include_log_proto_data| is true, the protos of the logs will be included.
// The format of the JSON object is as follows:
//
// {
// logType: string, // e.g. "UMA" or "UKM"
// logs: [
// {
// type?: string, // e.g. "Ongoing" (set only for UMA logs)
// hash: string,
// timestamp: string,
// data: string, // set if |include_log_proto_data| is true
// size: number,
// events: [
// {
// event: string, // e.g. "Trimmed"
// timestamp: number,
// message?: string
// },
// ...
// ]
// },
// ...
// ]
// }
//
// The "hash" field is the hex representation of the log's hash. The
// "data" field is a base64 encoding of the log's compressed (gzipped)
// serialized protobuf. The "size" field is the size (in bytes) of the log.
bool ExportLogsAsJson(bool include_log_proto_data, std::string* json_output);
// Exports logs data (see ExportLogsAsJson() above) to the passed |path|. If
// the file pointed by |path| does not exist, it will be created. If it
// already exists, its contents will be overwritten.
void ExportLogsToFile(const base::FilePath& path);
// Registers a callback. This callback will be run every time this observer is
// notified through OnLogCreated() or OnLogEvent(). When the returned
// CallbackListSubscription is destroyed, the callback is automatically
// de-registered.
[[nodiscard]] base::CallbackListSubscription AddNotifiedCallback(
base::RepeatingClosure callback);
// Returns |logs_|.
std::vector<std::unique_ptr<Log>>* logs_for_testing() { return &logs_; }
private:
// Returns the Log object from |logs_| with the given |log_hash| if one
// exists. Returns nullptr otherwise.
Log* GetLogFromHash(std::string_view log_hash);
// The type of service this observer is observing. This has no impact on how
// the logs are stored. This is only used when exporting the logs (see
// ExportLogsAsJson() above) so that the type of logs is easily identifiable.
const MetricsServiceType service_type_;
// The list of logs that are being kept track of. It is a vector so that we
// can keep the ordering of the logs as they are inserted.
std::vector<std::unique_ptr<Log>> logs_;
// An overlay on |logs_| that allows for a log to be located based on its
// hash.
base::flat_map<std::string_view, raw_ptr<Log, CtnExperimental>> indexed_logs_;
// Keeps track of the type of UMA logs (ongoing, stability, independent) that
// are being created. This should only be set for UMA logs, since the concept
// of log type only exists in UMA.
std::optional<MetricsLog::LogType> uma_log_type_;
// List of callbacks to run whenever this observer is notified. Note that
// OnLogType() will not trigger the callbacks.
base::RepeatingClosureList notified_callbacks_;
};
} // namespace metrics
#endif // COMPONENTS_METRICS_METRICS_SERVICE_OBSERVER_H_