Merge "[AF05] Fill NetworkStatsRecorderFileReading metrics" into main

This commit is contained in:
Junyu Lai 2023-12-26 02:29:56 +00:00 • committed by Gerrit Code Review
commit 59583789e9
3 changed files with 209 additions and 0 deletions

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.metrics;
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 com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED;
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__FAST_DATA_INPUT_STATE__FDIS_DISABLED;
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__OPERATION_TYPE__ROT_READ;
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_UNKNOWN;
import static com.android.server.ConnectivityStatsLog.NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT;
import android.annotation.NonNull;
import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.ConnectivityStatsLog;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Helper class to log NetworkStats related metrics.
*
* This class does not provide thread-safe.
*/
public class NetworkStatsMetricsLogger {
final Dependencies mDeps;
int mReadIndex = 1;
/** Dependency class */
@VisibleForTesting
public static class Dependencies {
/**
* Writes a NETWORK_STATS_RECORDER_FILE_OPERATION_REPORTED event to ConnectivityStatsLog.
*/
public void writeRecorderFileReadingStats(int recorderType, int readIndex,
int readLatencyMillis,
int fileCount, int totalFileSize,
int keys, int uids, int totalHistorySize) {
ConnectivityStatsLog.write(NETWORK_STATS_RECORDER_FILE_OPERATED,
NETWORK_STATS_RECORDER_FILE_OPERATED__OPERATION_TYPE__ROT_READ,
recorderType,
readIndex,
readLatencyMillis,
fileCount,
totalFileSize,
keys,
uids,
totalHistorySize,
NETWORK_STATS_RECORDER_FILE_OPERATED__FAST_DATA_INPUT_STATE__FDIS_DISABLED);
}
}
public NetworkStatsMetricsLogger() {
mDeps = new Dependencies();
}
@VisibleForTesting
public NetworkStatsMetricsLogger(Dependencies deps) {
mDeps = deps;
}
private static int prefixToRecorderType(@NonNull String prefix) {
switch (prefix) {
case PREFIX_XT:
return NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT;
case PREFIX_UID:
return NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UID;
case PREFIX_UID_TAG:
return NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UIDTAG;
default:
return NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UNKNOWN;
}
}
/**
* Log statistics from the NetworkStatsRecorder file reading process into statsd.
*/
public void logRecorderFileReading(@NonNull String prefix, int readLatencyMillis,
@NonNull NetworkStatsCollection collection) {
final Set<Integer> uids = new HashSet<>();
final Map<NetworkStatsCollection.Key, NetworkStatsHistory> entries =
collection.getEntries();
for (final NetworkStatsCollection.Key key : entries.keySet()) {
uids.add(key.uid);
}
int totalHistorySize = 0;
for (final NetworkStatsHistory history : entries.values()) {
totalHistorySize += history.size();
}
// TODO: Fill file characteristics.
mDeps.writeRecorderFileReadingStats(prefixToRecorderType(prefix),
mReadIndex++,
readLatencyMillis,
0 /* fileCount */,
0 /* totalFileSize */,
entries.size(),
uids.size(),
totalHistorySize);
}
}

View file

@ -32,12 +32,14 @@ import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.SystemClock;
import android.service.NetworkStatsRecorderProto;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.FileRotator;
import com.android.metrics.NetworkStatsMetricsLogger;
import com.android.net.module.util.NetworkStatsUtils;
import libcore.io.IoUtils;
@ -90,6 +92,7 @@ public class NetworkStatsRecorder {
private final CombiningRewriter mPendingRewriter;
private WeakReference<NetworkStatsCollection> mComplete;
private final NetworkStatsMetricsLogger mMetricsLogger = new NetworkStatsMetricsLogger();
/**
* Non-persisted recorder, with only one bucket. Used by {@link NetworkStatsObservers}.
@ -182,8 +185,15 @@ public class NetworkStatsRecorder {
Objects.requireNonNull(mRotator, "missing FileRotator");
NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
if (res == null) {
final long readStart = SystemClock.elapsedRealtime();
res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
mComplete = new WeakReference<NetworkStatsCollection>(res);
final long readEnd = SystemClock.elapsedRealtime();
// 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);
}
}
return res;
}

View file

@ -16,8 +16,15 @@
package com.android.server.net;
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_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_XT;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.mockito.Mockito.any;
@ -29,12 +36,16 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.net.NetworkIdentity;
import android.net.NetworkIdentitySet;
import android.net.NetworkStats;
import android.net.NetworkStatsCollection;
import android.os.DropBoxManager;
import androidx.test.filters.SmallTest;
import com.android.internal.util.FileRotator;
import com.android.metrics.NetworkStatsMetricsLogger;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@ -53,6 +64,8 @@ public final class NetworkStatsRecorderTest {
private static final String TAG = NetworkStatsRecorderTest.class.getSimpleName();
private static final String TEST_PREFIX = "test";
private static final int TEST_UID1 = 1234;
private static final int TEST_UID2 = 1235;
@Mock private DropBoxManager mDropBox;
@Mock private NetworkStats.NonMonotonicObserver mObserver;
@ -86,4 +99,65 @@ public final class NetworkStatsRecorderTest {
// Verify that the rotator won't delete files.
verify(rotator, never()).deleteAll();
}
@Test
public void testFileReadingMetrics_empty() {
final NetworkStatsCollection collection = new NetworkStatsCollection(30);
final NetworkStatsMetricsLogger.Dependencies deps =
mock(NetworkStatsMetricsLogger.Dependencies.class);
final NetworkStatsMetricsLogger logger = new NetworkStatsMetricsLogger(deps);
logger.logRecorderFileReading(PREFIX_XT, 888, collection);
verify(deps).writeRecorderFileReadingStats(
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT,
1 /* readIndex */,
888 /* readLatencyMillis */,
0 /* fileCount */,
0 /* totalFileSize */,
0 /* keys */,
0 /* uids */,
0 /* totalHistorySize */
);
// Write second time, verify the index increases.
logger.logRecorderFileReading(PREFIX_XT, 567, collection);
verify(deps).writeRecorderFileReadingStats(
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_XT,
2 /* readIndex */,
567 /* readLatencyMillis */,
0 /* fileCount */,
0 /* totalFileSize */,
0 /* keys */,
0 /* uids */,
0 /* totalHistorySize */
);
}
@Test
public void testFileReadingMetrics() {
final NetworkStatsCollection collection = new NetworkStatsCollection(30);
final NetworkStats.Entry entry = new NetworkStats.Entry();
final NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity.Builder().build());
// Empty entries will be skipped, put some ints to make sure they can be recorded.
entry.rxBytes = 1;
collection.recordData(identSet, TEST_UID1, SET_DEFAULT, TAG_NONE, 0, 60, entry);
collection.recordData(identSet, TEST_UID2, SET_DEFAULT, TAG_NONE, 0, 60, entry);
collection.recordData(identSet, TEST_UID2, SET_FOREGROUND, TAG_NONE, 30, 60, entry);
final NetworkStatsMetricsLogger.Dependencies deps =
mock(NetworkStatsMetricsLogger.Dependencies.class);
final NetworkStatsMetricsLogger logger = new NetworkStatsMetricsLogger(deps);
logger.logRecorderFileReading(PREFIX_UID, 123, collection);
verify(deps).writeRecorderFileReadingStats(
NETWORK_STATS_RECORDER_FILE_OPERATED__RECORDER_PREFIX__PREFIX_UID,
1 /* readIndex */,
123 /* readLatencyMillis */,
0 /* fileCount */,
0 /* totalFileSize */,
3 /* keys */,
2 /* uids */,
5 /* totalHistorySize */
);
}
}