Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef FUCHSIA_BASE_LEGACYMETRICS_CLIENT_H_ |
| 6 | #define FUCHSIA_BASE_LEGACYMETRICS_CLIENT_H_ |
| 7 | |
| 8 | #include <fuchsia/legacymetrics/cpp/fidl.h> |
| 9 | |
| 10 | #include <memory> |
| 11 | #include <vector> |
| 12 | |
| 13 | #include "base/callback.h" |
| 14 | #include "base/memory/weak_ptr.h" |
| 15 | #include "base/sequence_checker.h" |
Akira Baruah | 7b75418b | 2020-12-11 01:35:09 | [diff] [blame] | 16 | #include "base/time/time.h" |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 17 | #include "base/timer/timer.h" |
| 18 | #include "fuchsia/base/legacymetrics_user_event_recorder.h" |
| 19 | |
| 20 | namespace cr_fuchsia { |
| 21 | |
| 22 | // Used to report events & histogram data to the |
| 23 | // fuchsia.legacymetrics.MetricsRecorder service. |
| 24 | // LegacyMetricsClient must be Start()ed on an IO-capable sequence. |
| 25 | // Cannot be used in conjunction with other metrics reporting services. |
| 26 | // Must be constructed, used, and destroyed on the same sequence. |
| 27 | class LegacyMetricsClient { |
| 28 | public: |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 29 | // Maximum number of Events to send to Record() at a time, so as to not exceed |
| 30 | // the 64KB FIDL maximum message size. |
| 31 | static constexpr size_t kMaxBatchSize = 50; |
| 32 | |
Akira Baruah | 7b75418b | 2020-12-11 01:35:09 | [diff] [blame] | 33 | // Constants for FIDL reconnection with exponential backoff. |
| 34 | static constexpr base::TimeDelta kInitialReconnectDelay = |
| 35 | base::TimeDelta::FromSeconds(1); |
| 36 | static constexpr base::TimeDelta kMaxReconnectDelay = |
| 37 | base::TimeDelta::FromHours(1); |
| 38 | static constexpr size_t kReconnectBackoffFactor = 2; |
| 39 | |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 40 | using ReportAdditionalMetricsCallback = base::RepeatingCallback<void( |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 41 | base::OnceCallback<void(std::vector<fuchsia::legacymetrics::Event>)>)>; |
Kevin Marshall | aa7f516 | 2020-06-04 23:32:31 | [diff] [blame] | 42 | using NotifyFlushCallback = |
| 43 | base::OnceCallback<void(base::OnceClosure completion_cb)>; |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 44 | |
| 45 | LegacyMetricsClient(); |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 46 | ~LegacyMetricsClient(); |
| 47 | |
| 48 | explicit LegacyMetricsClient(const LegacyMetricsClient&) = delete; |
| 49 | LegacyMetricsClient& operator=(const LegacyMetricsClient&) = delete; |
| 50 | |
| 51 | // Starts buffering data and schedules metric reporting after every |
| 52 | // |report_interval|. |
| 53 | void Start(base::TimeDelta report_interval); |
| 54 | |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 55 | // Sets an asynchronous |callback| to be invoked just prior to reporting, |
| 56 | // allowing users to asynchronously gather and provide additional custom |
| 57 | // metrics. |callback| will receive the list of metrics when they are ready. |
| 58 | // Reporting is paused until |callback| is fulfilled. |
| 59 | // If used, then this method must be called before calling Start(). |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 60 | void SetReportAdditionalMetricsCallback( |
| 61 | ReportAdditionalMetricsCallback callback); |
| 62 | |
Kevin Marshall | aa7f516 | 2020-06-04 23:32:31 | [diff] [blame] | 63 | // Sets a |callback| which is invoked to warn that the connection to the |
| 64 | // remote MetricsRecorder will be terminated. The completion closure passed to |
| 65 | // |callback| should be invoked to signal flush completion. |
| 66 | void SetNotifyFlushCallback(NotifyFlushCallback callback); |
| 67 | |
Hai Bi | d0224f9 | 2020-10-19 23:47:48 | [diff] [blame] | 68 | // Use when caller needs an explicit flush and then disconnect, such as before |
| 69 | // termination. Caller will be notified when all events in the buffer are |
| 70 | // sent. |
| 71 | void FlushAndDisconnect(base::OnceClosure on_flush_complete); |
| 72 | |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 73 | private: |
Akira Baruah | 7b75418b | 2020-12-11 01:35:09 | [diff] [blame] | 74 | void ConnectAndStartReporting(); |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 75 | void ScheduleNextReport(); |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 76 | void StartReport(); |
| 77 | void Report(std::vector<fuchsia::legacymetrics::Event> additional_metrics); |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 78 | void OnMetricsRecorderDisconnected(zx_status_t status); |
Kevin Marshall | aa7f516 | 2020-06-04 23:32:31 | [diff] [blame] | 79 | void OnCloseSoon(); |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 80 | |
Kevin Marshall | aa7f516 | 2020-06-04 23:32:31 | [diff] [blame] | 81 | // Incrementally sends the contents of |to_send_| to |metrics_recorder_|. |
| 82 | void DrainBuffer(); |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 83 | |
Akira Baruah | 7b75418b | 2020-12-11 01:35:09 | [diff] [blame] | 84 | base::TimeDelta reconnect_delay_ = kInitialReconnectDelay; |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 85 | base::TimeDelta report_interval_; |
| 86 | ReportAdditionalMetricsCallback report_additional_callback_; |
Kevin Marshall | aa7f516 | 2020-06-04 23:32:31 | [diff] [blame] | 87 | NotifyFlushCallback notify_flush_callback_; |
| 88 | bool is_flushing_ = false; |
| 89 | bool record_ack_pending_ = false; |
| 90 | std::vector<fuchsia::legacymetrics::Event> to_send_; |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 91 | std::unique_ptr<LegacyMetricsUserActionRecorder> user_events_recorder_; |
| 92 | |
| 93 | fuchsia::legacymetrics::MetricsRecorderPtr metrics_recorder_; |
Akira Baruah | 7b75418b | 2020-12-11 01:35:09 | [diff] [blame] | 94 | base::RetainingOneShotTimer reconnect_timer_; |
| 95 | base::RetainingOneShotTimer report_timer_; |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 96 | SEQUENCE_CHECKER(sequence_checker_); |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 97 | |
Hai Bi | d0224f9 | 2020-10-19 23:47:48 | [diff] [blame] | 98 | base::OnceClosure on_flush_complete_; |
| 99 | |
Kevin Marshall | ebe60c4 | 2020-04-14 22:01:24 | [diff] [blame] | 100 | // Prevents use-after-free if |report_additional_callback_| is invoked after |
| 101 | // |this| is destroyed. |
| 102 | base::WeakPtrFactory<LegacyMetricsClient> weak_factory_{this}; |
Kevin Marshall | 05e29bd | 2020-03-19 21:55:44 | [diff] [blame] | 103 | }; |
| 104 | |
| 105 | } // namespace cr_fuchsia |
| 106 | |
| 107 | #endif // FUCHSIA_BASE_LEGACYMETRICS_CLIENT_H_ |