| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_METRICS_STRUCTURED_ARENA_EVENT_BUFFER_H_ |
| #define CHROME_BROWSER_METRICS_STRUCTURED_ARENA_EVENT_BUFFER_H_ |
| |
| #include <cstdint> |
| #include <memory> |
| |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/task/bind_post_task.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/metrics/structured/profile_observer.h" |
| #include "components/metrics/structured/lib/arena_persistent_proto.h" |
| #include "components/metrics/structured/lib/event_buffer.h" |
| #include "components/metrics/structured/proto/event_storage.pb.h" |
| #include "third_party/metrics_proto/structured_data.pb.h" |
| |
| namespace base { |
| class FilePath; |
| } |
| |
| class Profile; |
| |
| namespace metrics::structured { |
| |
| // An implementation of an EventBuffer that stored events in an |
| // ArenaPersistentProto. |
| // |
| // Since getting the in-memory size of the proto is not available in Chromium, |
| // an estimation is used. Events are serialized by copying the events into a |
| // RepeatedPtrField. This is necessary because the events are stored in an arena |
| // and the returned RepeatedPtrField isn't allocated from the same arena. |
| // Events are flushed by serializing the proto and writing it into the path |
| // provided. An estimation is used to determine the size of an event instead of |
| // getting the actual size. This buffer is flushed when the designated resources |
| // have been consumed. |
| // TODO(b/347752634) Refactor ProfileObserver classes to use a single helper |
| // class. |
| class ArenaEventBuffer : public EventBuffer<StructuredEventProto>, |
| public ProfileObserver { |
| public: |
| ArenaEventBuffer(const base::FilePath& path, |
| base::TimeDelta write_delay, |
| uint64_t max_size_bytes); |
| |
| ~ArenaEventBuffer() override; |
| |
| // EventBuffer: |
| Result AddEvent(StructuredEventProto event) override; |
| void Purge() override; |
| uint64_t Size() override; |
| google::protobuf::RepeatedPtrField<StructuredEventProto> Serialize() override; |
| void Flush(const base::FilePath& path, FlushedCallback callback) override; |
| |
| // ProfileObserver: |
| void ProfileAdded(const Profile& profile) override; |
| |
| // Updates the path of the persistent proto and merges the content of |path| |
| // into |events_|. |
| void UpdatePath(const base::FilePath& path); |
| |
| const google::protobuf::Arena* arena() const { return events_->arena(); } |
| |
| ArenaPersistentProto<EventsProto>& proto() { return *events_; } |
| const ArenaPersistentProto<EventsProto>& proto() const { return *events_; } |
| |
| // Computes an estimate size in bytes of an event. |
| // |
| // The estimation is computed by summing: |
| // * Size of StructuredEventProto |
| // * Size of Metrics, times the number of metrics |
| // * Size of event sequence metadata if it has one. |
| static uint64_t EstimateEventSize(const StructuredEventProto& event); |
| |
| private: |
| void OnEventRead(const ReadStatus status); |
| |
| void OnEventWrite(const WriteStatus status); |
| |
| // Called periodically to backup |events_| to disk. |
| void BackupTask(); |
| |
| // The proto to store the events. |
| std::unique_ptr<ArenaPersistentProto<EventsProto>> events_; |
| |
| // A timer to periodically backup |event_| to disk. |
| base::RepeatingTimer backup_timer_; |
| |
| // A cache of events received before the buffer was ready store them. |
| std::vector<StructuredEventProto> pre_init_events_; |
| |
| scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| base::WeakPtrFactory<ArenaEventBuffer> weak_factory_{this}; |
| }; |
| } // namespace metrics::structured |
| |
| #endif // CHROME_BROWSER_METRICS_STRUCTURED_ARENA_EVENT_BUFFER_H_ |