1 /* 2 * Copyright 2021 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 com.android.server.appsearch.external.localstorage.stats; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.appsearch.AppSearchResult; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.util.Objects; 27 28 /** 29 * A class for setting basic information to log for all function calls. 30 * 31 * <p>This class can set which stats to log for both batch and non-batch {@link 32 * android.app.appsearch.AppSearchSession} calls. 33 * 34 * <p>Some function calls may have their own detailed stats class like {@link PutDocumentStats}. 35 * However, {@link CallStats} can still be used along with the detailed stats class for easy 36 * aggregation/analysis with other function calls. 37 * 38 * @hide 39 */ 40 public class CallStats { 41 @IntDef( 42 value = { 43 CALL_TYPE_UNKNOWN, 44 CALL_TYPE_INITIALIZE, 45 CALL_TYPE_SET_SCHEMA, 46 CALL_TYPE_PUT_DOCUMENTS, 47 CALL_TYPE_GET_DOCUMENTS, 48 CALL_TYPE_REMOVE_DOCUMENTS_BY_ID, 49 CALL_TYPE_PUT_DOCUMENT, 50 CALL_TYPE_GET_DOCUMENT, 51 CALL_TYPE_REMOVE_DOCUMENT_BY_ID, 52 CALL_TYPE_SEARCH, 53 CALL_TYPE_OPTIMIZE, 54 CALL_TYPE_FLUSH, 55 CALL_TYPE_GLOBAL_SEARCH, 56 CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH, 57 CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH, 58 }) 59 @Retention(RetentionPolicy.SOURCE) 60 public @interface CallType {} 61 62 public static final int CALL_TYPE_UNKNOWN = 0; 63 public static final int CALL_TYPE_INITIALIZE = 1; 64 public static final int CALL_TYPE_SET_SCHEMA = 2; 65 public static final int CALL_TYPE_PUT_DOCUMENTS = 3; 66 public static final int CALL_TYPE_GET_DOCUMENTS = 4; 67 public static final int CALL_TYPE_REMOVE_DOCUMENTS_BY_ID = 5; 68 public static final int CALL_TYPE_PUT_DOCUMENT = 6; 69 public static final int CALL_TYPE_GET_DOCUMENT = 7; 70 public static final int CALL_TYPE_REMOVE_DOCUMENT_BY_ID = 8; 71 public static final int CALL_TYPE_SEARCH = 9; 72 public static final int CALL_TYPE_OPTIMIZE = 10; 73 public static final int CALL_TYPE_FLUSH = 11; 74 public static final int CALL_TYPE_GLOBAL_SEARCH = 12; 75 public static final int CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH = 13; 76 public static final int CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH = 14; 77 78 @Nullable private final String mPackageName; 79 @Nullable private final String mDatabase; 80 /** 81 * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal 82 * state. 83 */ 84 @AppSearchResult.ResultCode private final int mStatusCode; 85 86 private final int mTotalLatencyMillis; 87 88 @CallType private final int mCallType; 89 private final int mEstimatedBinderLatencyMillis; 90 private final int mNumOperationsSucceeded; 91 private final int mNumOperationsFailed; 92 CallStats(@onNull Builder builder)93 CallStats(@NonNull Builder builder) { 94 Objects.requireNonNull(builder); 95 mPackageName = builder.mPackageName; 96 mDatabase = builder.mDatabase; 97 mStatusCode = builder.mStatusCode; 98 mTotalLatencyMillis = builder.mTotalLatencyMillis; 99 mCallType = builder.mCallType; 100 mEstimatedBinderLatencyMillis = builder.mEstimatedBinderLatencyMillis; 101 mNumOperationsSucceeded = builder.mNumOperationsSucceeded; 102 mNumOperationsFailed = builder.mNumOperationsFailed; 103 } 104 105 /** Returns calling package name. */ 106 @Nullable getPackageName()107 public String getPackageName() { 108 return mPackageName; 109 } 110 111 /** Returns calling database name. */ 112 @Nullable getDatabase()113 public String getDatabase() { 114 return mDatabase; 115 } 116 117 /** Returns status code for this api call. */ 118 @AppSearchResult.ResultCode getStatusCode()119 public int getStatusCode() { 120 return mStatusCode; 121 } 122 123 /** Returns total latency of this api call in millis. */ getTotalLatencyMillis()124 public int getTotalLatencyMillis() { 125 return mTotalLatencyMillis; 126 } 127 128 /** Returns type of the call. */ 129 @CallType getCallType()130 public int getCallType() { 131 return mCallType; 132 } 133 134 /** Returns estimated binder latency, in milliseconds */ getEstimatedBinderLatencyMillis()135 public int getEstimatedBinderLatencyMillis() { 136 return mEstimatedBinderLatencyMillis; 137 } 138 139 /** 140 * Returns number of operations succeeded. 141 * 142 * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total 143 * number of individual successful put operations. In this case, how many documents are 144 * successfully indexed. 145 * 146 * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema}, the 147 * sum of {@link CallStats#getNumOperationsSucceeded()} and {@link 148 * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation. 149 */ getNumOperationsSucceeded()150 public int getNumOperationsSucceeded() { 151 return mNumOperationsSucceeded; 152 } 153 154 /** 155 * Returns number of operations failed. 156 * 157 * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total 158 * number of individual failed put operations. In this case, how many documents are failed to be 159 * indexed. 160 * 161 * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema}, the 162 * sum of {@link CallStats#getNumOperationsSucceeded()} and {@link 163 * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation. 164 */ getNumOperationsFailed()165 public int getNumOperationsFailed() { 166 return mNumOperationsFailed; 167 } 168 169 /** Builder for {@link CallStats}. */ 170 public static class Builder { 171 @Nullable String mPackageName; 172 @Nullable String mDatabase; 173 @AppSearchResult.ResultCode int mStatusCode; 174 int mTotalLatencyMillis; 175 @CallType int mCallType; 176 int mEstimatedBinderLatencyMillis; 177 int mNumOperationsSucceeded; 178 int mNumOperationsFailed; 179 180 /** Sets the PackageName used by the session. */ 181 @NonNull setPackageName(@onNull String packageName)182 public Builder setPackageName(@NonNull String packageName) { 183 mPackageName = Objects.requireNonNull(packageName); 184 return this; 185 } 186 187 /** Sets the database used by the session. */ 188 @NonNull setDatabase(@onNull String database)189 public Builder setDatabase(@NonNull String database) { 190 mDatabase = Objects.requireNonNull(database); 191 return this; 192 } 193 194 /** Sets the status code. */ 195 @NonNull setStatusCode(@ppSearchResult.ResultCode int statusCode)196 public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { 197 mStatusCode = statusCode; 198 return this; 199 } 200 201 /** Sets total latency in millis. */ 202 @NonNull setTotalLatencyMillis(int totalLatencyMillis)203 public Builder setTotalLatencyMillis(int totalLatencyMillis) { 204 mTotalLatencyMillis = totalLatencyMillis; 205 return this; 206 } 207 208 /** Sets type of the call. */ 209 @NonNull setCallType(@allType int callType)210 public Builder setCallType(@CallType int callType) { 211 mCallType = callType; 212 return this; 213 } 214 215 /** Sets estimated binder latency, in milliseconds. */ 216 @NonNull setEstimatedBinderLatencyMillis(int estimatedBinderLatencyMillis)217 public Builder setEstimatedBinderLatencyMillis(int estimatedBinderLatencyMillis) { 218 mEstimatedBinderLatencyMillis = estimatedBinderLatencyMillis; 219 return this; 220 } 221 222 /** 223 * Sets number of operations succeeded. 224 * 225 * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total 226 * number of individual successful put operations. In this case, how many documents are 227 * successfully indexed. 228 * 229 * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema}, 230 * the sum of {@link CallStats#getNumOperationsSucceeded()} and {@link 231 * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation. 232 */ 233 @NonNull setNumOperationsSucceeded(int numOperationsSucceeded)234 public Builder setNumOperationsSucceeded(int numOperationsSucceeded) { 235 mNumOperationsSucceeded = numOperationsSucceeded; 236 return this; 237 } 238 239 /** 240 * Sets number of operations failed. 241 * 242 * <p>For example, for {@link android.app.appsearch.AppSearchSession#put}, it is the total 243 * number of individual failed put operations. In this case, how many documents are failed 244 * to be indexed. 245 * 246 * <p>For non-batch calls such as {@link android.app.appsearch.AppSearchSession#setSchema}, 247 * the sum of {@link CallStats#getNumOperationsSucceeded()} and {@link 248 * CallStats#getNumOperationsFailed()} is always 1 since there is only one operation. 249 */ 250 @NonNull setNumOperationsFailed(int numOperationsFailed)251 public Builder setNumOperationsFailed(int numOperationsFailed) { 252 mNumOperationsFailed = numOperationsFailed; 253 return this; 254 } 255 256 /** Creates {@link CallStats} object from {@link Builder} instance. */ 257 @NonNull build()258 public CallStats build() { 259 return new CallStats(/* builder= */ this); 260 } 261 } 262 } 263