Merge "Add rate limiting to addTombstoneToDropbox." into tm-dev am: 0644bcb7a4 am: d88f79f222
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18090284 Change-Id: I6c851768f48240036249af34722455f8489a97e4 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -46,6 +46,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.am.DropboxRateLimiter;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -308,19 +309,31 @@ public class BootReceiver extends BroadcastReceiver {
|
||||
writeTimestamps(timestamps);
|
||||
}
|
||||
|
||||
private static final DropboxRateLimiter sDropboxRateLimiter = new DropboxRateLimiter();
|
||||
|
||||
/**
|
||||
* Add a tombstone to the DropBox.
|
||||
*
|
||||
* @param ctx Context
|
||||
* @param tombstone path to the tombstone
|
||||
* @param proto whether the tombstone is stored as proto
|
||||
* @param processName the name of the process corresponding to the tombstone
|
||||
*/
|
||||
public static void addTombstoneToDropBox(Context ctx, File tombstone, boolean proto) {
|
||||
public static void addTombstoneToDropBox(
|
||||
Context ctx, File tombstone, boolean proto, String processName) {
|
||||
final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
|
||||
if (db == null) {
|
||||
Slog.e(TAG, "Can't log tombstone: DropBoxManager not available");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we should rate limit and abort early if needed. Do this for both proto and
|
||||
// non-proto tombstones, even though proto tombstones do not support including the counter
|
||||
// of events dropped since rate limiting activated yet.
|
||||
DropboxRateLimiter.RateLimitResult rateLimitResult =
|
||||
sDropboxRateLimiter.shouldRateLimit(TAG_TOMBSTONE, processName);
|
||||
if (rateLimitResult.shouldRateLimit()) return;
|
||||
|
||||
HashMap<String, Long> timestamps = readTimestamps();
|
||||
try {
|
||||
if (proto) {
|
||||
@@ -328,7 +341,9 @@ public class BootReceiver extends BroadcastReceiver {
|
||||
db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0);
|
||||
}
|
||||
} else {
|
||||
final String headers = getBootHeadersToLogAndUpdate();
|
||||
// Add the header indicating how many events have been dropped due to rate limiting.
|
||||
final String headers = getBootHeadersToLogAndUpdate()
|
||||
+ rateLimitResult.createHeader();
|
||||
addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE,
|
||||
TAG_TOMBSTONE);
|
||||
}
|
||||
|
||||
@@ -8809,8 +8809,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
millisSinceOldestPendingRead).append("\n");
|
||||
}
|
||||
}
|
||||
sb.append("Dropped-Count: ").append(
|
||||
rateLimitResult.droppedCountSinceRateLimitActivated()).append("\n");
|
||||
sb.append(rateLimitResult.createHeader());
|
||||
sb.append("\n");
|
||||
|
||||
// Do the rest in a worker thread to avoid blocking the caller on I/O
|
||||
|
||||
@@ -111,8 +111,8 @@ public class DropboxRateLimiter {
|
||||
|
||||
/** Holds information on whether we should rate limit and how many events have been dropped. */
|
||||
public class RateLimitResult {
|
||||
boolean mShouldRateLimit;
|
||||
int mDroppedCountSinceRateLimitActivated;
|
||||
final boolean mShouldRateLimit;
|
||||
final int mDroppedCountSinceRateLimitActivated;
|
||||
|
||||
public RateLimitResult(boolean shouldRateLimit, int droppedCountSinceRateLimitActivated) {
|
||||
mShouldRateLimit = shouldRateLimit;
|
||||
@@ -128,6 +128,11 @@ public class DropboxRateLimiter {
|
||||
public int droppedCountSinceRateLimitActivated() {
|
||||
return mDroppedCountSinceRateLimitActivated;
|
||||
}
|
||||
|
||||
/** Returns a header indicating the number of dropped events. */
|
||||
public String createHeader() {
|
||||
return "Dropped-Count: " + mDroppedCountSinceRateLimitActivated + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private class ErrorRecord {
|
||||
|
||||
@@ -113,19 +113,22 @@ public final class NativeTombstoneManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename.endsWith(".pb")) {
|
||||
handleProtoTombstone(path);
|
||||
BootReceiver.addTombstoneToDropBox(mContext, path, true);
|
||||
} else {
|
||||
BootReceiver.addTombstoneToDropBox(mContext, path, false);
|
||||
String processName = "UNKNOWN";
|
||||
final boolean isProtoFile = filename.endsWith(".pb");
|
||||
File protoPath = isProtoFile ? path : new File(path.getAbsolutePath() + ".pb");
|
||||
|
||||
Optional<TombstoneFile> parsedTombstone = handleProtoTombstone(protoPath, isProtoFile);
|
||||
if (parsedTombstone.isPresent()) {
|
||||
processName = parsedTombstone.get().getProcessName();
|
||||
}
|
||||
BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName);
|
||||
}
|
||||
|
||||
private void handleProtoTombstone(File path) {
|
||||
private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) {
|
||||
final String filename = path.getName();
|
||||
if (!filename.endsWith(".pb")) {
|
||||
Slog.w(TAG, "unexpected tombstone name: " + path);
|
||||
return;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final String suffix = filename.substring("tombstone_".length());
|
||||
@@ -136,11 +139,11 @@ public final class NativeTombstoneManager {
|
||||
number = Integer.parseInt(numberStr);
|
||||
if (number < 0 || number > 99) {
|
||||
Slog.w(TAG, "unexpected tombstone name: " + path);
|
||||
return;
|
||||
return Optional.empty();
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
Slog.w(TAG, "unexpected tombstone name: " + path);
|
||||
return;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
ParcelFileDescriptor pfd;
|
||||
@@ -148,23 +151,27 @@ public final class NativeTombstoneManager {
|
||||
pfd = ParcelFileDescriptor.open(path, MODE_READ_WRITE);
|
||||
} catch (FileNotFoundException ex) {
|
||||
Slog.w(TAG, "failed to open " + path, ex);
|
||||
return;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
final Optional<TombstoneFile> parsedTombstone = TombstoneFile.parse(pfd);
|
||||
if (!parsedTombstone.isPresent()) {
|
||||
IoUtils.closeQuietly(pfd);
|
||||
return;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
TombstoneFile previous = mTombstones.get(number);
|
||||
if (previous != null) {
|
||||
previous.dispose();
|
||||
if (addToList) {
|
||||
synchronized (mLock) {
|
||||
TombstoneFile previous = mTombstones.get(number);
|
||||
if (previous != null) {
|
||||
previous.dispose();
|
||||
}
|
||||
|
||||
mTombstones.put(number, parsedTombstone.get());
|
||||
}
|
||||
|
||||
mTombstones.put(number, parsedTombstone.get());
|
||||
}
|
||||
|
||||
return parsedTombstone;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,6 +370,10 @@ public final class NativeTombstoneManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getProcessName() {
|
||||
return mProcessName;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
IoUtils.closeQuietly(mPfd);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user