Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d77683f authored by Arpan Kaphle's avatar Arpan Kaphle
Browse files

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
parent d10dc902
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -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);
+1 −2
Original line number Diff line number Diff line
@@ -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;

+103 −1
Original line number Diff line number Diff line
@@ -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;
    }
}
+9 −8
Original line number Diff line number Diff line
@@ -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.
     *