blob: edc3dd1159bef18023ed0cc8b9f2f371d20cdd30 [file] [log] [blame]
// Copyright 2022 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 COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_METRICS_H_
#define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_METRICS_H_
#include <string>
#include "base/memory/raw_ptr.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::UpdateResult()` 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 OnUpdateResult(
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;
// Checks `controller_` `done()`, `expire_timer_done()` and `in_start()` to
// determine whether the controller is absolutely done; i.e., there won't be
// any changes to results until the next user action. Just checking `done()`
// isn't sufficient, as the expiring copied matches can change the results.
// Just checking `done()` and `expire_timer_done()` isn't sufficient, as
// they'll both be true during the sync pass, and all async providers complete
// during the sync pass, there won't be a followup async update to trigger
// logging metrics.
bool ControllerIdle();
// 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.CrossInputMatchStability.MatchChange' or
// 'Omnibox.MatchStability.AsyncMatchChange2' depending on
// `controller_.in_start()`.
void LogSuggestionChangedMetrics(size_t change_index) const;
// Logs 'Omnibox.CrossInputMatchStability.MatchChangedInAnyPosition' or
// 'Omnibox.MatchStability.AsyncMatchChangedInAnyPosition' depending on
// `controller_.in_start()`.
void LogAnySuggestionChangedMetrics(bool changed) const;
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.
bool logged_finalization_metrics_ = true;
};
#endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_CONTROLLER_METRICS_H_