Connectivity metrics: log DnsEvents in-band

This patch changes how DnsEvents are logged in IpConnectivityMetrics.
The following changes are made:
 - DnsEventBatch are not logged after 100 queries on the same network
    - this allows to merge DnsEvent and DnsEventBatch into one class
 - DnsEventBatch are not logged after a network disconnect
    - this allows to remove the NetworkCallback
 - DnsEvent are now logged similarly to ConnectStats when statistics are
   flushed, in a direct call from IpConnectivityMetrics into
   NetdEventListenerService, in a direct call from IpConnectivityMetrics
   into NetdEventListenerService.
    - this allows to remove the Parcelable implementation of DnsEvent
 - transports information is added to DnsEvent.

Test: - simplified NetdEventListenerServiceTest covering dns logging
      - updated IpConnectivityEventBuilderTest
      - updated IpConnectivityMetricsTest
      - $ runtest frameworks-net passes
      - manually verified $ adb shell dumpsys connmetrics list proto
Bug: 34901696
Change-Id: I4fcd0ad7a7b85d587647f471a90c1e53a18fc95a
Merged-In: Ia4b33fd4212741152662a2adbb0533bd1b4902ee

(cherry picked from commit 0699cf9804)
This commit is contained in:
Hugo Benichi
2017-03-22 22:21:44 +09:00
parent 4db137b059
commit 2a5cfb9738
7 changed files with 304 additions and 422 deletions

View File

@@ -16,67 +16,64 @@
package android.net.metrics;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
* A DNS event recorded by NetdEventListenerService.
* {@hide}
*/
final public class DnsEvent implements Parcelable {
public final int netId;
final public class DnsEvent {
// The event type is currently only 1 or 2, so we store it as a byte.
public final byte[] eventTypes;
private static final int SIZE_LIMIT = 20000;
// Network id of the network associated with the event, or 0 if unspecified.
public final int netId;
// Transports of the network associated with the event, as defined in NetworkCapabilities.
// It is the caller responsability to ensure the value of transports does not change between
// calls to addResult.
public final long transports;
// The number of DNS queries recorded. Queries are stored in the structure-of-array style where
// the eventTypes, returnCodes, and latenciesMs arrays have the same length and the i-th event
// is spread across the three array at position i.
public int eventCount;
// The types of DNS queries as defined in INetdEventListener.
public byte[] eventTypes;
// Current getaddrinfo codes go from 1 to EAI_MAX = 15. gethostbyname returns errno, but there
// are fewer than 255 errno values. So we store the result code in a byte as well.
public final byte[] returnCodes;
// The latency is an integer because a) short arrays aren't parcelable and b) a short can only
// store a maximum latency of 32757 or 65535 ms, which is too short for pathologically slow
// queries.
public final int[] latenciesMs;
public byte[] returnCodes;
// Latencies in milliseconds of queries, stored as ints.
public int[] latenciesMs;
public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
public DnsEvent(int netId, long transports, int initialCapacity) {
this.netId = netId;
this.eventTypes = eventTypes;
this.returnCodes = returnCodes;
this.latenciesMs = latenciesMs;
this.transports = transports;
eventTypes = new byte[initialCapacity];
returnCodes = new byte[initialCapacity];
latenciesMs = new int[initialCapacity];
}
private DnsEvent(Parcel in) {
this.netId = in.readInt();
this.eventTypes = in.createByteArray();
this.returnCodes = in.createByteArray();
this.latenciesMs = in.createIntArray();
public void addResult(byte eventType, byte returnCode, int latencyMs) {
if (eventCount >= SIZE_LIMIT) {
// TODO: implement better rate limiting that does not biases metrics.
return;
}
if (eventCount == eventTypes.length) {
resize((int) (1.4 * eventCount));
}
eventTypes[eventCount] = eventType;
returnCodes[eventCount] = returnCode;
latenciesMs[eventCount] = latencyMs;
eventCount++;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(netId);
out.writeByteArray(eventTypes);
out.writeByteArray(returnCodes);
out.writeIntArray(latenciesMs);
}
@Override
public int describeContents() {
return 0;
public void resize(int newLength) {
eventTypes = Arrays.copyOf(eventTypes, newLength);
returnCodes = Arrays.copyOf(returnCodes, newLength);
latenciesMs = Arrays.copyOf(latenciesMs, newLength);
}
@Override
public String toString() {
return String.format("DnsEvent(%d, %d events)", netId, eventTypes.length);
return String.format("DnsEvent(%d events)", eventCount);
}
public static final Parcelable.Creator<DnsEvent> CREATOR = new Parcelable.Creator<DnsEvent>() {
@Override
public DnsEvent createFromParcel(Parcel in) {
return new DnsEvent(in);
}
@Override
public DnsEvent[] newArray(int size) {
return new DnsEvent[size];
}
};
}