blob: 6a537d299127c30ae49306e7a4353fd7ca4cd72d [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_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_METRICS_H_
#define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_METRICS_H_
#include <string>
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "components/omnibox/browser/autocomplete_result.h"
class AutocompleteController;
class AutocompleteProvider;
// Used to track and log timing metrics for `AutocompleteController`. Logs 3
// sets of metrics:
// 1) How long until each async provider completes.
// - Does not track intermediate updates if an async provider updates results
// multiple times.
// - Does not track sync providers (i.e., providers that don't use
// `AutocompleteProvider::NotifyListeners()` to notify the
// `AutocompleteController`.
// - Tracks async providers completing syncly (i.e., providers that invoke
// `AutocompleteProvider::NotifyListeners()` syncly; see the comment in
// `AutocompleteController::OnProviderUpdate()`).
// 2) How long until the suggestions finalize.
// - Does not track sync requests (i.e.,
// `AutocompleteInput::omit_asynchronous_matches()` set to true).
// - Does track async requests that complete syncly.
// - Tracks suggestion additions, changes, and removals.
// 3) How many suggestions change during updates.
// - Does not track sync request.
// - Tracks both sync and async updates.
// - Does not track suggestion removals.
// - Tracks suggestion additions and changes.
class AutocompleteControllerMetrics {
public:
explicit AutocompleteControllerMetrics(
const AutocompleteController& controller);
// Called when `AutocompleteController::Start()` is called. Will 1) log
// suggestion finalization metrics for the previous request if it hasn't
// already (i.e. if it hasn't completed and is being interrupted), and 2)
// reset state to track the new request. Should be called before
// `AutocompleteController::done()`,
// `::expire_timer_done()`, or `AutocompleteProvider::done()` have been
// updated for the new request.
void OnStart();
// Called when `AutocompleteController::NotifyChanged()` is called. Will log
// metrics on how many suggestions changed with this update. If the controller
// is done, will also log suggestion finalization metrics; otherwise, future
// calls to `OnProviderUpdate()`, `OnStop()`, or `OnStart()` will log
// suggestion finalization metrics.
void OnNotifyChanged(
std::vector<AutocompleteResult::MatchDedupComparator> last_result,
std::vector<AutocompleteResult::MatchDedupComparator> new_result);
// Called when `AutocompleteController::OnProviderUpdate()` is called. If the
// provider is done, will log how long it took; otherwise, future calls to
// `OnProviderUpdate()`, `OnStop()`, or `OnStart()` will log how long the
// provider took.
void OnProviderUpdate(const AutocompleteProvider& provider) const;
// Called when either `AutocompleteController::StopHelper()` or `OnStart()`
// are called; i.e., when the ongoing request, if incomplete, will be
// interrupted, e.g., because the input was updated, the popup was closed, or
// the `AutocompleteController::stop_timer_` expired. Should be called before
// `AutocompleteController::done()`, `::expire_timer_done()`, or
// `AutocompleteProvider::done()` have been updated.
void OnStop();
private:
friend class AutocompleteControllerMetricsTest;
// Logs
// 'Omnibox.AsyncAutocompletionTime.[Done|LastChange|LastDefaultChange]'.
// Additionally logs either '*.Completed' or '*.Interrupted' for each of the
// 3 depending on whether the controller completed or was interrupted.
void LogSuggestionFinalizationMetrics();
// Logs 'Omnibox.AsyncAutocompletionTime.Provider.<provider name>'.
// Additionally logs either '*.Completed' or '*.Interrupted' depending
// whether the provider completed or was interrupted.
void LogProviderTimeMetrics(const AutocompleteProvider& provider) const;
// Helper for the above 2 logging methods. Logs
// 'Omnibox.AsyncAutocompletionTime.<name>'. Additionally logs either
// '*.Completed' or '*.Interrupted' depending on `completed`.
void LogAsyncAutocompletionTimeMetrics(const std::string& name,
bool completed,
const base::TimeTicks end_time) const;
// Logs 'Omnibox.MatchStability.MatchChangeIndex'. Additionally logs
// '*.CrossInput' or '*.Async' depending on `controller_.in_start()`.
void LogSuggestionChangeIndexMetrics(size_t change_index) const;
// Logs 'Omnibox.MatchStability.MatchChangeInAnyPosition'. Additionally logs
// '*.CrossInput' or '*.Async' depending on `controller_.in_start()`.
void LogSuggestionChangeInAnyPositionMetrics(bool changed) const;
const raw_ref<const AutocompleteController> controller_;
// When `OnStart()` was last invoked. Used for measuring latency. Valid even
// if `controller_.in_start_` is false.
base::TimeTicks start_time_;
// When `OnProviderUpdate()` was last invoked and detected any change to the
// suggestions.
base::TimeTicks last_change_time_;
// When `OnProviderUpdate()` was last invoked and detected a change to the
// default suggestion.
base::TimeTicks last_default_change_time_;
// Whether `LogSuggestionFinalizationMetrics()` has been invoked for the
// current request. Used for `DCHECK`s and iOS only. The autocomplete
// controller state should be the source of truth instead.
bool logged_finalization_metrics_ = true;
};
#endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_METRICS_H_