Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Unified Diff: third_party/cacheinvalidation/src/java/com/google/ipc/invalidation/ticl/Statistics.java

Issue 1162033004: Pull cacheinvalidations code directory into chromium repo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/cacheinvalidation/src/java/com/google/ipc/invalidation/ticl/Statistics.java
diff --git a/third_party/cacheinvalidation/src/java/com/google/ipc/invalidation/ticl/Statistics.java b/third_party/cacheinvalidation/src/java/com/google/ipc/invalidation/ticl/Statistics.java
new file mode 100644
index 0000000000000000000000000000000000000000..899955ebc1958d869d08b86ea2ea25eabfdfe50e
--- /dev/null
+++ b/third_party/cacheinvalidation/src/java/com/google/ipc/invalidation/ticl/Statistics.java
@@ -0,0 +1,353 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * 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.google.ipc.invalidation.ticl;
+
+import com.google.ipc.invalidation.external.client.SystemResources.Logger;
+import com.google.ipc.invalidation.external.client.types.SimplePair;
+import com.google.ipc.invalidation.ticl.proto.ClientProtocol.PropertyRecord;
+import com.google.ipc.invalidation.ticl.proto.JavaClient.StatisticsState;
+import com.google.ipc.invalidation.util.InternalBase;
+import com.google.ipc.invalidation.util.Marshallable;
+import com.google.ipc.invalidation.util.TextBuilder;
+import com.google.ipc.invalidation.util.TypedUtil;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Statistics for the Ticl, e.g., number of registration calls, number of token mismatches, etc.
+ *
+ */
+public class Statistics extends InternalBase implements Marshallable<StatisticsState> {
+
+ // Implementation: To classify the statistics a bit better, we have a few enums to track different
+ // types of statistics, e.g., sent message types, errors, etc. For each statistic type, we create
+ // a map and provide a method to record an event for each type of statistic.
+
+ /** Types of messages sent to the server: {@code ClientToServerMessage} for their description. */
+ public enum SentMessageType {
+ INFO,
+ INITIALIZE,
+ INVALIDATION_ACK,
+ REGISTRATION,
+ REGISTRATION_SYNC,
+ TOTAL, // Refers to the actual ClientToServerMessage message sent on the network.
+ }
+
+ /**
+ * Types of messages received from the server: {@code ServerToClientMessage} for their
+ * description.
+ */
+ public enum ReceivedMessageType {
+ INFO_REQUEST,
+ INVALIDATION,
+ REGISTRATION_STATUS,
+ REGISTRATION_SYNC_REQUEST,
+ TOKEN_CONTROL,
+ ERROR,
+ CONFIG_CHANGE,
+ STALE_INVALIDATION, // An already acked INVALIDATION.
+ TOTAL, // Refers to the actual ServerToClientMessage messages received from the network.
+ }
+
+ /** Interesting API calls coming from the application ({@code InvalidationClient}). */
+ public enum IncomingOperationType {
+ ACKNOWLEDGE,
+ REGISTRATION,
+ UNREGISTRATION,
+ }
+
+ /** Different types of events issued by the {@code InvalidationListener}). */
+ public enum ListenerEventType {
+ INFORM_ERROR,
+ INFORM_REGISTRATION_FAILURE,
+ INFORM_REGISTRATION_STATUS,
+ INVALIDATE,
+ INVALIDATE_ALL,
+ INVALIDATE_UNKNOWN,
+ REISSUE_REGISTRATIONS,
+ }
+
+ /** Different types of errors observed by the Ticl. */
+ public enum ClientErrorType {
+ /** Acknowledge call received from client with a bad handle. */
+ ACKNOWLEDGE_HANDLE_FAILURE,
+
+ /** Incoming message dropped due to parsing, validation problems. */
+ INCOMING_MESSAGE_FAILURE,
+
+ /** Tried to send an outgoing message that was invalid. */
+ OUTGOING_MESSAGE_FAILURE,
+
+ /** Persistent state failed to deserialize correctly. */
+ PERSISTENT_DESERIALIZATION_FAILURE,
+
+ /** Read of blob from persistent state failed. */
+ PERSISTENT_READ_FAILURE,
+
+ /** Write of blob from persistent state failed. */
+ PERSISTENT_WRITE_FAILURE,
+
+ /** Message received with incompatible protocol version. */
+ PROTOCOL_VERSION_FAILURE,
+
+ /**
+ * Registration at client and server is different, e.g., client thinks it is registered while
+ * the server says it is unregistered (of course, sync will fix it).
+ */
+ REGISTRATION_DISCREPANCY,
+
+ /** The nonce from the server did not match the current nonce by the client. */
+ NONCE_MISMATCH,
+
+ /** The current token at the client is different from the token in the incoming message. */
+ TOKEN_MISMATCH,
+
+ /** No message sent due to token missing. */
+ TOKEN_MISSING_FAILURE,
+
+ /** Received a message with a token (transient) failure. */
+ TOKEN_TRANSIENT_FAILURE,
+ }
+
+ // Names of statistics types. Do not rely on reflection to determine type names because Proguard
+ // may change them for Android clients.
+ private static final String SENT_MESSAGE_TYPE_NAME = "SentMessageType";
+ private static final String INCOMING_OPERATION_TYPE_NAME = "IncomingOperationType";
+ private static final String RECEIVED_MESSAGE_TYPE_NAME = "ReceivedMessageType";
+ private static final String LISTENER_EVENT_TYPE_NAME = "ListenerEventType";
+ private static final String CLIENT_ERROR_TYPE_NAME = "ClientErrorType";
+
+ // Map from stats enum names to values. Used in place of Enum.valueOf() because this method
+ // invokes Enum.values() via reflection, and that method may be renamed by Proguard.
+ private static final Map<String, SentMessageType> SENT_MESSAGE_TYPE_NAME_TO_VALUE_MAP =
+ createValueOfMap(SentMessageType.values());
+ private static final Map<String, IncomingOperationType>
+ INCOMING_OPERATION_TYPE_NAME_TO_VALUE_MAP = createValueOfMap(IncomingOperationType.values());
+ private static final Map<String, ReceivedMessageType> RECEIVED_MESSAGE_TYPE_NAME_TO_VALUE_MAP =
+ createValueOfMap(ReceivedMessageType.values());
+ private static final Map<String, ListenerEventType> LISTENER_EVENT_TYPE_NAME_TO_VALUE_MAP =
+ createValueOfMap(ListenerEventType.values());
+ private static final Map<String, ClientErrorType> CLIENT_ERROR_TYPE_NAME_TO_VALUE_MAP =
+ createValueOfMap(ClientErrorType.values());
+
+ // Maps for each type of Statistic to keep track of how many times each event has occurred.
+
+ private final Map<SentMessageType, Integer> sentMessageTypes =
+ new HashMap<SentMessageType, Integer>();
+ private final Map<ReceivedMessageType, Integer> receivedMessageTypes =
+ new HashMap<ReceivedMessageType, Integer>();
+ private final Map<IncomingOperationType, Integer> incomingOperationTypes =
+ new HashMap<IncomingOperationType, Integer>();
+ private final Map<ListenerEventType, Integer> listenerEventTypes =
+ new HashMap<ListenerEventType, Integer>();
+ private final Map<ClientErrorType, Integer> clientErrorTypes =
+ new HashMap<ClientErrorType, Integer>();
+
+ public Statistics() {
+ initializeMap(sentMessageTypes, SentMessageType.values());
+ initializeMap(receivedMessageTypes, ReceivedMessageType.values());
+ initializeMap(incomingOperationTypes, IncomingOperationType.values());
+ initializeMap(listenerEventTypes, ListenerEventType.values());
+ initializeMap(clientErrorTypes, ClientErrorType.values());
+ }
+
+ /** Returns a copy of this. */
+ public Statistics getCopyForTest() {
+ Statistics statistics = new Statistics();
+ statistics.sentMessageTypes.putAll(sentMessageTypes);
+ statistics.receivedMessageTypes.putAll(receivedMessageTypes);
+ statistics.incomingOperationTypes.putAll(incomingOperationTypes);
+ statistics.listenerEventTypes.putAll(listenerEventTypes);
+ statistics.clientErrorTypes.putAll(clientErrorTypes);
+ return statistics;
+ }
+
+ /** Returns the counter value for {@code clientErrorType}. */
+ int getClientErrorCounterForTest(ClientErrorType clientErrorType) {
+ return TypedUtil.mapGet(clientErrorTypes, clientErrorType);
+ }
+
+ /** Returns the counter value for {@code sentMessageType}. */
+ int getSentMessageCounterForTest(SentMessageType sentMessageType) {
+ return TypedUtil.mapGet(sentMessageTypes, sentMessageType);
+ }
+
+ /** Returns the counter value for {@code receivedMessageType}. */
+ int getReceivedMessageCounterForTest(ReceivedMessageType receivedMessageType) {
+ return TypedUtil.mapGet(receivedMessageTypes, receivedMessageType);
+ }
+
+ /** Records the fact that a message of type {@code sentMessageType} has been sent. */
+ public void recordSentMessage(SentMessageType sentMessageType) {
+ incrementValue(sentMessageTypes, sentMessageType);
+ }
+
+ /** Records the fact that a message of type {@code receivedMessageType} has been received. */
+ public void recordReceivedMessage(ReceivedMessageType receivedMessageType) {
+ incrementValue(receivedMessageTypes, receivedMessageType);
+ }
+
+ /**
+ * Records the fact that the application has made a call of type
+ * {@code incomingOperationType}.
+ */
+ public void recordIncomingOperation(IncomingOperationType incomingOperationType) {
+ incrementValue(incomingOperationTypes, incomingOperationType);
+ }
+
+ /** Records the fact that the listener has issued an event of type {@code listenerEventType}. */
+ public void recordListenerEvent(ListenerEventType listenerEventType) {
+ incrementValue(listenerEventTypes, listenerEventType);
+ }
+
+ /** Records the fact that the client has observed an error of type {@code clientErrorType}. */
+ public void recordError(ClientErrorType clientErrorType) {
+ incrementValue(clientErrorTypes, clientErrorType);
+ }
+
+ /**
+ * Modifies {@code performanceCounters} to contain all the statistics that are non-zero. Each pair
+ * has the name of the statistic event and the number of times that event has occurred since the
+ * client started.
+ */
+ public void getNonZeroStatistics(List<SimplePair<String, Integer>> performanceCounters) {
+ // Add the non-zero values from the different maps to performanceCounters.
+ fillWithNonZeroStatistics(sentMessageTypes, performanceCounters, SENT_MESSAGE_TYPE_NAME);
+ fillWithNonZeroStatistics(receivedMessageTypes, performanceCounters,
+ RECEIVED_MESSAGE_TYPE_NAME);
+ fillWithNonZeroStatistics(incomingOperationTypes, performanceCounters,
+ INCOMING_OPERATION_TYPE_NAME);
+ fillWithNonZeroStatistics(listenerEventTypes, performanceCounters, LISTENER_EVENT_TYPE_NAME);
+ fillWithNonZeroStatistics(clientErrorTypes, performanceCounters, CLIENT_ERROR_TYPE_NAME);
+ }
+
+ /** Modifies {@code result} to contain those statistics from {@code map} whose value is > 0. */
+ private static <Key extends Enum<Key>> void fillWithNonZeroStatistics(Map<Key, Integer> map,
+ List<SimplePair<String, Integer>> destination, String typeName) {
+ String prefix = typeName + ".";
+ for (Map.Entry<Key, Integer> entry : map.entrySet()) {
+ if (entry.getValue() > 0) {
+ destination.add(SimplePair.of(prefix + entry.getKey().name(), entry.getValue()));
+ }
+ }
+ }
+
+ /** Initializes a map from enum names to values of the given {@code keys}. */
+ private static <Key extends Enum<Key>> Map<String, Key> createValueOfMap(Key[] keys) {
+ HashMap<String, Key> map = new HashMap<String, Key>();
+ for (Key key : keys) {
+ map.put(key.name(), key);
+ }
+ return map;
+ }
+
+ /** Increments the value of {@code map}[{@code key}] by 1. */
+ private static <Key> void incrementValue(Map<Key, Integer> map, Key key) {
+ map.put(key, TypedUtil.mapGet(map, key) + 1);
+ }
+
+ /** Initializes all values for {@code keys} in {@code map} to be 0. */
+ private static <Key> void initializeMap(Map<Key, Integer> map, Key[] keys) {
+ for (Key key : keys) {
+ map.put(key, 0);
+ }
+ }
+
+ @Override
+ public void toCompactString(TextBuilder builder) {
+ List<SimplePair<String, Integer>> nonZeroValues = new ArrayList<SimplePair<String, Integer>>();
+ getNonZeroStatistics(nonZeroValues);
+ builder.appendFormat("Client Statistics: %s\n", nonZeroValues);
+ }
+
+ @Override
+ public StatisticsState marshal() {
+ // Get all the non-zero counters, convert them to proto PropertyRecord messages, and return
+ // a StatisticsState containing the records.
+ List<SimplePair<String, Integer>> counters = new ArrayList<SimplePair<String, Integer>>();
+ getNonZeroStatistics(counters);
+ List<PropertyRecord> propertyRecords = new ArrayList<PropertyRecord>(counters.size());
+ for (SimplePair<String, Integer> counter : counters) {
+ propertyRecords.add(PropertyRecord.create(counter.getFirst(), counter.getSecond()));
+ }
+ return StatisticsState.create(propertyRecords);
+ }
+
+ /**
+ * Given the serialized {@code performanceCounters} of the client statistics, returns a Statistics
+ * object with the performance counter values from {@code performanceCounters}.
+ */
+
+ public static Statistics deserializeStatistics(Logger logger,
+ Collection<PropertyRecord> performanceCounters) {
+ Statistics statistics = new Statistics();
+
+ // For each counter, parse out the counter name and value.
+ for (PropertyRecord performanceCounter : performanceCounters) {
+ String counterName = performanceCounter.getName();
+ String[] parts = counterName.split("\\.");
+ if (parts.length != 2) {
+ logger.warning("Perf counter name must of form: class.value, skipping: %s", counterName);
+ continue;
+ }
+ String className = parts[0];
+ String fieldName = parts[1];
+ int counterValue = performanceCounter.getValue();
+
+ // Call the relevant method in a loop (i.e., depending on the type of the class).
+ if (TypedUtil.<String>equals(className, SENT_MESSAGE_TYPE_NAME)) {
+ incrementPerformanceCounterValue(logger, SENT_MESSAGE_TYPE_NAME_TO_VALUE_MAP,
+ statistics.sentMessageTypes, fieldName, counterValue);
+ } else if (TypedUtil.<String>equals(className, INCOMING_OPERATION_TYPE_NAME)) {
+ incrementPerformanceCounterValue(logger, INCOMING_OPERATION_TYPE_NAME_TO_VALUE_MAP,
+ statistics.incomingOperationTypes, fieldName, counterValue);
+ } else if (TypedUtil.<String>equals(className, RECEIVED_MESSAGE_TYPE_NAME)) {
+ incrementPerformanceCounterValue(logger, RECEIVED_MESSAGE_TYPE_NAME_TO_VALUE_MAP,
+ statistics.receivedMessageTypes, fieldName, counterValue);
+ } else if (TypedUtil.<String>equals(className, LISTENER_EVENT_TYPE_NAME)) {
+ incrementPerformanceCounterValue(logger, LISTENER_EVENT_TYPE_NAME_TO_VALUE_MAP,
+ statistics.listenerEventTypes, fieldName, counterValue);
+ } else if (TypedUtil.<String>equals(className, CLIENT_ERROR_TYPE_NAME)) {
+ incrementPerformanceCounterValue(logger, CLIENT_ERROR_TYPE_NAME_TO_VALUE_MAP,
+ statistics.clientErrorTypes, fieldName, counterValue);
+ } else {
+ logger.warning("Skipping unknown enum class name %s", className);
+ }
+ }
+ return statistics;
+ }
+
+ /**
+ * Looks for an enum value with the given {@code fieldName} in {@code valueOfMap} and increments
+ * the corresponding entry in {@code counts} by {@code counterValue}. Call to update statistics
+ * for a single performance counter.
+ */
+ private static <Key extends Enum<Key>> void incrementPerformanceCounterValue(Logger logger,
+ Map<String, Key> valueOfMap, Map<Key, Integer> counts, String fieldName, int counterValue) {
+ Key type = TypedUtil.mapGet(valueOfMap, fieldName);
+ if (type != null) {
+ int currentValue = TypedUtil.mapGet(counts, type);
+ counts.put(type, currentValue + counterValue);
+ } else {
+ logger.warning("Skipping unknown enum value name %s", fieldName);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698