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