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

Commit 3346da99 authored by Siim Sammul's avatar Siim Sammul Committed by Automerger Merge Worker
Browse files

Merge "Count the number of dropped events due to rate limiting and attach that...

Merge "Count the number of dropped events due to rate limiting and attach that number to the header of the dropbox entry." into tm-dev am: 48ecaf9d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17619726



Change-Id: I1faa5dba1305b47e36baa7307eac60a8e8748ad2
Ignore-AOSP-First: this is an automerge
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 3c89ee75 48ecaf9d
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -8713,7 +8713,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
        // Check if we should rate limit and abort early if needed.
        if (mDropboxRateLimiter.shouldRateLimit(eventType, processName)) return;
        final DropboxRateLimiter.RateLimitResult rateLimitResult =
                mDropboxRateLimiter.shouldRateLimit(eventType, processName);
        if (rateLimitResult.shouldRateLimit()) return;
        final StringBuilder sb = new StringBuilder(1024);
        appendDropBoxProcessHeaders(process, processName, sb);
@@ -8762,6 +8764,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                        millisSinceOldestPendingRead).append("\n");
            }
        }
        sb.append("Dropped-Count: ").append(
                rateLimitResult.droppedCountSinceRateLimitActivated()).append("\n");
        sb.append("\n");
        // Do the rest in a worker thread to avoid blocking the caller on I/O
+43 −6
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ public class DropboxRateLimiter {
    }

    /** Determines whether dropbox entries of a specific tag and process should be rate limited. */
    public boolean shouldRateLimit(String eventType, String processName) {
    public RateLimitResult shouldRateLimit(String eventType, String processName) {
        // Rate-limit how often we're willing to do the heavy lifting to collect and record logs.
        final long now = mClock.uptimeMillis();
        synchronized (mErrorClusterRecords) {
@@ -60,17 +60,33 @@ public class DropboxRateLimiter {
            if (errRecord == null) {
                errRecord = new ErrorRecord(now, 1);
                mErrorClusterRecords.put(errorKey(eventType, processName), errRecord);
            } else if (now - errRecord.getStartTime() > RATE_LIMIT_BUFFER_DURATION) {
                return new RateLimitResult(false, 0);
            }

            if (now - errRecord.getStartTime() > RATE_LIMIT_BUFFER_DURATION) {
                errRecord.setStartTime(now);
                errRecord.setCount(1);
            } else {
                return new RateLimitResult(false, recentlyDroppedCount(errRecord));
            }

            errRecord.incrementCount();
                if (errRecord.getCount() > RATE_LIMIT_ALLOWED_ENTRIES) return true;
            if (errRecord.getCount() > RATE_LIMIT_ALLOWED_ENTRIES) {
                return new RateLimitResult(true, recentlyDroppedCount(errRecord));
            }
        }
        return false;
        return new RateLimitResult(false, 0);
    }

    /**
     * Returns the number of entries of a certain type and process that have recenlty been
     * dropped. Resets every RATE_LIMIT_BUFFER_DURATION if events are still actively created or
     * RATE_LIMIT_BUFFER_EXPIRY if not. */
    private int recentlyDroppedCount(ErrorRecord errRecord) {
        if (errRecord == null || errRecord.getCount() < RATE_LIMIT_ALLOWED_ENTRIES) return 0;
        return errRecord.getCount() - RATE_LIMIT_ALLOWED_ENTRIES;
    }


    private void maybeRemoveExpiredRecords(long now) {
        if (now - mLastMapCleanUp <= RATE_LIMIT_BUFFER_EXPIRY) return;

@@ -87,6 +103,27 @@ public class DropboxRateLimiter {
        return eventType + processName;
    }

    /** Holds information on whether we should rate limit and how many events have been dropped. */
    public class RateLimitResult {
        boolean mShouldRateLimit;
        int mDroppedCountSinceRateLimitActivated;

        public RateLimitResult(boolean shouldRateLimit, int droppedCountSinceRateLimitActivated) {
            mShouldRateLimit = shouldRateLimit;
            mDroppedCountSinceRateLimitActivated = droppedCountSinceRateLimitActivated;
        }

        /** Whether to rate limit. */
        public boolean shouldRateLimit() {
            return mShouldRateLimit;
        }

        /** The number of dropped events since rate limit was activated. */
        public int droppedCountSinceRateLimitActivated() {
            return mDroppedCountSinceRateLimitActivated;
        }
    }

    private class ErrorRecord {
        long mStartTime;
        int mCount;
+34 −15
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.am;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

@@ -43,34 +44,52 @@ public class DropboxRateLimiterTest {
    @Test
    public void testMultipleProcesses() {
        // The first 5 entries should not be rate limited.
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        // Different processes and tags should not get rate limited either.
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process2"));
        assertFalse(mRateLimiter.shouldRateLimit("tag2", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process2").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag2", "process").shouldRateLimit());
        // The 6th entry of the same process should be rate limited.
        assertTrue(mRateLimiter.shouldRateLimit("tag", "process"));
        assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
    }

    @Test
    public void testBufferClearing() throws Exception {
        // The first 5 entries should not be rate limited.
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
        // The 6th entry of the same process should be rate limited.
        assertTrue(mRateLimiter.shouldRateLimit("tag", "process"));
        assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());

        // After 11 seconds there should be nothing left in the buffer and the same type of entry
        // should not get rate limited anymore.
        mClock.setOffsetMillis(11000);

        assertFalse(mRateLimiter.shouldRateLimit("tag", "process"));
        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
    }

    @Test
    public void testRecentlyDroppedCount() throws Exception {
        assertEquals(0,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
        assertEquals(0,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
        assertEquals(0,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
        assertEquals(0,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
        assertEquals(0,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
        assertEquals(1,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
        assertEquals(2,
                mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
    }

    private static class TestClock implements DropboxRateLimiter.Clock {