Merge "[AF06] Fill file attributes metrics" into main
This commit is contained in:
commit
46afd1b4cb
6 changed files with 106 additions and 13 deletions
|
|
@ -29,15 +29,19 @@ import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FIL
|
|||
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.NetworkStatsCollection;
|
||||
import android.net.NetworkStatsHistory;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.ConnectivityStatsLog;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Helper class to log NetworkStats related metrics.
|
||||
|
|
@ -94,11 +98,47 @@ public class NetworkStatsMetricsLogger {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file count and total byte count for the given directory and prefix.
|
||||
*
|
||||
* @return File count and total byte count as a pair, or 0s if met errors.
|
||||
*/
|
||||
private static Pair<Integer, Integer> getStatsFilesAttributes(
|
||||
@Nullable File statsDir, @NonNull String prefix) {
|
||||
if (statsDir == null) return new Pair<>(0, 0);
|
||||
|
||||
// Only counts the matching files.
|
||||
// The files are named in the following format:
|
||||
// <prefix>.<startTimestamp>-[<endTimestamp>]
|
||||
// e.g. uid_tag.12345-
|
||||
// See FileRotator#FileInfo for more detail.
|
||||
final Pattern pattern = Pattern.compile("^" + prefix + "\\.[0-9]+-[0-9]*$");
|
||||
|
||||
// Ensure that base path exists.
|
||||
statsDir.mkdirs();
|
||||
|
||||
int totalFiles = 0;
|
||||
int totalBytes = 0;
|
||||
for (String name : emptyIfNull(statsDir.list())) {
|
||||
if (!pattern.matcher(name).matches()) continue;
|
||||
|
||||
totalFiles++;
|
||||
// Cast to int is safe since stats persistent files are several MBs in total.
|
||||
totalBytes += (int) (new File(statsDir, name).length());
|
||||
|
||||
}
|
||||
return new Pair<>(totalFiles, totalBytes);
|
||||
}
|
||||
|
||||
private static String [] emptyIfNull(@Nullable String [] array) {
|
||||
return (array == null) ? new String[0] : array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log statistics from the NetworkStatsRecorder file reading process into statsd.
|
||||
*/
|
||||
public void logRecorderFileReading(@NonNull String prefix, int readLatencyMillis,
|
||||
@NonNull NetworkStatsCollection collection) {
|
||||
@Nullable File statsDir, @NonNull NetworkStatsCollection collection) {
|
||||
final Set<Integer> uids = new HashSet<>();
|
||||
final Map<NetworkStatsCollection.Key, NetworkStatsHistory> entries =
|
||||
collection.getEntries();
|
||||
|
|
@ -112,12 +152,12 @@ public class NetworkStatsMetricsLogger {
|
|||
totalHistorySize += history.size();
|
||||
}
|
||||
|
||||
// TODO: Fill file characteristics.
|
||||
final Pair<Integer, Integer> fileAttributes = getStatsFilesAttributes(statsDir, prefix);
|
||||
mDeps.writeRecorderFileReadingStats(prefixToRecorderType(prefix),
|
||||
mReadIndex++,
|
||||
readLatencyMillis,
|
||||
0 /* fileCount */,
|
||||
0 /* totalFileSize */,
|
||||
fileAttributes.first /* fileCount */,
|
||||
fileAttributes.second /* totalFileSize */,
|
||||
entries.size(),
|
||||
uids.size(),
|
||||
totalHistorySize);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import static android.net.TrafficStats.MB_IN_BYTES;
|
|||
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.NetworkIdentitySet;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.NetworkStats.NonMonotonicObserver;
|
||||
|
|
@ -45,6 +46,7 @@ import com.android.net.module.util.NetworkStatsUtils;
|
|||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
|
@ -93,6 +95,8 @@ public class NetworkStatsRecorder {
|
|||
|
||||
private WeakReference<NetworkStatsCollection> mComplete;
|
||||
private final NetworkStatsMetricsLogger mMetricsLogger = new NetworkStatsMetricsLogger();
|
||||
@Nullable
|
||||
private final File mStatsDir;
|
||||
|
||||
/**
|
||||
* Non-persisted recorder, with only one bucket. Used by {@link NetworkStatsObservers}.
|
||||
|
|
@ -114,6 +118,7 @@ public class NetworkStatsRecorder {
|
|||
mSinceBoot = new NetworkStatsCollection(mBucketDuration);
|
||||
|
||||
mPendingRewriter = null;
|
||||
mStatsDir = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -121,7 +126,7 @@ public class NetworkStatsRecorder {
|
|||
*/
|
||||
public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
|
||||
DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags,
|
||||
boolean wipeOnError, boolean useFastDataInput) {
|
||||
boolean wipeOnError, boolean useFastDataInput, @Nullable File statsDir) {
|
||||
mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
|
||||
mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
|
||||
mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
|
||||
|
|
@ -136,6 +141,7 @@ public class NetworkStatsRecorder {
|
|||
mSinceBoot = new NetworkStatsCollection(bucketDuration);
|
||||
|
||||
mPendingRewriter = new CombiningRewriter(mPending);
|
||||
mStatsDir = statsDir;
|
||||
}
|
||||
|
||||
public void setPersistThreshold(long thresholdBytes) {
|
||||
|
|
@ -192,7 +198,8 @@ public class NetworkStatsRecorder {
|
|||
// For legacy recorders which are used for data integrity check, which
|
||||
// have wipeOnError flag unset, skip reporting metrics.
|
||||
if (mWipeOnError) {
|
||||
mMetricsLogger.logRecorderFileReading(mCookie, (int) (readEnd - readStart), res);
|
||||
mMetricsLogger.logRecorderFileReading(mCookie, (int) (readEnd - readStart),
|
||||
mStatsDir, res);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -969,7 +969,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||
return new NetworkStatsRecorder(new FileRotator(
|
||||
baseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
|
||||
mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags,
|
||||
wipeOnError, false /* useFastDataInput */);
|
||||
wipeOnError, false /* useFastDataInput */, baseDir);
|
||||
}
|
||||
|
||||
@GuardedBy("mStatsLock")
|
||||
|
|
|
|||
|
|
@ -156,7 +156,8 @@ class NetworkStatsTest {
|
|||
UID_COLLECTION_BUCKET_DURATION_MS,
|
||||
false /* includeTags */,
|
||||
false /* wipeOnError */,
|
||||
useFastDataInput /* useFastDataInput */
|
||||
useFastDataInput /* useFastDataInput */,
|
||||
it
|
||||
)
|
||||
recorder.orLoadCompleteLocked
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@ import static android.net.NetworkStats.SET_DEFAULT;
|
|||
import static android.net.NetworkStats.SET_FOREGROUND;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
|
||||
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
|
||||
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
|
||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||
|
||||
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UID;
|
||||
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UIDTAG;
|
||||
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT;
|
||||
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
|
||||
|
||||
|
|
@ -36,6 +38,7 @@ import static org.mockito.Mockito.reset;
|
|||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.net.NetworkIdentity;
|
||||
import android.net.NetworkIdentitySet;
|
||||
import android.net.NetworkStats;
|
||||
|
|
@ -49,12 +52,17 @@ import com.android.metrics.NetworkStatsMetricsLogger;
|
|||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
|
||||
import libcore.testing.io.TestIoUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
|
|
@ -78,7 +86,7 @@ public final class NetworkStatsRecorderTest {
|
|||
private NetworkStatsRecorder buildRecorder(FileRotator rotator, boolean wipeOnError) {
|
||||
return new NetworkStatsRecorder(rotator, mObserver, mDropBox, TEST_PREFIX,
|
||||
HOUR_IN_MILLIS, false /* includeTags */, wipeOnError,
|
||||
false /* useFastDataInput */);
|
||||
false /* useFastDataInput */, null /* baseDir */);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -106,7 +114,7 @@ public final class NetworkStatsRecorderTest {
|
|||
final NetworkStatsMetricsLogger.Dependencies deps =
|
||||
mock(NetworkStatsMetricsLogger.Dependencies.class);
|
||||
final NetworkStatsMetricsLogger logger = new NetworkStatsMetricsLogger(deps);
|
||||
logger.logRecorderFileReading(PREFIX_XT, 888, collection);
|
||||
logger.logRecorderFileReading(PREFIX_XT, 888, null /* statsDir */, collection);
|
||||
verify(deps).writeRecorderFileReadingStats(
|
||||
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT,
|
||||
1 /* readIndex */,
|
||||
|
|
@ -119,7 +127,7 @@ public final class NetworkStatsRecorderTest {
|
|||
);
|
||||
|
||||
// Write second time, verify the index increases.
|
||||
logger.logRecorderFileReading(PREFIX_XT, 567, collection);
|
||||
logger.logRecorderFileReading(PREFIX_XT, 567, null /* statsDir */, collection);
|
||||
verify(deps).writeRecorderFileReadingStats(
|
||||
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT,
|
||||
2 /* readIndex */,
|
||||
|
|
@ -148,7 +156,7 @@ public final class NetworkStatsRecorderTest {
|
|||
final NetworkStatsMetricsLogger.Dependencies deps =
|
||||
mock(NetworkStatsMetricsLogger.Dependencies.class);
|
||||
final NetworkStatsMetricsLogger logger = new NetworkStatsMetricsLogger(deps);
|
||||
logger.logRecorderFileReading(PREFIX_UID, 123, collection);
|
||||
logger.logRecorderFileReading(PREFIX_UID, 123, null /* statsDir */, collection);
|
||||
verify(deps).writeRecorderFileReadingStats(
|
||||
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UID,
|
||||
1 /* readIndex */,
|
||||
|
|
@ -160,4 +168,41 @@ public final class NetworkStatsRecorderTest {
|
|||
5 /* totalHistorySize */
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileReadingMetrics_fileAttributes() throws IOException {
|
||||
final NetworkStatsCollection collection = new NetworkStatsCollection(30);
|
||||
|
||||
// Create files for testing. Only the first and the third files should be counted,
|
||||
// with total 26 (each char takes 2 bytes) bytes in the content.
|
||||
final File statsDir = TestIoUtils.createTemporaryDirectory(getClass().getSimpleName());
|
||||
write(statsDir, "uid_tag.1024-2048", "wanted");
|
||||
write(statsDir, "uid_tag.1024-2048.backup", "");
|
||||
write(statsDir, "uid_tag.2048-", "wanted2");
|
||||
write(statsDir, "uid.2048-4096", "unwanted");
|
||||
write(statsDir, "uid.2048-4096.backup", "unwanted2");
|
||||
|
||||
final NetworkStatsMetricsLogger.Dependencies deps =
|
||||
mock(NetworkStatsMetricsLogger.Dependencies.class);
|
||||
final NetworkStatsMetricsLogger logger = new NetworkStatsMetricsLogger(deps);
|
||||
logger.logRecorderFileReading(PREFIX_UID_TAG, 678, statsDir, collection);
|
||||
verify(deps).writeRecorderFileReadingStats(
|
||||
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UIDTAG,
|
||||
1 /* readIndex */,
|
||||
678 /* readLatencyMillis */,
|
||||
2 /* fileCount */,
|
||||
26 /* totalFileSize */,
|
||||
0 /* keys */,
|
||||
0 /* uids */,
|
||||
0 /* totalHistorySize */
|
||||
);
|
||||
}
|
||||
|
||||
private void write(@NonNull File baseDir, @NonNull String name,
|
||||
@NonNull String value) throws IOException {
|
||||
final DataOutputStream out = new DataOutputStream(
|
||||
new FileOutputStream(new File(baseDir, name)));
|
||||
out.writeChars(value);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2231,7 +2231,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
|
|||
return new NetworkStatsRecorder(new FileRotator(
|
||||
directory, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
|
||||
observer, dropBox, prefix, config.bucketDuration, includeTags, wipeOnError,
|
||||
false /* useFastDataInput */);
|
||||
false /* useFastDataInput */, directory);
|
||||
}
|
||||
|
||||
private NetworkStatsCollection getLegacyCollection(String prefix, boolean includeTags) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue