Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.compositor.bottombar.contextualsearch; | 5 package org.chromium.chrome.browser.compositor.bottombar.contextualsearch; |
| 6 | 6 |
| 7 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState; | 7 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState; |
| 8 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange Reason; | 8 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange Reason; |
| 9 import org.chromium.chrome.browser.contextualsearch.ContextualSearchHeuristics; | 9 import org.chromium.chrome.browser.contextualsearch.ContextualSearchHeuristics; |
| 10 import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger ; | 10 import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger ; |
| 11 import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger Impl; | |
| 12 import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma; | 11 import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma; |
| 13 import org.chromium.chrome.browser.contextualsearch.QuickActionCategory; | 12 import org.chromium.chrome.browser.contextualsearch.QuickActionCategory; |
| 14 | 13 |
| 15 import java.net.URL; | |
| 16 | |
| 17 /** | 14 /** |
| 18 * This class is responsible for all the logging related to Contextual Search. | 15 * This class is responsible for all the logging related to Contextual Search. |
| 19 */ | 16 */ |
| 20 public class ContextualSearchPanelMetrics { | 17 public class ContextualSearchPanelMetrics { |
| 21 private static final int MILLISECONDS_TO_NANOSECONDS = 1000000; | 18 private static final int MILLISECONDS_TO_NANOSECONDS = 1000000; |
| 22 | 19 |
| 23 // The Ranker logger to use to write Tap Suppression Ranker logs to UMA. | |
| 24 private final ContextualSearchRankerLogger mTapSuppressionRankerLogger; | |
| 25 | |
| 26 // Flags for logging. | 20 // Flags for logging. |
| 27 private boolean mDidSearchInvolvePromo; | 21 private boolean mDidSearchInvolvePromo; |
| 28 private boolean mWasSearchContentViewSeen; | 22 private boolean mWasSearchContentViewSeen; |
| 29 private boolean mIsPromoActive; | 23 private boolean mIsPromoActive; |
| 30 private boolean mHasExpanded; | 24 private boolean mHasExpanded; |
| 31 private boolean mHasMaximized; | 25 private boolean mHasMaximized; |
| 32 private boolean mHasExitedPeeking; | 26 private boolean mHasExitedPeeking; |
| 33 private boolean mHasExitedExpanded; | 27 private boolean mHasExitedExpanded; |
| 34 private boolean mHasExitedMaximized; | 28 private boolean mHasExitedMaximized; |
| 35 private boolean mIsSerpNavigation; | 29 private boolean mIsSerpNavigation; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 51 // Time when a search request was started. Reset by chained searches. | 45 // Time when a search request was started. Reset by chained searches. |
| 52 // Used to log the time it takes for a Search Result to become available. | 46 // Used to log the time it takes for a Search Result to become available. |
| 53 private long mSearchRequestStartTimeNs; | 47 private long mSearchRequestStartTimeNs; |
| 54 // Time when the panel was opened beyond peeked. Reset when the panel is clo sed. | 48 // Time when the panel was opened beyond peeked. Reset when the panel is clo sed. |
| 55 // Used to log how long the panel was open. | 49 // Used to log how long the panel was open. |
| 56 private long mPanelOpenedBeyondPeekTimeNs; | 50 private long mPanelOpenedBeyondPeekTimeNs; |
| 57 // The current set of heuristics that should be logged with results seen whe n the panel closes. | 51 // The current set of heuristics that should be logged with results seen whe n the panel closes. |
| 58 private ContextualSearchHeuristics mResultsSeenExperiments; | 52 private ContextualSearchHeuristics mResultsSeenExperiments; |
| 59 // The current set of heuristics to be logged through ranker with results se en when the panel | 53 // The current set of heuristics to be logged through ranker with results se en when the panel |
| 60 // closes. | 54 // closes. |
| 61 private ContextualSearchHeuristics mRankerLogExperiments; | 55 private ContextualSearchRankerLogger mRankerLogger; |
| 62 | |
| 63 /** | |
| 64 * Constructs an object to track metrics for the Contextual Search Overlay P anel. | |
| 65 */ | |
| 66 ContextualSearchPanelMetrics() { | |
| 67 mTapSuppressionRankerLogger = new ContextualSearchRankerLoggerImpl(); | |
| 68 } | |
| 69 | 56 |
| 70 /** | 57 /** |
| 71 * Log information when the panel's state has changed. | 58 * Log information when the panel's state has changed. |
| 72 * @param fromState The state the panel is transitioning from. | 59 * @param fromState The state the panel is transitioning from. |
| 73 * @param toState The state that the panel is transitioning to. | 60 * @param toState The state that the panel is transitioning to. |
| 74 * @param reason The reason for the state change. | 61 * @param reason The reason for the state change. |
| 75 */ | 62 */ |
| 76 public void onPanelStateChanged(PanelState fromState, PanelState toState, | 63 public void onPanelStateChanged(PanelState fromState, PanelState toState, |
| 77 StateChangeReason reason) { | 64 StateChangeReason reason) { |
| 78 // Note: the logging within this function includes the promo, unless spe cifically | 65 // Note: the logging within this function includes the promo, unless spe cifically |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 90 boolean isContentVisible = | 77 boolean isContentVisible = |
| 91 toState == PanelState.MAXIMIZED || toState == PanelState.EXPANDE D; | 78 toState == PanelState.MAXIMIZED || toState == PanelState.EXPANDE D; |
| 92 boolean isExitingPanelOpenedBeyondPeeked = mWasPanelOpenedBeyondPeek && !isContentVisible; | 79 boolean isExitingPanelOpenedBeyondPeeked = mWasPanelOpenedBeyondPeek && !isContentVisible; |
| 93 | 80 |
| 94 if (toState == PanelState.CLOSED && mPanelTriggerTimeFromTapNs != 0 | 81 if (toState == PanelState.CLOSED && mPanelTriggerTimeFromTapNs != 0 |
| 95 && reason == StateChangeReason.BASE_PAGE_SCROLL) { | 82 && reason == StateChangeReason.BASE_PAGE_SCROLL) { |
| 96 long durationMs = | 83 long durationMs = |
| 97 (System.nanoTime() - mPanelTriggerTimeFromTapNs) / MILLISECO NDS_TO_NANOSECONDS; | 84 (System.nanoTime() - mPanelTriggerTimeFromTapNs) / MILLISECO NDS_TO_NANOSECONDS; |
| 98 ContextualSearchUma.logDurationBetweenTriggerAndScroll( | 85 ContextualSearchUma.logDurationBetweenTriggerAndScroll( |
| 99 durationMs, mWasSearchContentViewSeen); | 86 durationMs, mWasSearchContentViewSeen); |
| 100 mTapSuppressionRankerLogger.log( | |
| 101 ContextualSearchRankerLogger.Feature.DURATION_BEFORE_SCROLL_ MS, durationMs); | |
| 102 } | 87 } |
| 103 | 88 |
| 104 if (isEndingSearch) { | 89 if (isEndingSearch) { |
| 105 long durationMs = (System.nanoTime() - mFirstPeekTimeNs) / MILLISECO NDS_TO_NANOSECONDS; | 90 long durationMs = (System.nanoTime() - mFirstPeekTimeNs) / MILLISECO NDS_TO_NANOSECONDS; |
| 106 ContextualSearchUma.logPanelViewDurationAction(durationMs); | 91 ContextualSearchUma.logPanelViewDurationAction(durationMs); |
| 107 if (!mDidSearchInvolvePromo) { | 92 if (!mDidSearchInvolvePromo) { |
| 108 // Measure duration only when the promo is not involved. | 93 // Measure duration only when the promo is not involved. |
| 109 ContextualSearchUma.logDuration(mWasSearchContentViewSeen, isCha ined, durationMs); | 94 ContextualSearchUma.logDuration(mWasSearchContentViewSeen, isCha ined, durationMs); |
| 110 } | 95 } |
| 111 if (mIsPromoActive) { | 96 if (mIsPromoActive) { |
| 112 // The user is exiting still in the promo, without choosing an o ption. | 97 // The user is exiting still in the promo, without choosing an o ption. |
| 113 ContextualSearchUma.logPromoSeen(mWasSearchContentViewSeen, mWas ActivatedByTap); | 98 ContextualSearchUma.logPromoSeen(mWasSearchContentViewSeen, mWas ActivatedByTap); |
| 114 } else { | 99 } else { |
| 115 ContextualSearchUma.logResultsSeen(mWasSearchContentViewSeen, mW asActivatedByTap); | 100 ContextualSearchUma.logResultsSeen(mWasSearchContentViewSeen, mW asActivatedByTap); |
| 116 } | 101 } |
| 117 | 102 |
| 118 if (mWasContextualCardsDataShown) { | 103 if (mWasContextualCardsDataShown) { |
| 119 ContextualSearchUma.logContextualCardsResultsSeen(mWasSearchCont entViewSeen); | 104 ContextualSearchUma.logContextualCardsResultsSeen(mWasSearchCont entViewSeen); |
|
Theresa
2017/05/30 20:25:24
I think ideally we would send some sort of signal
Donn Denman
2017/05/30 23:13:24
Agreed, I think this would be ideal, though not su
| |
| 120 } | 105 } |
| 121 if (mWasQuickActionShown) { | 106 if (mWasQuickActionShown) { |
| 122 ContextualSearchUma.logQuickActionResultsSeen(mWasSearchContentV iewSeen, | 107 ContextualSearchUma.logQuickActionResultsSeen(mWasSearchContentV iewSeen, |
| 123 mQuickActionCategory); | 108 mQuickActionCategory); |
| 124 ContextualSearchUma.logQuickActionClicked(mWasQuickActionClicked , | 109 ContextualSearchUma.logQuickActionClicked(mWasQuickActionClicked , |
| 125 mQuickActionCategory); | 110 mQuickActionCategory); |
| 126 mTapSuppressionRankerLogger.logOutcome( | 111 if (mRankerLogger != null) { |
| 127 ContextualSearchRankerLogger.Feature.OUTCOME_WAS_QUICK_A CTION_CLICKED, | 112 mRankerLogger.logOutcome( |
| 128 mWasQuickActionClicked); | 113 ContextualSearchRankerLogger.Feature.OUTCOME_WAS_QUI CK_ACTION_CLICKED, |
| 114 mWasQuickActionClicked); | |
| 115 } | |
| 129 } | 116 } |
| 130 | 117 |
| 131 if (mResultsSeenExperiments != null) { | 118 if (mResultsSeenExperiments != null) { |
| 132 mResultsSeenExperiments.logResultsSeen( | 119 mResultsSeenExperiments.logResultsSeen( |
| 133 mWasSearchContentViewSeen, mWasActivatedByTap); | 120 mWasSearchContentViewSeen, mWasActivatedByTap); |
| 134 mResultsSeenExperiments = null; | 121 mResultsSeenExperiments = null; |
| 135 } | 122 } |
| 136 | 123 |
| 137 if (mWasActivatedByTap) { | 124 if (mWasActivatedByTap) { |
| 138 boolean wasAnySuppressionHeuristicSatisfied = mWasAnyHeuristicSa tisfiedOnPanelShow; | 125 boolean wasAnySuppressionHeuristicSatisfied = mWasAnyHeuristicSa tisfiedOnPanelShow; |
| 139 ContextualSearchUma.logAnyTapSuppressionHeuristicSatisfied( | 126 ContextualSearchUma.logAnyTapSuppressionHeuristicSatisfied( |
| 140 mWasSearchContentViewSeen, wasAnySuppressionHeuristicSat isfied); | 127 mWasSearchContentViewSeen, wasAnySuppressionHeuristicSat isfied); |
| 141 // Log all the experiments to the Ranker logger. | 128 // Update The Ranker logger. |
|
Theresa
2017/05/30 20:25:24
nit: s/The/the
Donn Denman
2017/05/30 23:13:24
Done.
| |
| 142 if (mRankerLogExperiments != null) { | 129 if (mRankerLogger != null) { |
| 143 mTapSuppressionRankerLogger.logOutcome( | 130 // Tell Ranker about the primary outcome. |
| 131 mRankerLogger.logOutcome( | |
| 144 ContextualSearchRankerLogger.Feature.OUTCOME_WAS_PAN EL_OPENED, | 132 ContextualSearchRankerLogger.Feature.OUTCOME_WAS_PAN EL_OPENED, |
| 145 mWasSearchContentViewSeen); | 133 mWasSearchContentViewSeen); |
| 146 mRankerLogExperiments.logRankerTapSuppression(mTapSuppressio nRankerLogger); | 134 // UMA-Log the Ranker inference signal for Tap only. |
| 147 mRankerLogExperiments = null; | 135 ContextualSearchUma.logRankerInferenceResultsSeen( |
| 136 mWasSearchContentViewSeen, mRankerLogger.wasUiSuppre ssionInfered()); | |
| 148 } | 137 } |
| 149 // Reset writing to Ranker so whatever interactions occurred are recorded as a | |
| 150 // complete record. | |
| 151 mTapSuppressionRankerLogger.writeLogAndReset(); | |
| 152 | |
| 153 ContextualSearchUma.logSelectionLengthResultsSeen( | 138 ContextualSearchUma.logSelectionLengthResultsSeen( |
| 154 mWasSearchContentViewSeen, mSelectionLength); | 139 mWasSearchContentViewSeen, mSelectionLength); |
| 155 } | 140 } |
| 141 | |
| 142 // Reset writing to Ranker so whatever interactions occurred are rec orded as a | |
| 143 // complete record. | |
| 144 if (mRankerLogger != null) mRankerLogger.writeLogAndReset(); | |
| 145 mRankerLogger = null; | |
| 156 } | 146 } |
| 157 | 147 |
| 158 if (isExitingPanelOpenedBeyondPeeked) { | 148 if (isExitingPanelOpenedBeyondPeeked) { |
| 159 assert mPanelOpenedBeyondPeekTimeNs != 0; | 149 assert mPanelOpenedBeyondPeekTimeNs != 0; |
| 160 long durationPanelOpen = (System.nanoTime() - mPanelOpenedBeyondPeek TimeNs) | 150 long durationPanelOpen = (System.nanoTime() - mPanelOpenedBeyondPeek TimeNs) |
| 161 / MILLISECONDS_TO_NANOSECONDS; | 151 / MILLISECONDS_TO_NANOSECONDS; |
| 162 ContextualSearchUma.logPanelOpenDuration(durationPanelOpen); | 152 ContextualSearchUma.logPanelOpenDuration(durationPanelOpen); |
| 163 mPanelOpenedBeyondPeekTimeNs = 0; | 153 mPanelOpenedBeyondPeekTimeNs = 0; |
| 164 mWasPanelOpenedBeyondPeek = false; | 154 mWasPanelOpenedBeyondPeek = false; |
| 165 } | 155 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 | 312 |
| 323 /** | 313 /** |
| 324 * Sets the experiments to log with results seen. | 314 * Sets the experiments to log with results seen. |
| 325 * @param resultsSeenExperiments The experiments to log when the panel resul ts are known. | 315 * @param resultsSeenExperiments The experiments to log when the panel resul ts are known. |
| 326 */ | 316 */ |
| 327 public void setResultsSeenExperiments(ContextualSearchHeuristics resultsSeen Experiments) { | 317 public void setResultsSeenExperiments(ContextualSearchHeuristics resultsSeen Experiments) { |
| 328 mResultsSeenExperiments = resultsSeenExperiments; | 318 mResultsSeenExperiments = resultsSeenExperiments; |
| 329 } | 319 } |
| 330 | 320 |
| 331 /** | 321 /** |
| 332 * Sets the experiments to log through Ranker with results seen. | 322 * Sets up logging through Ranker for outcomes. |
| 333 * @param rankerLogExperiments The experiments to log through Ranker when th e panel results | 323 * @param rankerLogger The {@link ContextualSearchRankerLogger} currently be ing used to measure |
| 334 * are known. | 324 * or suppress the UI by Ranker. |
|
Theresa
2017/05/30 20:25:24
nit: align "or" with "The" on the previous line
Donn Denman
2017/05/30 23:13:24
Oh, Thanks for pointing this out! I've been doing
| |
| 335 * @param basePageUrl The URL of the base page to log along with Ranker data . | |
| 336 */ | 325 */ |
| 337 public void setRankerLogExperiments( | 326 public void setRankerLogger(ContextualSearchRankerLogger rankerLogger) { |
| 338 ContextualSearchHeuristics rankerLogExperiments, URL basePageUrl) { | 327 mRankerLogger = rankerLogger; |
| 339 mRankerLogExperiments = rankerLogExperiments; | |
| 340 mTapSuppressionRankerLogger.setupLoggingForPage(basePageUrl); | |
| 341 } | 328 } |
| 342 | 329 |
| 343 /** | 330 /** |
| 344 * Determine whether a new contextual search is starting. | 331 * Determine whether a new contextual search is starting. |
| 345 * @param toState The contextual search state that will be transitioned to. | 332 * @param toState The contextual search state that will be transitioned to. |
| 346 * @param reason The reason for the search state transition. | 333 * @param reason The reason for the search state transition. |
| 347 * @return Whether a new contextual search is starting. | 334 * @return Whether a new contextual search is starting. |
| 348 */ | 335 */ |
| 349 private boolean isStartingNewContextualSearch(PanelState toState, StateChang eReason reason) { | 336 private boolean isStartingNewContextualSearch(PanelState toState, StateChang eReason reason) { |
| 350 return toState == PanelState.PEEKED | 337 return toState == PanelState.PEEKED |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 367 | 354 |
| 368 /** | 355 /** |
| 369 * @param fromState The state the panel is transitioning from. | 356 * @param fromState The state the panel is transitioning from. |
| 370 * @return Whether there is an ongoing contextual search. | 357 * @return Whether there is an ongoing contextual search. |
| 371 */ | 358 */ |
| 372 private boolean isOngoingContextualSearch(PanelState fromState) { | 359 private boolean isOngoingContextualSearch(PanelState fromState) { |
| 373 return fromState != PanelState.UNDEFINED && fromState != PanelState.CLOS ED; | 360 return fromState != PanelState.UNDEFINED && fromState != PanelState.CLOS ED; |
| 374 } | 361 } |
| 375 } | 362 } |
| 376 | 363 |
| OLD | NEW |