Completely emitting aggr candidate+auth metrics

This finalizes the aggregate candidate to fully combine the information
from authentication entries and candidate entries, and emits the
combined flow. Clean up is still required.

Bug: 271135048
Test: Build + Won't Submit without E2E Test
Change-Id: I72140e75ccec92779a7803524cc2746b9eed2ab5
This commit is contained in:
Arpan Kaphle
2023-05-02 00:41:55 +00:00
parent d10dc90293
commit 9d77683ff3
4 changed files with 125 additions and 18 deletions

View File

@@ -103,6 +103,10 @@ public class MetricUtilities {
if (t2 - t1 > Integer.MAX_VALUE) {
throw new ArithmeticException("Input timestamps are too far apart and unsupported");
}
if (t2 < t1) {
Slog.i(TAG, "The timestamps aren't in expected order, falling back to default int");
return DEFAULT_INT_32;
}
return (int) ((t2 - t1) / 1000);
}
@@ -466,11 +470,11 @@ public class MetricUtilities {
candidateAggregateMetric.getAggregateCollectiveQuery()
.getUniqueEntryCounts(),
/*query_total_candidate_failure*/
DEFAULT_INT_32,
candidateAggregateMetric.getTotalQueryFailures(),
/*query_framework_exception_unique_classtypes*/
DEFAULT_REPEATED_STR,
candidateAggregateMetric.getUniqueExceptionStringsQuery(),
/*query_per_exception_classtype_counts*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getUniqueExceptionCountsQuery(),
/*auth_response_unique_classtypes*/
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueResponseStrings(),
@@ -484,14 +488,15 @@ public class MetricUtilities {
candidateAggregateMetric.getAggregateCollectiveAuth()
.getUniqueEntryCounts(),
/*auth_total_candidate_failure*/
DEFAULT_INT_32,
candidateAggregateMetric.getTotalAuthFailures(),
/*auth_framework_exception_unique_classtypes*/
DEFAULT_REPEATED_STR,
candidateAggregateMetric.getUniqueExceptionStringsAuth(),
/*auth_per_exception_classtype_counts*/
DEFAULT_REPEATED_INT_32,
candidateAggregateMetric.getUniqueExceptionCountsAuth(),
/*num_auth_clicks*/
candidateAggregateMetric.getNumAuthEntriesTapped(),
/*auth_returned*/ false
/*auth_returned*/
candidateAggregateMetric.isAuthReturned()
);
} catch (Exception e) {
Slog.w(TAG, "Unexpected error during metric logging: " + e);

View File

@@ -25,10 +25,9 @@ import java.util.Map;
* Contains information about what was collected from the authentication entry output.
*/
public class BrowsedAuthenticationMetric {
private static final String TAG = "BrowsedAuthenticationMetric";
private static final String TAG = "AuthenticationMetric";
// The session id of this provider known flow related metric
private final int mSessionIdProvider;
// The provider associated with the press, defaults to -1
private int mProviderUid = -1;

View File

@@ -24,7 +24,8 @@ import java.util.Map;
/**
* This will generate most of its data via using the information of {@link CandidatePhaseMetric}
* across all the providers. This belongs to the metric flow where the calling app is known.
* across all the providers. This belongs to the metric flow where the calling app is known. It
* also contains {@link BrowsedAuthenticationMetric} data aggregated within.
*/
public class CandidateAggregateMetric {
@@ -34,6 +35,9 @@ public class CandidateAggregateMetric {
// Indicates if this provider returned from the candidate query phase,
// true if at least one provider returns validly, even if empty, default false
private boolean mQueryReturned = false;
// For reference, the initial log timestamp when the service started running the API call,
// defaults to -1
private long mServiceBeganTimeNanoseconds = -1;
// Indicates the total number of providers this aggregate captures information for, default 0
private int mNumProviders = 0;
// Indicates if the authentication entry returned, true if at least one entry returns validly,
@@ -47,6 +51,18 @@ public class CandidateAggregateMetric {
// The combined aggregate collective across the auth entry info
private ResponseCollective mAggregateCollectiveAuth =
new ResponseCollective(Map.of(), Map.of());
// The minimum of all the providers query start time, defaults to -1
private long mMinProviderTimestampNanoseconds = -1;
// The maximum of all the providers query finish time, defaults to -1
private long mMaxProviderTimestampsNanoseconds = -1;
// The total number of failures across all the providers, defaults to -1
private int mTotalQueryFailures = -1;
// The map of all seen framework exceptions and their counts across all providers, default empty
private Map<String, Integer> mExceptionCountQuery = new LinkedHashMap<>();
// The total number of failures across all auth entries, defaults to -1
private int mTotalAuthFailures = -1;
// The map of all seen framework exceptions and their counts across auth entries, default empty
private Map<String, Integer> mExceptionCountAuth = new LinkedHashMap<>();
public CandidateAggregateMetric(int sessionIdTrackOne) {
mSessionIdProvider = sessionIdTrackOne;
@@ -72,16 +88,33 @@ public class CandidateAggregateMetric {
Map<String, Integer> responseCountQuery = new LinkedHashMap<>();
Map<EntryEnum, Integer> entryCountQuery = new LinkedHashMap<>();
var providerSessions = providers.values();
long min_query_start = Integer.MAX_VALUE;
long max_query_end = Integer.MIN_VALUE;
for (var session : providerSessions) {
var sessionMetric = session.getProviderSessionMetric();
var candidateMetric = sessionMetric.getCandidatePhasePerProviderMetric();
if (mServiceBeganTimeNanoseconds == -1) {
mServiceBeganTimeNanoseconds = candidateMetric.getServiceBeganTimeNanoseconds();
}
mQueryReturned = mQueryReturned || candidateMetric.isQueryReturned();
ResponseCollective candidateCollective = candidateMetric.getResponseCollective();
ResponseCollective.combineTypeCountMaps(responseCountQuery,
candidateCollective.getResponseCountsMap());
ResponseCollective.combineTypeCountMaps(entryCountQuery,
candidateCollective.getEntryCountsMap());
min_query_start = Math.min(min_query_start,
candidateMetric.getStartQueryTimeNanoseconds());
max_query_end = Math.max(max_query_end, candidateMetric
.getQueryFinishTimeNanoseconds());
mTotalQueryFailures += (candidateMetric.isHasException() ? 1 : 0);
if (!candidateMetric.getFrameworkException().isEmpty()) {
mExceptionCountQuery.put(candidateMetric.getFrameworkException(),
mExceptionCountQuery.getOrDefault(
candidateMetric.getFrameworkException(), 0) + 1);
}
}
mMinProviderTimestampNanoseconds = min_query_start;
mMaxProviderTimestampsNanoseconds = max_query_end;
mAggregateCollectiveQuery = new ResponseCollective(responseCountQuery, entryCountQuery);
}
@@ -101,6 +134,12 @@ public class CandidateAggregateMetric {
authCollective.getResponseCountsMap());
ResponseCollective.combineTypeCountMaps(entryCountAuth,
authCollective.getEntryCountsMap());
mTotalQueryFailures += (authMetric.isHasException() ? 1 : 0);
if (!authMetric.getFrameworkException().isEmpty()) {
mExceptionCountQuery.put(authMetric.getFrameworkException(),
mExceptionCountQuery.getOrDefault(
authMetric.getFrameworkException(), 0) + 1);
}
}
}
mAggregateCollectiveAuth = new ResponseCollective(responseCountAuth, entryCountAuth);
@@ -130,4 +169,67 @@ public class CandidateAggregateMetric {
public boolean isAuthReturned() {
return mAuthReturned;
}
public long getMaxProviderTimestampsNanoseconds() {
return mMaxProviderTimestampsNanoseconds;
}
public long getMinProviderTimestampNanoseconds() {
return mMinProviderTimestampNanoseconds;
}
public int getTotalQueryFailures() {
return mTotalQueryFailures;
}
/**
* Returns the unique, deduped, exception classtypes for logging associated with this provider.
*
* @return a string array for deduped exception classtypes
*/
public String[] getUniqueExceptionStringsQuery() {
String[] result = new String[mExceptionCountQuery.keySet().size()];
mExceptionCountQuery.keySet().toArray(result);
return result;
}
/**
* Returns the unique, deduped, exception classtype counts for logging associated with this
* provider.
*
* @return a string array for deduped classtype exception counts
*/
public int[] getUniqueExceptionCountsQuery() {
return mExceptionCountQuery.values().stream().mapToInt(Integer::intValue).toArray();
}
/**
* Returns the unique, deduped, exception classtypes for logging associated with this provider
* for auth entries.
*
* @return a string array for deduped exception classtypes for auth entries
*/
public String[] getUniqueExceptionStringsAuth() {
String[] result = new String[mExceptionCountAuth.keySet().size()];
mExceptionCountAuth.keySet().toArray(result);
return result;
}
/**
* Returns the unique, deduped, exception classtype counts for logging associated with this
* provider for auth entries.
*
* @return a string array for deduped classtype exception counts for auth entries
*/
public int[] getUniqueExceptionCountsAuth() {
return mExceptionCountAuth.values().stream().mapToInt(Integer::intValue).toArray();
}
public long getServiceBeganTimeNanoseconds() {
return mServiceBeganTimeNanoseconds;
}
public int getTotalAuthFailures() {
return mTotalAuthFailures;
}
}

View File

@@ -100,8 +100,8 @@ public class ProviderSessionMetric {
*/
public void collectAuthenticationExceptionStatus(boolean hasException) {
try {
var mostRecentAuthenticationMetric = mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
BrowsedAuthenticationMetric mostRecentAuthenticationMetric =
getUsedAuthenticationMetric();
mostRecentAuthenticationMetric.setHasException(hasException);
} catch (Exception e) {
Slog.i(TAG, "Error while setting authentication metric exception " + e);
@@ -122,13 +122,9 @@ public class ProviderSessionMetric {
private void collectAuthEntryUpdate(boolean isFailureStatus,
boolean isCompletionStatus, int providerSessionUid) {
// TODO(b/271135048) - Mimic typical candidate update, but with authentication metric
// Collect the final timestamps (and start timestamp), status, exceptions and the provider
// uid. This occurs typically *after* the collection is complete.
var mostRecentAuthenticationMetric = mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
BrowsedAuthenticationMetric mostRecentAuthenticationMetric =
getUsedAuthenticationMetric();
mostRecentAuthenticationMetric.setProviderUid(providerSessionUid);
// TODO(immediately) - add timestamps (no longer needed!!) but also update below values!
if (isFailureStatus) {
mostRecentAuthenticationMetric.setQueryReturned(false);
mostRecentAuthenticationMetric.setProviderStatus(
@@ -142,6 +138,11 @@ public class ProviderSessionMetric {
}
}
private BrowsedAuthenticationMetric getUsedAuthenticationMetric() {
return mBrowsedAuthenticationMetric
.get(mBrowsedAuthenticationMetric.size() - 1);
}
/**
* Used to collect metrics at the update stage when a candidate provider gives back an update.
*