OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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.contextualsearch; | 5 package org.chromium.chrome.browser.contextualsearch; |
6 | 6 |
7 import org.chromium.base.Log; | 7 import org.chromium.chrome.browser.contextualsearch.ContextualSearchRankerLogger
.Feature; |
8 | 8 |
9 import java.net.URL; | 9 import java.net.URL; |
| 10 import java.util.Collections; |
| 11 import java.util.HashMap; |
| 12 import java.util.Map; |
10 | 13 |
11 /** | 14 /** |
12 * Implements the UMA logging for Ranker that's used for Contextual Search Tap S
uppression. | 15 * Implements the UMA logging for Ranker that's used for Contextual Search Tap S
uppression. |
13 */ | 16 */ |
14 public class ContextualSearchRankerLoggerImpl implements ContextualSearchRankerL
ogger { | 17 public class ContextualSearchRankerLoggerImpl implements ContextualSearchRankerL
ogger { |
15 private static final String TAG = "ContextualSearch"; | 18 private static final String TAG = "ContextualSearch"; |
16 | 19 |
| 20 // Names for our features. |
| 21 private static final Map<Feature, String> FEATURE_NAMES; |
| 22 static { |
| 23 Map<Feature, String> names = new HashMap<Feature, String>(); |
| 24 names.put(Feature.OUTCOME_WAS_PANEL_OPENED, "OutcomeWasPanelOpened"); |
| 25 names.put(Feature.OUTCOME_WAS_QUICK_ACTION_CLICKED, "OutcomeWasQuickActi
onClicked"); |
| 26 names.put(Feature.OUTCOME_WAS_QUICK_ANSWER_SEEN, "OutcomeWasQuickAnswerS
een"); |
| 27 names.put(Feature.DURATION_AFTER_SCROLL_MS, "DurationAfterScrollMs"); |
| 28 names.put(Feature.SCREEN_TOP_DPS, "ScreenTopDps"); |
| 29 names.put(Feature.WAS_SCREEN_BOTTOM, "WasScreenBottom"); |
| 30 names.put(Feature.PREVIOUS_WEEK_IMPRESSIONS_COUNT, "PreviousWeekImpressi
onsCount"); |
| 31 names.put(Feature.PREVIOUS_WEEK_CTR_PERCENT, "PreviousWeekCtrPercent"); |
| 32 names.put(Feature.PREVIOUS_28DAY_IMPRESSIONS_COUNT, "Previous28DayImpres
sionsCount"); |
| 33 names.put(Feature.PREVIOUS_28DAY_CTR_PERCENT, "Previous28DayCtrPercent")
; |
| 34 FEATURE_NAMES = Collections.unmodifiableMap(names); |
| 35 } |
| 36 |
17 // Pointer to the native instance of this class. | 37 // Pointer to the native instance of this class. |
18 private long mNativePointer; | 38 private long mNativePointer; |
19 | 39 |
20 // Whether logging for the current URL is currently setup. | 40 // Whether logging for the current URL has been setup. |
21 private boolean mIsLoggingSetup; | 41 private boolean mIsLoggingReadyForUrl; |
22 | 42 |
23 // Whether the service is ready to actually record log data. | 43 // URL of the base page that the log data is associated with. |
24 private boolean mCanServiceActuallyRecord; | 44 private URL mBasePageUrl; |
25 | 45 |
26 // Whether any data has been written to the log since calling setupLoggingFo
rPage(). | 46 // Whether inference has already occurred for this interaction (and calling
#logFeature is no |
27 private boolean mDidLog; | 47 // longer allowed). |
| 48 private boolean mHasInferenceOccurred; |
| 49 |
| 50 // Whether the UI was suppressed. |
| 51 private boolean mWasUiSuppressionInfered; |
| 52 |
| 53 // Map that accumulates all of the Features to log for a specific user-inter
action. |
| 54 private Map<Feature, Object> mFeaturesToLog; |
28 | 55 |
29 /** | 56 /** |
30 * Constructs a Ranker Logger and associated native implementation to write
Contextual Search | 57 * Constructs a Ranker Logger and associated native implementation to write
Contextual Search |
31 * ML data to Ranker. | 58 * ML data to Ranker. |
32 */ | 59 */ |
33 public ContextualSearchRankerLoggerImpl() { | 60 public ContextualSearchRankerLoggerImpl() { |
34 if (isEnabled()) mNativePointer = nativeInit(); | 61 if (isEnabled()) mNativePointer = nativeInit(); |
35 } | 62 } |
36 | 63 |
37 /** | 64 /** |
38 * This method should be called to clean up storage when an instance of this
class is | 65 * This method should be called to clean up storage when an instance of this
class is |
39 * no longer in use. The nativeDestroy will call the destructor on the nati
ve instance. | 66 * no longer in use. The nativeDestroy will call the destructor on the nati
ve instance. |
40 */ | 67 */ |
41 void destroy() { | 68 void destroy() { |
42 if (isEnabled()) { | 69 if (isEnabled()) { |
43 assert mNativePointer != 0; | 70 assert mNativePointer != 0; |
44 writeLogAndReset(); | 71 writeLogAndReset(); |
45 nativeDestroy(mNativePointer); | 72 nativeDestroy(mNativePointer); |
46 mNativePointer = 0; | 73 mNativePointer = 0; |
47 mCanServiceActuallyRecord = false; | |
48 mDidLog = false; | |
49 } | 74 } |
50 mIsLoggingSetup = false; | 75 mIsLoggingReadyForUrl = false; |
51 } | 76 } |
52 | 77 |
53 @Override | 78 @Override |
54 public void setupLoggingForPage(URL basePageUrl) { | 79 public void setupLoggingForPage(URL basePageUrl) { |
55 mIsLoggingSetup = true; | 80 mIsLoggingReadyForUrl = true; |
56 if (isEnabled()) { | 81 mBasePageUrl = basePageUrl; |
57 // The URL may be null for custom Chrome URIs like chrome://flags. | 82 mHasInferenceOccurred = false; |
58 if (basePageUrl != null) { | |
59 nativeSetupLoggingAndRanker(mNativePointer, basePageUrl.toString
()); | |
60 mCanServiceActuallyRecord = true; | |
61 } | |
62 } | |
63 } | 83 } |
64 | 84 |
65 @Override | 85 @Override |
66 public void log(Feature feature, Object value) { | 86 public void logFeature(Feature feature, Object value) { |
67 assert mIsLoggingSetup; | 87 assert mIsLoggingReadyForUrl : "mIsLoggingReadyForUrl false."; |
68 if (!isEnabled()) return; | 88 assert !mHasInferenceOccurred; |
69 | |
70 // TODO(donnd): Add some enforcement that log() calls are done before in
ference time. | |
71 logInternal(feature, value); | |
72 } | |
73 | |
74 @Override | |
75 public void logOutcome(Feature feature, Object value) { | |
76 assert mIsLoggingSetup; | |
77 if (!isEnabled()) return; | 89 if (!isEnabled()) return; |
78 | 90 |
79 logInternal(feature, value); | 91 logInternal(feature, value); |
80 } | 92 } |
81 | 93 |
82 @Override | 94 @Override |
83 public void writeLogAndReset() { | 95 public void logOutcome(Feature feature, Object value) { |
84 if (isEnabled()) { | 96 if (!isEnabled()) return; |
85 if (mDidLog) nativeWriteLogAndReset(mNativePointer); | 97 |
86 mCanServiceActuallyRecord = false; | 98 // Since the panel can be closed at any time, we might try to log that o
utcome immediately. |
87 mDidLog = false; | 99 if (!mIsLoggingReadyForUrl) return; |
88 } | 100 |
89 mIsLoggingSetup = false; | 101 logInternal(feature, value); |
90 } | 102 } |
91 | 103 |
92 /** Whether actually writing data is enabled. If not, we may do nothing or
print. */ | 104 @Override |
| 105 public boolean inferUiSuppression() { |
| 106 mHasInferenceOccurred = true; |
| 107 // TODO(donnd): actually run the Ranker model and register its recommend
ation here! |
| 108 mWasUiSuppressionInfered = false; |
| 109 // TODO(donnd): actually return the recommendation so it can be acted up
on! |
| 110 return false; |
| 111 } |
| 112 |
| 113 @Override |
| 114 public boolean wasUiSuppressionInfered() { |
| 115 return mWasUiSuppressionInfered; |
| 116 } |
| 117 |
| 118 @Override |
| 119 public void reset() { |
| 120 mIsLoggingReadyForUrl = false; |
| 121 mHasInferenceOccurred = false; |
| 122 mFeaturesToLog = null; |
| 123 mBasePageUrl = null; |
| 124 mWasUiSuppressionInfered = false; |
| 125 } |
| 126 |
| 127 @Override |
| 128 public void writeLogAndReset() { |
| 129 // The URL may be null for custom Chrome URIs like chrome://flags. |
| 130 if (isEnabled() && mBasePageUrl != null && mFeaturesToLog != null) { |
| 131 assert mIsLoggingReadyForUrl; |
| 132 nativeSetupLoggingAndRanker(mNativePointer, mBasePageUrl.toString())
; |
| 133 for (Map.Entry<Feature, Object> entry : mFeaturesToLog.entrySet()) { |
| 134 logObject(entry.getKey(), entry.getValue()); |
| 135 } |
| 136 nativeWriteLogAndReset(mNativePointer); |
| 137 } |
| 138 reset(); |
| 139 } |
| 140 |
| 141 /** |
| 142 * Logs the given feature/value to the internal map that accumulates an enti
re record (which can |
| 143 * be logged by calling writeLogAndReset). |
| 144 * @param feature The feature to log. |
| 145 * @param value The value to log. |
| 146 */ |
| 147 private void logInternal(Feature feature, Object value) { |
| 148 if (mFeaturesToLog == null) mFeaturesToLog = new HashMap<Feature, Object
>(); |
| 149 mFeaturesToLog.put(feature, value); |
| 150 } |
| 151 |
| 152 /** Whether actually writing data is enabled. If not, we may do nothing, or
just print. */ |
93 private boolean isEnabled() { | 153 private boolean isEnabled() { |
94 return ContextualSearchFieldTrial.isRankerLoggingEnabled(); | 154 return ContextualSearchFieldTrial.isRankerLoggingEnabled(); |
95 } | 155 } |
96 | 156 |
97 /** | 157 /** |
98 * Logs the given feature/value after checking that logging has been set up. | 158 * Logs the given {@link ContextualSearchRankerLogger.Feature} with the give
n value |
| 159 * {@link Object}. |
99 * @param feature The feature to log. | 160 * @param feature The feature to log. |
100 * @param value The value to log. | 161 * @param value An {@link Object} value to log (must be convertible to a {@c
ode long}). |
101 */ | 162 */ |
102 private void logInternal(Feature feature, Object value) { | 163 private void logObject(Feature feature, Object value) { |
103 if (value instanceof Boolean) { | 164 if (value instanceof Boolean) { |
104 logToNative(feature.toString(), ((boolean) value ? 1 : 0)); | 165 logToNative(feature, ((boolean) value ? 1 : 0)); |
105 } else if (value instanceof Integer) { | 166 } else if (value instanceof Integer) { |
106 logToNative(feature.toString(), Long.valueOf((int) value)); | 167 logToNative(feature, Long.valueOf((int) value)); |
107 } else if (value instanceof Long) { | 168 } else if (value instanceof Long) { |
108 logToNative(feature.toString(), (long) value); | 169 logToNative(feature, (long) value); |
109 } else if (value instanceof Character) { | 170 } else if (value instanceof Character) { |
110 logToNative(feature.toString(), Character.getNumericValue((char) val
ue)); | 171 logToNative(feature, Character.getNumericValue((char) value)); |
111 } else { | 172 } else { |
112 Log.w(TAG, | 173 assert false : "Could not log feature to Ranker: " + feature.toStrin
g() + " of class " |
113 "Could not log feature to Ranker: " + feature.toString() + "
of class " | 174 + value.getClass(); |
114 + value.getClass()); | |
115 } | 175 } |
116 } | 176 } |
117 | 177 |
118 /** | 178 /** |
119 * Logs to the native instance. All native logging must go through this bot
tleneck. | 179 * Logs to the native instance. All native logging must go through this bot
tleneck. |
120 * @param feature The feature to log. | 180 * @param feature The feature to log. |
121 * @param value The value to log. | 181 * @param value The value to log. |
122 */ | 182 */ |
123 private void logToNative(String feature, long value) { | 183 private void logToNative(Feature feature, long value) { |
124 if (mCanServiceActuallyRecord) { | 184 nativeLogLong(mNativePointer, getFeatureName(feature), value); |
125 nativeLogLong(mNativePointer, feature, value); | 185 } |
126 mDidLog = true; | 186 |
127 } | 187 /** |
| 188 * @return The name of the given feature. |
| 189 */ |
| 190 private String getFeatureName(Feature feature) { |
| 191 return FEATURE_NAMES.get(feature); |
128 } | 192 } |
129 | 193 |
130 // =========================================================================
=================== | 194 // =========================================================================
=================== |
131 // Native methods. | 195 // Native methods. |
132 // =========================================================================
=================== | 196 // =========================================================================
=================== |
133 private native long nativeInit(); | 197 private native long nativeInit(); |
134 private native void nativeDestroy(long nativeContextualSearchRankerLoggerImp
l); | 198 private native void nativeDestroy(long nativeContextualSearchRankerLoggerImp
l); |
135 private native void nativeLogLong( | 199 private native void nativeLogLong( |
136 long nativeContextualSearchRankerLoggerImpl, String featureString, l
ong value); | 200 long nativeContextualSearchRankerLoggerImpl, String featureString, l
ong value); |
137 private native void nativeSetupLoggingAndRanker( | 201 private native void nativeSetupLoggingAndRanker( |
138 long nativeContextualSearchRankerLoggerImpl, String basePageUrl); | 202 long nativeContextualSearchRankerLoggerImpl, String basePageUrl); |
139 private native void nativeWriteLogAndReset(long nativeContextualSearchRanker
LoggerImpl); | 203 private native void nativeWriteLogAndReset(long nativeContextualSearchRanker
LoggerImpl); |
140 } | 204 } |
OLD | NEW |