Commit 20814f73 authored by tby's avatar tby Committed by Commit Bot

[Cros SR logging] Implement UKM logging of launcher non-app results.

This adds the chrome-side of user interactions with non-app results in
the CrOS launcher. See go/cros-launcher-search-ranking-logging for
more details.

Bug: 972817
Change-Id: I602cd982a6972df93bdb920cc1f1bc793f6ab9e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1706592
Commit-Queue: Tony Yeoman <tby@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarcalamity <calamity@chromium.org>
Reviewed-by: default avatarJia Meng <jiameng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#681092}
parent 35544747
...@@ -380,6 +380,9 @@ void AppListClientImpl::SetUpSearchUI() { ...@@ -380,6 +380,9 @@ void AppListClientImpl::SetUpSearchUI() {
search_controller_ = search_controller_ =
app_list::CreateSearchController(profile_, current_model_updater_, this); app_list::CreateSearchController(profile_, current_model_updater_, this);
search_ranking_event_logger_ =
std::make_unique<app_list::SearchRankingEventLogger>(
profile_, search_controller_.get());
} }
app_list::SearchController* AppListClientImpl::search_controller() { app_list::SearchController* AppListClientImpl::search_controller() {
...@@ -525,7 +528,7 @@ void AppListClientImpl::NotifySearchResultsForLogging( ...@@ -525,7 +528,7 @@ void AppListClientImpl::NotifySearchResultsForLogging(
const base::string16& trimmed_query, const base::string16& trimmed_query,
const ash::SearchResultIdWithPositionIndices& results, const ash::SearchResultIdWithPositionIndices& results,
int position_index) { int position_index) {
search_ranking_event_logger_.Log(trimmed_query, results, position_index); search_ranking_event_logger_->Log(trimmed_query, results, position_index);
} }
ash::ShelfLaunchSource AppListClientImpl::AppListSourceToLaunchSource( ash::ShelfLaunchSource AppListClientImpl::AppListSourceToLaunchSource(
......
...@@ -191,7 +191,8 @@ class AppListClientImpl ...@@ -191,7 +191,8 @@ class AppListClientImpl
bool app_list_target_visibility_ = false; bool app_list_target_visibility_ = false;
bool app_list_visible_ = false; bool app_list_visible_ = false;
app_list::SearchRankingEventLogger search_ranking_event_logger_; std::unique_ptr<app_list::SearchRankingEventLogger>
search_ranking_event_logger_;
base::WeakPtrFactory<AppListClientImpl> weak_ptr_factory_{this}; base::WeakPtrFactory<AppListClientImpl> weak_ptr_factory_{this};
......
...@@ -5,19 +5,30 @@ ...@@ -5,19 +5,30 @@
#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_LOGGING_SEARCH_RANKING_EVENT_LOGGER_H_ #ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_LOGGING_SEARCH_RANKING_EVENT_LOGGER_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_LOGGING_SEARCH_RANKING_EVENT_LOGGER_H_ #define CHROME_BROWSER_UI_APP_LIST_SEARCH_LOGGING_SEARCH_RANKING_EVENT_LOGGER_H_
#include <map>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/app_list/app_list_types.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/metrics/ukm_background_recorder_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/search/search_controller.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
class ChromeSearchResult;
namespace app_list { namespace app_list {
// Performs UKM logging of search ranking events in the launcher's results list.
class SearchRankingEventLogger { class SearchRankingEventLogger {
public: public:
SearchRankingEventLogger(); SearchRankingEventLogger(Profile* profile,
SearchController* search_controller);
~SearchRankingEventLogger(); ~SearchRankingEventLogger();
// Called if a search result item got clicked, or a list of search result has // Called if a search result item got clicked, or a list of search result has
// been shown to the user after a certain amount of time. |raw_query| is the // been shown to the user after a certain amount of time. |raw_query| is the
...@@ -28,13 +39,80 @@ class SearchRankingEventLogger { ...@@ -28,13 +39,80 @@ class SearchRankingEventLogger {
// clicked, |position_index| will be -1). // clicked, |position_index| will be -1).
void Log(const base::string16& trimmed_query, void Log(const base::string16& trimmed_query,
const ash::SearchResultIdWithPositionIndices& search_results, const ash::SearchResultIdWithPositionIndices& search_results,
int position_index); int launched_index);
// Sets a testing-only closure to inform tests when a UKM event has been
// recorded.
void SetEventRecordedForTesting(base::OnceClosure closure);
private: private:
// Logs suggested items either from impressions or from click events. // Stores state necessary for logging a given search result that is
void LogSuggestedZeroStateItems( // accumulated throughout the session.
const ash::SearchResultIdWithPositionIndices& search_results, struct ResultState {
int position_index); ResultState();
~ResultState();
base::Optional<base::Time> last_launch = base::nullopt;
// Initialises all elements to 0.
int launches_per_hour[24] = {};
int launches_this_session = 0;
};
// Stores the relevant parts of a ChromeSearchResult used for logging.
struct ResultInfo {
public:
ResultInfo();
ResultInfo(const ResultInfo& other);
~ResultInfo();
int index;
std::string target;
base::string16 title;
ash::SearchResultType type;
int subtype;
float relevance;
};
// Calls the UKM API for a source ID relevant to |result|, and then begins the
// logging process by calling LogEvent.
void GetBackgroundSourceIdAndLogEvent(int event_id,
const base::string16& trimmed_query,
const ResultInfo& result_info,
int launched_index);
// Logs the given event to UKM. If |source_id| is nullopt then use a blank
// source ID.
void LogEvent(int event_id,
const base::string16& trimmed_query,
const ResultInfo& result_info,
int launched_index,
base::Optional<ukm::SourceId> source_id);
SearchController* search_controller_;
// Some events do not have an associated URL and so are logged directly with
// |ukm_recorder_| using a blank source ID. Other events need to validate the
// URL before recording, and use |ukm_background_recorder_|.
ukm::UkmRecorder* ukm_recorder_;
ukm::UkmBackgroundRecorderService* ukm_background_recorder_;
// TODO(972817): Zero-state previous query results change their URL based on
// the position they should be displayed at in the launcher. Because their
// ID changes, we lose information on their result state. If, in future, we
// want to rank these results and want more information, we should normalize
// their IDs to remove the position information.
std::map<std::string, ResultState> id_to_result_state_;
// The next, unused, event ID.
int next_event_id_ = 1;
// Testing-only closure to inform tests when a UKM event has been recorded.
base::OnceClosure event_recorded_for_testing_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<SearchRankingEventLogger> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SearchRankingEventLogger);
}; };
} // namespace app_list } // namespace app_list
......
...@@ -231,6 +231,10 @@ SearchResultType OmniboxResult::GetSearchResultType() const { ...@@ -231,6 +231,10 @@ SearchResultType OmniboxResult::GetSearchResultType() const {
} }
} }
GURL OmniboxResult::DestinationURL() const {
return match_.destination_url;
}
void OmniboxResult::UpdateIcon() { void OmniboxResult::UpdateIcon() {
BookmarkModel* bookmark_model = BookmarkModel* bookmark_model =
BookmarkModelFactory::GetForBrowserContext(profile_); BookmarkModelFactory::GetForBrowserContext(profile_);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/app_list/search/chrome_search_result.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
#include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match.h"
#include "url/gurl.h"
class AppListControllerDelegate; class AppListControllerDelegate;
class AutocompleteController; class AutocompleteController;
...@@ -41,6 +42,9 @@ class OmniboxResult : public ChromeSearchResult { ...@@ -41,6 +42,9 @@ class OmniboxResult : public ChromeSearchResult {
void InvokeAction(int action_index, int event_flags) override; void InvokeAction(int action_index, int event_flags) override;
SearchResultType GetSearchResultType() const override; SearchResultType GetSearchResultType() const override;
// Returns the URL that will be navigated to by this search result.
GURL DestinationURL() const;
private: private:
void UpdateIcon(); void UpdateIcon();
void UpdateTitleAndDetails(); void UpdateTitleAndDetails();
......
...@@ -52,7 +52,7 @@ class SearchController { ...@@ -52,7 +52,7 @@ class SearchController {
// Takes ownership of |provider| and associates it with given mixer group. // Takes ownership of |provider| and associates it with given mixer group.
void AddProvider(size_t group_id, std::unique_ptr<SearchProvider> provider); void AddProvider(size_t group_id, std::unique_ptr<SearchProvider> provider);
ChromeSearchResult* FindSearchResult(const std::string& result_id); virtual ChromeSearchResult* FindSearchResult(const std::string& result_id);
ChromeSearchResult* GetResultByTitleForTest(const std::string& title); ChromeSearchResult* GetResultByTitleForTest(const std::string& title);
// Sends training signal to each |providers_| // Sends training signal to each |providers_|
......
...@@ -237,14 +237,13 @@ std::unique_ptr<RecurrencePredictor> MakePredictor( ...@@ -237,14 +237,13 @@ std::unique_ptr<RecurrencePredictor> MakePredictor(
} }
JsonConfigConverter::JsonConfigConverter(service_manager::Connector* connector) JsonConfigConverter::JsonConfigConverter(service_manager::Connector* connector)
: connector_(connector) { : connector_(connector) {}
DCHECK(connector_);
}
JsonConfigConverter::~JsonConfigConverter() {} JsonConfigConverter::~JsonConfigConverter() {}
void JsonConfigConverter::Convert(const std::string& json_string, void JsonConfigConverter::Convert(const std::string& json_string,
const std::string& model_identifier, const std::string& model_identifier,
OnConfigLoadedCallback callback) { OnConfigLoadedCallback callback) {
DCHECK(connector_);
GetJsonParser().Parse( GetJsonParser().Parse(
json_string, json_string,
base::BindOnce(&JsonConfigConverter::OnJsonParsed, base::Unretained(this), base::BindOnce(&JsonConfigConverter::OnJsonParsed, base::Unretained(this),
......
...@@ -4969,6 +4969,7 @@ test("unit_tests") { ...@@ -4969,6 +4969,7 @@ test("unit_tests") {
"../browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc", "../browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc",
"../browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc", "../browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc",
"../browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc", "../browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc",
"../browser/ui/app_list/search/logging/search_ranking_event_logger_unittest.cc",
"../browser/ui/app_list/search/search_result_ranker/app_launch_event_logger_unittest.cc", "../browser/ui/app_list/search/search_result_ranker/app_launch_event_logger_unittest.cc",
"../browser/ui/app_list/search/search_result_ranker/app_launch_predictor_unittest.cc", "../browser/ui/app_list/search/search_result_ranker/app_launch_predictor_unittest.cc",
"../browser/ui/app_list/search/search_result_ranker/app_list_launch_metrics_provider_unittest.cc", "../browser/ui/app_list/search/search_result_ranker/app_list_launch_metrics_provider_unittest.cc",
......
...@@ -2168,6 +2168,91 @@ Unknown properties are collapsed to zero. --> ...@@ -2168,6 +2168,91 @@ Unknown properties are collapsed to zero. -->
<int value="8" label="kLaunchTypeUnspecified"/> <int value="8" label="kLaunchTypeUnspecified"/>
</enum> </enum>
<enum name="AppListNonAppImpressionCategory">
<int value="0" label="APPS"/>
<int value="1" label="SEARCH_RESULTS"/>
<int value="2" label="START"/>
<int value="3" label="CUSTOM_LAUNCHER_PAGE_DEPRECATED"/>
</enum>
<enum name="AppListNonAppImpressionDeviceMode">
<int value="0" label="UNKNOWN"/>
<int value="1" label="FILE"/>
<int value="2" label="HISTORY"/>
<int value="3" label="NAV_SUGGEST"/>
<int value="4" label="SEARCH"/>
<int value="5" label="BOOKMARK"/>
<int value="6" label="DOCUMENT"/>
<int value="7" label="OMNIBOX_DEPRECATED"/>
<int value="8" label="OMNIBOX_GENERIC"/>
</enum>
<enum name="AppListNonAppImpressionFileExtension">
<int value="0" label=".3ga"/>
<int value="1" label=".3gp"/>
<int value="2" label=".aac"/>
<int value="3" label=".alac"/>
<int value="4" label=".asf"/>
<int value="5" label=".avi"/>
<int value="6" label=".bmp"/>
<int value="7" label=".csv"/>
<int value="8" label=".doc"/>
<int value="9" label=".docx"/>
<int value="10" label=".flac"/>
<int value="11" label=".gif"/>
<int value="12" label=".jpeg"/>
<int value="13" label=".jpg"/>
<int value="14" label=".log"/>
<int value="15" label=".m3u"/>
<int value="16" label=".m3u8"/>
<int value="17" label=".m4a"/>
<int value="18" label=".m4v"/>
<int value="19" label=".mid"/>
<int value="20" label=".mkv"/>
<int value="21" label=".mov"/>
<int value="22" label=".mp3"/>
<int value="23" label=".mp4"/>
<int value="24" label=".mpg"/>
<int value="25" label=".odf"/>
<int value="26" label=".odp"/>
<int value="27" label=".ods"/>
<int value="28" label=".odt"/>
<int value="29" label=".oga"/>
<int value="30" label=".ogg"/>
<int value="31" label=".ogv"/>
<int value="32" label=".pdf"/>
<int value="33" label=".png"/>
<int value="34" label=".ppt"/>
<int value="35" label=".pptx"/>
<int value="36" label=".ra"/>
<int value="37" label=".ram"/>
<int value="38" label=".rar"/>
<int value="39" label=".rm"/>
<int value="40" label=".rtf"/>
<int value="41" label=".wav"/>
<int value="42" label=".webm"/>
<int value="43" label=".webp"/>
<int value="44" label=".wma"/>
<int value="45" label=".wmv"/>
<int value="46" label=".xls"/>
<int value="47" label=".xlsx"/>
<int value="48" label=".crdownload"/>
<int value="49" label=".crx"/>
<int value="50" label=".dmg"/>
<int value="51" label=".exe"/>
<int value="52" label=".html"/>
<int value="53" label=".htm"/>
<int value="54" label=".jar"/>
<int value="55" label=".ps"/>
<int value="56" label=".torrent"/>
<int value="57" label=".txt"/>
<int value="58" label=".zip"/>
<int value="59" label=".mhtml"/>
<int value="60" label=".gdoc"/>
<int value="61" label=".gsheet"/>
<int value="62" label=".gslides"/>
</enum>
<enum name="AppListOmniboxResult"> <enum name="AppListOmniboxResult">
<int value="0" label="QUERY_SUGGESTION"/> <int value="0" label="QUERY_SUGGESTION"/>
<int value="1" label="ZERO_STATE_SUGEESTION"/> <int value="1" label="ZERO_STATE_SUGEESTION"/>
...@@ -678,6 +678,237 @@ be describing additional metrics about the same event. ...@@ -678,6 +678,237 @@ be describing additional metrics about the same event.
</metric> </metric>
</event> </event>
<event name="AppListNonAppImpression">
<owner>jiameng@chromium.org</owner>
<owner>thanhdng@chromium.org</owner>
<owner>tby@chromium.org</owner>
<summary>
Records details of impressions and launches of non-apps in the ChromeOS
launcher, such as files, omnibox results, and answer cards.
</summary>
<metric name="Category" enum="AppListNonAppImpressionCategory">
<summary>
The kind of launcher item. Corresponds to the value of
ChromeSearchResult::result_[sub]type.
</summary>
</metric>
<metric name="DayOfWeek">
<summary>
The day of the week that the event was logged on, in the local time zone.
Sunday is 0.
</summary>
</metric>
<metric name="DeviceMode" enum="AppListNonAppImpressionDeviceMode">
<summary>
The mode of the device.
</summary>
</metric>
<metric name="EventId">
<summary>
An ID linking together events within a single set of launcher search
results. One of these may be a launch, and the rest impressions.
</summary>
</metric>
<metric name="FileExtension" enum="AppListNonAppImpressionFileExtension">
<summary>
An enum representing the file extension if this event represents a local
or DriveFS file.
</summary>
</metric>
<metric name="HourOfDay">
<summary>
The hour of the day that the event was logged in. Hours measured from
midnight in the local timezone.
</summary>
</metric>
<metric name="IsLaunched" enum="Boolean">
<summary>
True if the item represented by this event was launched, false otherwise.
</summary>
</metric>
<metric name="LaunchesAtHour00">
<summary>
The number of launches within the last 24 hours at hour 0. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour01">
<summary>
The number of launches within the last 24 hours at hour 1. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour02">
<summary>
The number of launches within the last 24 hours at hour 2. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour03">
<summary>
The number of launches within the last 24 hours at hour 3. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour04">
<summary>
The number of launches within the last 24 hours at hour 4. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour05">
<summary>
The number of launches within the last 24 hours at hour 5. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour06">
<summary>
The number of launches within the last 24 hours at hour 6. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour07">
<summary>
The number of launches within the last 24 hours at hour 7. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour08">
<summary>
The number of launches within the last 24 hours at hour 8. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour09">
<summary>
The number of launches within the last 24 hours at hour 9. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour10">
<summary>
The number of launches within the last 24 hours at hour 10. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour11">
<summary>
The number of launches within the last 24 hours at hour 11. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour12">
<summary>
The number of launches within the last 24 hours at hour 12. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour13">
<summary>
The number of launches within the last 24 hours at hour 13. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour14">
<summary>
The number of launches within the last 24 hours at hour 14. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour15">
<summary>
The number of launches within the last 24 hours at hour 15. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour16">
<summary>
The number of launches within the last 24 hours at hour 16. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour17">
<summary>
The number of launches within the last 24 hours at hour 17. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour18">
<summary>
The number of launches within the last 24 hours at hour 18. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour19">
<summary>
The number of launches within the last 24 hours at hour 19. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour20">
<summary>
The number of launches within the last 24 hours at hour 20. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour21">
<summary>
The number of launches within the last 24 hours at hour 21. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour22">
<summary>
The number of launches within the last 24 hours at hour 22. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesAtHour23">
<summary>
The number of launches within the last 24 hours at hour 23. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="LaunchesThisSession">
<summary>
How many times this item has been launched during this session. Rounded
down to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="Position">
<summary>
The index of this item in the search results list. Indices start at 0.
</summary>
</metric>
<metric name="QueryLength">
<summary>
The length of the raw search query with whitespace trimmed. Rounded down
to the nearest exponential bucket, with a bucket ratio of 1.15.
</summary>
</metric>
<metric name="RelevanceScore">
<summary>
The raw relevance score returned by the relevant search provider for this
item.
</summary>
</metric>
<metric name="TimeOfLastLaunch">
<summary>
The hour when the previous launch of this item occurred. Hours measured
from midnight in the local timezone. This can be any value 0-23, as the
last launch could have been on a previous day.
</summary>
</metric>
<metric name="TimeSinceLastLaunch">
<summary>
Seconds since this item was last launched in this session. Rounded down to
the nearest exponential bucket, with a bucket ratio of 1.045. This makes
the bucket at 24 hour mark approximately 1 hour long.
</summary>
</metric>
</event>
<event name="Autofill.CardUploadDecision"> <event name="Autofill.CardUploadDecision">
<owner>sebsg@chromium.org</owner> <owner>sebsg@chromium.org</owner>
<metric name="UploadDecision"> <metric name="UploadDecision">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment