From dc02288f2316bd700c7126db20577213a77813d5 Mon Sep 17 00:00:00 2001 From: Arpan Kaphle Date: Mon, 17 Apr 2023 17:26:04 +0000 Subject: [PATCH] Collecting Request:Count metrics This sets up the collection of the request:count metrics, with unique, unknown request strings, cut off at a certain point (20 characters to the end). This is in line with our designed plans, but the exact cut off point may be discussed. The idea is that the server side context is all that's needed for queries. Bug: 271135048 Test: Build + E2E Test in progress (won't submit till that is done) Change-Id: I5420f6dd09f5b52f71926ad20d89d82f9b369b24 --- .../server/credentials/GetRequestSession.java | 8 +-- .../server/credentials/MetricUtilities.java | 28 ++++++++-- .../credentials/PrepareGetRequestSession.java | 3 +- .../metrics/InitialPhaseMetric.java | 53 +++++++++++++++---- .../metrics/RequestSessionMetric.java | 32 ++++++++--- 5 files changed, 94 insertions(+), 30 deletions(-) diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java index f39de43b5076f..0271727249b12 100644 --- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java @@ -19,7 +19,6 @@ package com.android.server.credentials; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; -import android.credentials.CredentialOption; import android.credentials.CredentialProviderInfo; import android.credentials.GetCredentialException; import android.credentials.GetCredentialRequest; @@ -36,7 +35,6 @@ import com.android.server.credentials.metrics.ProviderStatusForMetrics; import java.util.ArrayList; import java.util.Set; -import java.util.stream.Collectors; /** * Central session for a single getCredentials request. This class listens to the @@ -56,11 +54,7 @@ public class GetRequestSession extends RequestSession mRequestCounts = new LinkedHashMap<>(); + public InitialPhaseMetric() { } @@ -55,8 +62,8 @@ public class InitialPhaseMetric { /* -- Direct Latency Utility -- */ public int getServiceStartToQueryLatencyMicroseconds() { - return (int) ((this.mCredentialServiceStartedTimeNanoseconds - - this.mCredentialServiceBeginQueryTimeNanoseconds) / 1000); + return (int) ((mCredentialServiceStartedTimeNanoseconds + - mCredentialServiceBeginQueryTimeNanoseconds) / 1000); } /* -- Timestamps -- */ @@ -64,7 +71,7 @@ public class InitialPhaseMetric { public void setCredentialServiceStartedTimeNanoseconds( long credentialServiceStartedTimeNanoseconds ) { - this.mCredentialServiceStartedTimeNanoseconds = credentialServiceStartedTimeNanoseconds; + mCredentialServiceStartedTimeNanoseconds = credentialServiceStartedTimeNanoseconds; } public void setCredentialServiceBeginQueryTimeNanoseconds( @@ -112,13 +119,11 @@ public class InitialPhaseMetric { /* ------ Count Request Class Types ------ */ - public void setCountRequestClassType(int countRequestClassType) { - mCountRequestClassType = countRequestClassType; + public int getCountRequestClassType() { + return mRequestCounts.size(); } - public int getCountRequestClassType() { - return mCountRequestClassType; - } + /* ------ Origin Specified ------ */ public void setOriginSpecified(boolean originSpecified) { mOriginSpecified = originSpecified; @@ -127,4 +132,34 @@ public class InitialPhaseMetric { public boolean isOriginSpecified() { return mOriginSpecified; } + + /* ------ Unique Request Counts Map Information ------ */ + + public void setRequestCounts(Map requestCounts) { + mRequestCounts = requestCounts; + } + + /** + * Reruns the unique, deduped, request classtypes for logging. + * @return a string array for deduped classtypes + */ + public String[] getUniqueRequestStrings() { + if (mRequestCounts.isEmpty()) { + Log.w(TAG, "There are no unique string request types collected"); + } + String[] result = new String[mRequestCounts.keySet().size()]; + mRequestCounts.keySet().toArray(result); + return result; + } + + /** + * Reruns the unique, deduped, request classtype counts for logging. + * @return a string array for deduped classtype counts + */ + public int[] getUniqueRequestCounts() { + if (mRequestCounts.isEmpty()) { + Log.w(TAG, "There are no unique string request type counts collected"); + } + return mRequestCounts.values().stream().mapToInt(Integer::intValue).toArray(); + } } diff --git a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java index 10bf56c853f58..18e04df9416ae 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java @@ -16,10 +16,12 @@ package com.android.server.credentials.metrics; +import static com.android.server.credentials.MetricUtilities.DELTA_CUT; +import static com.android.server.credentials.MetricUtilities.generateMetricKey; import static com.android.server.credentials.MetricUtilities.logApiCalledCandidatePhase; import static com.android.server.credentials.MetricUtilities.logApiCalledFinalPhase; -import android.annotation.NonNull; +import android.credentials.GetCredentialRequest; import android.credentials.ui.UserSelectionDialogResult; import android.os.IBinder; import android.util.Log; @@ -27,6 +29,7 @@ import android.util.Log; import com.android.server.credentials.ProviderSession; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -48,7 +51,6 @@ public class RequestSessionMetric { protected final ChosenProviderFinalPhaseMetric mChosenProviderFinalPhaseMetric = new ChosenProviderFinalPhaseMetric(); // TODO(b/271135048) - Replace this with a new atom per each browsing emit (V4) - @NonNull protected List mCandidateBrowsingPhaseMetric = new ArrayList<>(); public RequestSessionMetric() { @@ -161,16 +163,32 @@ public class RequestSessionMetric { } } + // Used by get flows to generate the unique request count maps + private Map getRequestCountMap(GetCredentialRequest request) { + Map uniqueRequestCounts = new LinkedHashMap<>(); + try { + request.getCredentialOptions().forEach(option -> { + String optionKey = generateMetricKey(option.getType(), DELTA_CUT); + if (!uniqueRequestCounts.containsKey(optionKey)) { + uniqueRequestCounts.put(optionKey, 0); + } + uniqueRequestCounts.put(optionKey, uniqueRequestCounts.get(optionKey) + 1); + }); + } catch (Exception e) { + Log.w(TAG, "Unexpected error during get request metric logging: " + e); + } + return uniqueRequestCounts; + } + /** * Collects initializations for Get flow metrics. * - * @param requestClassTypeCount the number of class types in the request - * @param origin indicates if an origin was passed in or not + * @param request the get credential request containing information to parse for metrics */ - public void collectGetFlowInitialMetricInfo(int requestClassTypeCount, boolean origin) { + public void collectGetFlowInitialMetricInfo(GetCredentialRequest request) { try { - mInitialPhaseMetric.setCountRequestClassType(requestClassTypeCount); - mInitialPhaseMetric.setOriginSpecified(origin); + mInitialPhaseMetric.setOriginSpecified(request.getOrigin() != null); + mInitialPhaseMetric.setRequestCounts(getRequestCountMap(request)); } catch (Exception e) { Log.w(TAG, "Unexpected error during metric logging: " + e); }