1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.metrics; 18 19 import java.util.Arrays; 20 import java.util.BitSet; 21 22 /** 23 * A batch of DNS events recorded by NetdEventListenerService for a specific network. 24 * {@hide} 25 */ 26 final public class DnsEvent { 27 28 private static final int SIZE_LIMIT = 20000; 29 30 // Network id of the network associated with the event, or 0 if unspecified. 31 public final int netId; 32 // Transports of the network associated with the event, as defined in NetworkCapabilities. 33 // It is the caller responsability to ensure the value of transports does not change between 34 // calls to addResult. 35 public final long transports; 36 // The number of DNS queries recorded. Queries are stored in the structure-of-array style where 37 // the eventTypes, returnCodes, and latenciesMs arrays have the same length and the i-th event 38 // is spread across the three array at position i. 39 public int eventCount; 40 // The number of successful DNS queries recorded. 41 public int successCount; 42 // The types of DNS queries as defined in INetdEventListener. 43 public byte[] eventTypes; 44 // Current getaddrinfo codes go from 1 to EAI_MAX = 15. gethostbyname returns errno, but there 45 // are fewer than 255 errno values. So we store the result code in a byte as well. 46 public byte[] returnCodes; 47 // Latencies in milliseconds of queries, stored as ints. 48 public int[] latenciesMs; 49 DnsEvent(int netId, long transports, int initialCapacity)50 public DnsEvent(int netId, long transports, int initialCapacity) { 51 this.netId = netId; 52 this.transports = transports; 53 eventTypes = new byte[initialCapacity]; 54 returnCodes = new byte[initialCapacity]; 55 latenciesMs = new int[initialCapacity]; 56 } 57 addResult(byte eventType, byte returnCode, int latencyMs)58 boolean addResult(byte eventType, byte returnCode, int latencyMs) { 59 boolean isSuccess = (returnCode == 0); 60 if (eventCount >= SIZE_LIMIT) { 61 // TODO: implement better rate limiting that does not biases metrics. 62 return isSuccess; 63 } 64 if (eventCount == eventTypes.length) { 65 resize((int) (1.4 * eventCount)); 66 } 67 eventTypes[eventCount] = eventType; 68 returnCodes[eventCount] = returnCode; 69 latenciesMs[eventCount] = latencyMs; 70 eventCount++; 71 if (isSuccess) { 72 successCount++; 73 } 74 return isSuccess; 75 } 76 resize(int newLength)77 public void resize(int newLength) { 78 eventTypes = Arrays.copyOf(eventTypes, newLength); 79 returnCodes = Arrays.copyOf(returnCodes, newLength); 80 latenciesMs = Arrays.copyOf(latenciesMs, newLength); 81 } 82 83 @Override toString()84 public String toString() { 85 StringBuilder builder = 86 new StringBuilder("DnsEvent(").append("netId=").append(netId) 87 .append(", transports=") 88 .append(BitSet.valueOf(new long[] { transports })) 89 .append(", "); 90 builder.append(String.format("%d events, ", eventCount)); 91 builder.append(String.format("%d success)", successCount)); 92 return builder.toString(); 93 } 94 } 95