// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef FUCHSIA_BASE_LEGACYMETRICS_CLIENT_H_ #define FUCHSIA_BASE_LEGACYMETRICS_CLIENT_H_ #include #include #include #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "fuchsia/base/legacymetrics_user_event_recorder.h" namespace cr_fuchsia { // Used to report events & histogram data to the // fuchsia.legacymetrics.MetricsRecorder service. // LegacyMetricsClient must be Start()ed on an IO-capable sequence. // Cannot be used in conjunction with other metrics reporting services. // Must be constructed, used, and destroyed on the same sequence. class LegacyMetricsClient { public: // Maximum number of Events to send to Record() at a time, so as to not exceed // the 64KB FIDL maximum message size. static constexpr size_t kMaxBatchSize = 50; // Constants for FIDL reconnection with exponential backoff. static constexpr base::TimeDelta kInitialReconnectDelay = base::TimeDelta::FromSeconds(1); static constexpr base::TimeDelta kMaxReconnectDelay = base::TimeDelta::FromHours(1); static constexpr size_t kReconnectBackoffFactor = 2; using ReportAdditionalMetricsCallback = base::RepeatingCallback)>)>; using NotifyFlushCallback = base::OnceCallback; LegacyMetricsClient(); ~LegacyMetricsClient(); explicit LegacyMetricsClient(const LegacyMetricsClient&) = delete; LegacyMetricsClient& operator=(const LegacyMetricsClient&) = delete; // Starts buffering data and schedules metric reporting after every // |report_interval|. void Start(base::TimeDelta report_interval); // Sets an asynchronous |callback| to be invoked just prior to reporting, // allowing users to asynchronously gather and provide additional custom // metrics. |callback| will receive the list of metrics when they are ready. // Reporting is paused until |callback| is fulfilled. // If used, then this method must be called before calling Start(). void SetReportAdditionalMetricsCallback( ReportAdditionalMetricsCallback callback); // Sets a |callback| which is invoked to warn that the connection to the // remote MetricsRecorder will be terminated. The completion closure passed to // |callback| should be invoked to signal flush completion. void SetNotifyFlushCallback(NotifyFlushCallback callback); // Use when caller needs an explicit flush and then disconnect, such as before // termination. Caller will be notified when all events in the buffer are // sent. void FlushAndDisconnect(base::OnceClosure on_flush_complete); private: void ConnectAndStartReporting(); void ScheduleNextReport(); void StartReport(); void Report(std::vector additional_metrics); void OnMetricsRecorderDisconnected(zx_status_t status); void OnCloseSoon(); // Incrementally sends the contents of |to_send_| to |metrics_recorder_|. void DrainBuffer(); base::TimeDelta reconnect_delay_ = kInitialReconnectDelay; base::TimeDelta report_interval_; ReportAdditionalMetricsCallback report_additional_callback_; NotifyFlushCallback notify_flush_callback_; bool is_flushing_ = false; bool record_ack_pending_ = false; std::vector to_send_; std::unique_ptr user_events_recorder_; fuchsia::legacymetrics::MetricsRecorderPtr metrics_recorder_; base::RetainingOneShotTimer reconnect_timer_; base::RetainingOneShotTimer report_timer_; SEQUENCE_CHECKER(sequence_checker_); base::OnceClosure on_flush_complete_; // Prevents use-after-free if |report_additional_callback_| is invoked after // |this| is destroyed. base::WeakPtrFactory weak_factory_{this}; }; } // namespace cr_fuchsia #endif // FUCHSIA_BASE_LEGACYMETRICS_CLIENT_H_