| // 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. |
| |
| #include "chromeos/components/local_search_service/search_metrics_reporter.h" |
| |
| #include "base/check_op.h" |
| #include "base/metrics/histogram_functions.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "chromeos/components/local_search_service/pref_names.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service.h" |
| |
| namespace chromeos { |
| namespace local_search_service { |
| namespace { |
| |
| // Interval for asking metrics::DailyEvent to check whether a day has passed. |
| constexpr base::TimeDelta kCheckDailyEventInternal = |
| base::TimeDelta::FromMinutes(30); |
| |
| // Prefs corresponding to IndexId values. |
| constexpr std::array<const char*, SearchMetricsReporter::kNumberIndexIds> |
| kDailyCountPrefs = { |
| prefs::kLocalSearchServiceMetricsCrosSettingsCount, |
| prefs::kLocalSearchServiceMetricsHelpAppCount, |
| }; |
| |
| // Histograms corresponding to IndexId values. |
| constexpr std::array<const char*, SearchMetricsReporter::kNumberIndexIds> |
| kDailyCountHistograms = { |
| SearchMetricsReporter::kCrosSettingsName, |
| SearchMetricsReporter::kHelpAppName, |
| }; |
| |
| } // namespace |
| |
| constexpr char SearchMetricsReporter::kDailyEventIntervalName[]; |
| constexpr char SearchMetricsReporter::kCrosSettingsName[]; |
| constexpr char SearchMetricsReporter::kHelpAppName[]; |
| |
| constexpr int SearchMetricsReporter::kNumberIndexIds; |
| |
| // This class is needed since metrics::DailyEvent requires taking ownership |
| // of its observers. It just forwards events to SearchMetricsReporter. |
| class SearchMetricsReporter::DailyEventObserver |
| : public metrics::DailyEvent::Observer { |
| public: |
| explicit DailyEventObserver(SearchMetricsReporter* reporter) |
| : reporter_(reporter) { |
| DCHECK(reporter_); |
| } |
| |
| ~DailyEventObserver() override = default; |
| DailyEventObserver(const DailyEventObserver&) = delete; |
| DailyEventObserver& operator=(const DailyEventObserver&) = delete; |
| |
| // metrics::DailyEvent::Observer: |
| void OnDailyEvent(metrics::DailyEvent::IntervalType type) override { |
| reporter_->ReportDailyMetrics(type); |
| } |
| |
| private: |
| SearchMetricsReporter* reporter_; // Not owned. |
| }; |
| |
| // static: |
| void SearchMetricsReporter::RegisterLocalStatePrefs( |
| PrefRegistrySimple* registry) { |
| metrics::DailyEvent::RegisterPref( |
| registry, prefs::kLocalSearchServiceMetricsDailySample); |
| for (const char* daily_count_pref : kDailyCountPrefs) { |
| registry->RegisterIntegerPref(daily_count_pref, 0); |
| } |
| } |
| |
| SearchMetricsReporter::SearchMetricsReporter( |
| PrefService* local_state_pref_service) |
| : pref_service_(local_state_pref_service), |
| daily_event_(std::make_unique<metrics::DailyEvent>( |
| pref_service_, |
| prefs::kLocalSearchServiceMetricsDailySample, |
| kDailyEventIntervalName)) { |
| for (size_t i = 0; i < kDailyCountPrefs.size(); ++i) { |
| daily_counts_[i] = pref_service_->GetInteger(kDailyCountPrefs[i]); |
| } |
| |
| daily_event_->AddObserver(std::make_unique<DailyEventObserver>(this)); |
| daily_event_->CheckInterval(); |
| timer_.Start(FROM_HERE, kCheckDailyEventInternal, daily_event_.get(), |
| &metrics::DailyEvent::CheckInterval); |
| } |
| |
| SearchMetricsReporter::~SearchMetricsReporter() = default; |
| |
| void SearchMetricsReporter::OnSearchPerformed( |
| IndexId index_id, |
| OnSearchPerformedCallback callback) { |
| const size_t index = static_cast<size_t>(index_id); |
| const char* daily_count_pref = kDailyCountPrefs[index]; |
| ++daily_counts_[index]; |
| pref_service_->SetInteger(daily_count_pref, daily_counts_[index]); |
| std::move(callback).Run(); |
| } |
| |
| void SearchMetricsReporter::ReportDailyMetricsForTesting( |
| metrics::DailyEvent::IntervalType type) { |
| ReportDailyMetrics(type); |
| } |
| |
| mojo::PendingRemote<mojom::SearchMetricsReporter> |
| SearchMetricsReporter::BindNewPipeAndPassRemote() { |
| receivers_.push_back( |
| std::make_unique<mojo::Receiver<mojom::SearchMetricsReporter>>(this)); |
| return receivers_.back()->BindNewPipeAndPassRemote(); |
| } |
| |
| void SearchMetricsReporter::ReportDailyMetrics( |
| metrics::DailyEvent::IntervalType type) { |
| // Do nothing on the first run. |
| if (type == metrics::DailyEvent::IntervalType::FIRST_RUN) |
| return; |
| |
| // Only send metrics for DAY_ELAPSED event. |
| if (type == metrics::DailyEvent::IntervalType::DAY_ELAPSED) { |
| for (size_t index = 0; index < kDailyCountPrefs.size(); ++index) { |
| base::UmaHistogramCounts1000(kDailyCountHistograms[index], |
| daily_counts_[index]); |
| } |
| } |
| |
| for (size_t i = 0; i < kDailyCountPrefs.size(); ++i) { |
| daily_counts_[i] = 0; |
| pref_service_->SetInteger(kDailyCountPrefs[i], 0); |
| } |
| } |
| |
| } // namespace local_search_service |
| } // namespace chromeos |