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 androidx.appsearch.localstorage.stats; 18 19 import androidx.annotation.IntDef; 20 import androidx.annotation.RestrictTo; 21 import androidx.appsearch.annotation.CanIgnoreReturnValue; 22 import androidx.appsearch.app.AppSearchResult; 23 import androidx.appsearch.stats.BaseStats; 24 25 import org.jspecify.annotations.NonNull; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * Class holds detailed stats for initialization 32 * 33 * @exportToFramework:hide 34 */ 35 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 36 public final class InitializeStats extends BaseStats { 37 /** 38 * The cause of IcingSearchEngine recovering from a previous bad state during initialization. 39 */ 40 @IntDef(value = { 41 // It needs to be sync with RecoveryCause in 42 // external/icing/proto/icing/proto/logging.proto#InitializeStatsProto 43 RECOVERY_CAUSE_NONE, 44 RECOVERY_CAUSE_DATA_LOSS, 45 RECOVERY_CAUSE_INCONSISTENT_WITH_GROUND_TRUTH, 46 RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH, 47 RECOVERY_CAUSE_IO_ERROR, 48 }) 49 @Retention(RetentionPolicy.SOURCE) 50 public @interface RecoveryCause { 51 } 52 53 // No recovery happened. 54 public static final int RECOVERY_CAUSE_NONE = 0; 55 // Data loss in ground truth. 56 public static final int RECOVERY_CAUSE_DATA_LOSS = 1; 57 // Data in index is inconsistent with ground truth. 58 public static final int RECOVERY_CAUSE_INCONSISTENT_WITH_GROUND_TRUTH = 2; 59 // Total checksum of all the components does not match. 60 public static final int RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH = 3; 61 // Random I/O errors. 62 public static final int RECOVERY_CAUSE_IO_ERROR = 4; 63 64 /** 65 * Status regarding how much data is lost during the initialization. 66 */ 67 @IntDef(value = { 68 // It needs to be sync with DocumentStoreDataStatus in 69 // external/icing/proto/icing/proto/logging.proto#InitializeStatsProto 70 71 DOCUMENT_STORE_DATA_STATUS_NO_DATA_LOSS, 72 DOCUMENT_STORE_DATA_STATUS_PARTIAL_LOSS, 73 DOCUMENT_STORE_DATA_STATUS_COMPLETE_LOSS, 74 }) 75 @Retention(RetentionPolicy.SOURCE) 76 public @interface DocumentStoreDataStatus { 77 } 78 79 // Document store is successfully initialized or fully recovered. 80 public static final int DOCUMENT_STORE_DATA_STATUS_NO_DATA_LOSS = 0; 81 // Ground truth data is partially lost. 82 public static final int DOCUMENT_STORE_DATA_STATUS_PARTIAL_LOSS = 1; 83 // Ground truth data is completely lost. 84 public static final int DOCUMENT_STORE_DATA_STATUS_COMPLETE_LOSS = 2; 85 86 @AppSearchResult.ResultCode 87 private final int mStatusCode; 88 private final int mTotalLatencyMillis; 89 /** Whether the initialize() detects deSync. */ 90 private final boolean mHasDeSync; 91 /** Time used to read and process the schema and namespaces. */ 92 private final int mPrepareSchemaAndNamespacesLatencyMillis; 93 /** Time used to read and process the visibility store. */ 94 private final int mPrepareVisibilityStoreLatencyMillis; 95 /** Overall time used for the native function call. */ 96 private final int mNativeLatencyMillis; 97 @RecoveryCause 98 private final int mNativeDocumentStoreRecoveryCause; 99 @RecoveryCause 100 private final int mNativeIndexRestorationCause; 101 @RecoveryCause 102 private final int mNativeSchemaStoreRecoveryCause; 103 /** Time used to recover the document store. */ 104 private final int mNativeDocumentStoreRecoveryLatencyMillis; 105 /** Time used to restore the index. */ 106 private final int mNativeIndexRestorationLatencyMillis; 107 /** Time used to recover the schema store. */ 108 private final int mNativeSchemaStoreRecoveryLatencyMillis; 109 /** Status regarding how much data is lost during the initialization. */ 110 private final int mNativeDocumentStoreDataStatus; 111 /** 112 * Returns number of documents currently in document store. Those may include alive, deleted, 113 * and expired documents. 114 */ 115 private final int mNativeNumDocuments; 116 /** Returns number of schema types currently in the schema store. */ 117 private final int mNativeNumSchemaTypes; 118 /** Whether we had to reset the index, losing all data, during initialization. */ 119 private final boolean mHasReset; 120 /** If we had to reset, contains the status code of the reset operation. */ 121 @AppSearchResult.ResultCode 122 private final int mResetStatusCode; 123 124 /** Returns the status of the initialization. */ 125 @AppSearchResult.ResultCode getStatusCode()126 public int getStatusCode() { 127 return mStatusCode; 128 } 129 130 /** Returns the total latency in milliseconds for the initialization. */ getTotalLatencyMillis()131 public int getTotalLatencyMillis() { 132 return mTotalLatencyMillis; 133 } 134 135 /** 136 * Returns whether the initialize() detects deSync. 137 * 138 * <p>If there is a deSync, it means AppSearch and IcingSearchEngine have an inconsistent view 139 * of what data should exist. 140 */ hasDeSync()141 public boolean hasDeSync() { 142 return mHasDeSync; 143 } 144 145 /** Returns time used to read and process the schema and namespaces. */ getPrepareSchemaAndNamespacesLatencyMillis()146 public int getPrepareSchemaAndNamespacesLatencyMillis() { 147 return mPrepareSchemaAndNamespacesLatencyMillis; 148 } 149 150 /** Returns time used to read and process the visibility file. */ getPrepareVisibilityStoreLatencyMillis()151 public int getPrepareVisibilityStoreLatencyMillis() { 152 return mPrepareVisibilityStoreLatencyMillis; 153 } 154 155 /** Returns overall time used for the native function call. */ getNativeLatencyMillis()156 public int getNativeLatencyMillis() { 157 return mNativeLatencyMillis; 158 } 159 160 /** Returns recovery cause for document store. 161 * 162 * <p> Possible recovery causes for document store: 163 * <li> {@link InitializeStats#RECOVERY_CAUSE_DATA_LOSS} 164 * <li> {@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH} 165 * <li> {@link InitializeStats#RECOVERY_CAUSE_IO_ERROR} 166 */ 167 @RecoveryCause getDocumentStoreRecoveryCause()168 public int getDocumentStoreRecoveryCause() { 169 return mNativeDocumentStoreRecoveryCause; 170 } 171 172 /** Returns restoration cause for index store. 173 * 174 * <p> Possible causes: 175 * <li> {@link InitializeStats#RECOVERY_CAUSE_INCONSISTENT_WITH_GROUND_TRUTH} 176 * <li> {@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH} 177 * <li> {@link InitializeStats#RECOVERY_CAUSE_IO_ERROR} 178 */ 179 @RecoveryCause getIndexRestorationCause()180 public int getIndexRestorationCause() { 181 return mNativeIndexRestorationCause; 182 } 183 184 /** Returns recovery cause for schema store. 185 * 186 * <p> Possible causes: 187 * <li> IO_ERROR 188 */ 189 @RecoveryCause getSchemaStoreRecoveryCause()190 public int getSchemaStoreRecoveryCause() { 191 return mNativeSchemaStoreRecoveryCause; 192 } 193 194 /** Returns time used to recover the document store. */ getDocumentStoreRecoveryLatencyMillis()195 public int getDocumentStoreRecoveryLatencyMillis() { 196 return mNativeDocumentStoreRecoveryLatencyMillis; 197 } 198 199 /** Returns time used to restore the index. */ getIndexRestorationLatencyMillis()200 public int getIndexRestorationLatencyMillis() { 201 return mNativeIndexRestorationLatencyMillis; 202 } 203 204 /** Returns time used to recover the schema store. */ getSchemaStoreRecoveryLatencyMillis()205 public int getSchemaStoreRecoveryLatencyMillis() { 206 return mNativeSchemaStoreRecoveryLatencyMillis; 207 } 208 209 /** Returns status about how much data is lost during the initialization. */ 210 @DocumentStoreDataStatus getDocumentStoreDataStatus()211 public int getDocumentStoreDataStatus() { 212 return mNativeDocumentStoreDataStatus; 213 } 214 215 /** 216 * Returns number of documents currently in document store. Those may include alive, deleted, 217 * and expired documents. 218 */ getDocumentCount()219 public int getDocumentCount() { 220 return mNativeNumDocuments; 221 } 222 223 /** Returns number of schema types currently in the schema store. */ getSchemaTypeCount()224 public int getSchemaTypeCount() { 225 return mNativeNumSchemaTypes; 226 } 227 228 /** Returns whether we had to reset the index, losing all data, as part of initialization. */ hasReset()229 public boolean hasReset() { 230 return mHasReset; 231 } 232 233 /** 234 * Returns the status of the reset, if one was performed according to {@link #hasReset}. 235 * 236 * <p>If no value has been set, the default value is {@link AppSearchResult#RESULT_OK}. 237 */ 238 @AppSearchResult.ResultCode getResetStatusCode()239 public int getResetStatusCode() { 240 return mResetStatusCode; 241 } 242 InitializeStats(@onNull Builder builder)243 InitializeStats(@NonNull Builder builder) { 244 super(builder); 245 mStatusCode = builder.mStatusCode; 246 mTotalLatencyMillis = builder.mTotalLatencyMillis; 247 mHasDeSync = builder.mHasDeSync; 248 mPrepareSchemaAndNamespacesLatencyMillis = builder.mPrepareSchemaAndNamespacesLatencyMillis; 249 mPrepareVisibilityStoreLatencyMillis = builder.mPrepareVisibilityStoreLatencyMillis; 250 mNativeLatencyMillis = builder.mNativeLatencyMillis; 251 mNativeDocumentStoreRecoveryCause = builder.mNativeDocumentStoreRecoveryCause; 252 mNativeIndexRestorationCause = builder.mNativeIndexRestorationCause; 253 mNativeSchemaStoreRecoveryCause = builder.mNativeSchemaStoreRecoveryCause; 254 mNativeDocumentStoreRecoveryLatencyMillis = 255 builder.mNativeDocumentStoreRecoveryLatencyMillis; 256 mNativeIndexRestorationLatencyMillis = builder.mNativeIndexRestorationLatencyMillis; 257 mNativeSchemaStoreRecoveryLatencyMillis = builder.mNativeSchemaStoreRecoveryLatencyMillis; 258 mNativeDocumentStoreDataStatus = builder.mNativeDocumentStoreDataStatus; 259 mNativeNumDocuments = builder.mNativeNumDocuments; 260 mNativeNumSchemaTypes = builder.mNativeNumSchemaTypes; 261 mHasReset = builder.mHasReset; 262 mResetStatusCode = builder.mResetStatusCode; 263 } 264 265 /** Builder for {@link InitializeStats}. */ 266 public static class Builder extends BaseStats.Builder<InitializeStats.Builder> { 267 @AppSearchResult.ResultCode 268 int mStatusCode; 269 270 int mTotalLatencyMillis; 271 boolean mHasDeSync; 272 int mPrepareSchemaAndNamespacesLatencyMillis; 273 int mPrepareVisibilityStoreLatencyMillis; 274 int mNativeLatencyMillis; 275 @RecoveryCause 276 int mNativeDocumentStoreRecoveryCause; 277 @RecoveryCause 278 int mNativeIndexRestorationCause; 279 @RecoveryCause 280 int mNativeSchemaStoreRecoveryCause; 281 int mNativeDocumentStoreRecoveryLatencyMillis; 282 int mNativeIndexRestorationLatencyMillis; 283 int mNativeSchemaStoreRecoveryLatencyMillis; 284 @DocumentStoreDataStatus 285 int mNativeDocumentStoreDataStatus; 286 int mNativeNumDocuments; 287 int mNativeNumSchemaTypes; 288 boolean mHasReset; 289 @AppSearchResult.ResultCode 290 int mResetStatusCode; 291 292 /** Sets the status of the initialization. */ 293 @CanIgnoreReturnValue setStatusCode(@ppSearchResult.ResultCode int statusCode)294 public @NonNull Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { 295 mStatusCode = statusCode; 296 return this; 297 } 298 299 /** Sets the total latency of the initialization in milliseconds. */ 300 @CanIgnoreReturnValue setTotalLatencyMillis(int totalLatencyMillis)301 public @NonNull Builder setTotalLatencyMillis(int totalLatencyMillis) { 302 mTotalLatencyMillis = totalLatencyMillis; 303 return this; 304 } 305 306 /** 307 * Sets whether the initialize() detects deSync. 308 * 309 * <p>If there is a deSync, it means AppSearch and IcingSearchEngine have an inconsistent 310 * view of what data should exist. 311 */ 312 @CanIgnoreReturnValue setHasDeSync(boolean hasDeSync)313 public @NonNull Builder setHasDeSync(boolean hasDeSync) { 314 mHasDeSync = hasDeSync; 315 return this; 316 } 317 318 /** Sets time used to read and process the schema and namespaces. */ 319 @CanIgnoreReturnValue setPrepareSchemaAndNamespacesLatencyMillis( int prepareSchemaAndNamespacesLatencyMillis)320 public @NonNull Builder setPrepareSchemaAndNamespacesLatencyMillis( 321 int prepareSchemaAndNamespacesLatencyMillis) { 322 mPrepareSchemaAndNamespacesLatencyMillis = prepareSchemaAndNamespacesLatencyMillis; 323 return this; 324 } 325 326 /** Sets time used to read and process the visibility file. */ 327 @CanIgnoreReturnValue setPrepareVisibilityStoreLatencyMillis( int prepareVisibilityStoreLatencyMillis)328 public @NonNull Builder setPrepareVisibilityStoreLatencyMillis( 329 int prepareVisibilityStoreLatencyMillis) { 330 mPrepareVisibilityStoreLatencyMillis = prepareVisibilityStoreLatencyMillis; 331 return this; 332 } 333 334 /** Sets overall time used for the native function call. */ 335 @CanIgnoreReturnValue setNativeLatencyMillis(int nativeLatencyMillis)336 public @NonNull Builder setNativeLatencyMillis(int nativeLatencyMillis) { 337 mNativeLatencyMillis = nativeLatencyMillis; 338 return this; 339 } 340 341 /** 342 * Sets recovery cause for document store. 343 * 344 * <p> Possible recovery causes for document store: 345 * <li> {@link InitializeStats#RECOVERY_CAUSE_DATA_LOSS} 346 * <li> {@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH} 347 * <li> {@link InitializeStats#RECOVERY_CAUSE_IO_ERROR} 348 */ 349 @CanIgnoreReturnValue setDocumentStoreRecoveryCause( @ecoveryCause int documentStoreRecoveryCause)350 public @NonNull Builder setDocumentStoreRecoveryCause( 351 @RecoveryCause int documentStoreRecoveryCause) { 352 mNativeDocumentStoreRecoveryCause = documentStoreRecoveryCause; 353 return this; 354 } 355 356 /** Sets restoration cause for index store. 357 * 358 * <p> Possible causes: 359 * <li> {@link InitializeStats#DOCUMENT_STORE_DATA_STATUS_COMPLETE_LOSS} 360 * <li> {@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH} 361 * <li> {@link InitializeStats#RECOVERY_CAUSE_IO_ERROR} 362 */ 363 @CanIgnoreReturnValue setIndexRestorationCause( @ecoveryCause int indexRestorationCause)364 public @NonNull Builder setIndexRestorationCause( 365 @RecoveryCause int indexRestorationCause) { 366 mNativeIndexRestorationCause = indexRestorationCause; 367 return this; 368 } 369 370 /** Returns recovery cause for schema store. 371 * 372 * <p> Possible causes: 373 * <li> {@link InitializeStats#RECOVERY_CAUSE_IO_ERROR} 374 */ 375 @CanIgnoreReturnValue setSchemaStoreRecoveryCause( @ecoveryCause int schemaStoreRecoveryCause)376 public @NonNull Builder setSchemaStoreRecoveryCause( 377 @RecoveryCause int schemaStoreRecoveryCause) { 378 mNativeSchemaStoreRecoveryCause = schemaStoreRecoveryCause; 379 return this; 380 } 381 382 /** Sets time used to recover the document store. */ 383 @CanIgnoreReturnValue setDocumentStoreRecoveryLatencyMillis( int documentStoreRecoveryLatencyMillis)384 public @NonNull Builder setDocumentStoreRecoveryLatencyMillis( 385 int documentStoreRecoveryLatencyMillis) { 386 mNativeDocumentStoreRecoveryLatencyMillis = documentStoreRecoveryLatencyMillis; 387 return this; 388 } 389 390 /** Sets time used to restore the index. */ 391 @CanIgnoreReturnValue setIndexRestorationLatencyMillis( int indexRestorationLatencyMillis)392 public @NonNull Builder setIndexRestorationLatencyMillis( 393 int indexRestorationLatencyMillis) { 394 mNativeIndexRestorationLatencyMillis = indexRestorationLatencyMillis; 395 return this; 396 } 397 398 /** Sets time used to recover the schema store. */ 399 @CanIgnoreReturnValue setSchemaStoreRecoveryLatencyMillis( int schemaStoreRecoveryLatencyMillis)400 public @NonNull Builder setSchemaStoreRecoveryLatencyMillis( 401 int schemaStoreRecoveryLatencyMillis) { 402 mNativeSchemaStoreRecoveryLatencyMillis = schemaStoreRecoveryLatencyMillis; 403 return this; 404 } 405 406 /** 407 * Sets Native Document Store Data status. 408 * status is defined in external/icing/proto/icing/proto/logging.proto 409 */ 410 @CanIgnoreReturnValue setDocumentStoreDataStatus( @ocumentStoreDataStatus int documentStoreDataStatus)411 public @NonNull Builder setDocumentStoreDataStatus( 412 @DocumentStoreDataStatus int documentStoreDataStatus) { 413 mNativeDocumentStoreDataStatus = documentStoreDataStatus; 414 return this; 415 } 416 417 /** 418 * Sets number of documents currently in document store. Those may include alive, deleted, 419 * and expired documents. 420 */ 421 @CanIgnoreReturnValue setDocumentCount(int numDocuments)422 public @NonNull Builder setDocumentCount(int numDocuments) { 423 mNativeNumDocuments = numDocuments; 424 return this; 425 } 426 427 /** Sets number of schema types currently in the schema store. */ 428 @CanIgnoreReturnValue setSchemaTypeCount(int numSchemaTypes)429 public @NonNull Builder setSchemaTypeCount(int numSchemaTypes) { 430 mNativeNumSchemaTypes = numSchemaTypes; 431 return this; 432 } 433 434 /** Sets whether we had to reset the index, losing all data, as part of initialization. */ 435 @CanIgnoreReturnValue setHasReset(boolean hasReset)436 public @NonNull Builder setHasReset(boolean hasReset) { 437 mHasReset = hasReset; 438 return this; 439 } 440 441 /** Sets the status of the reset, if one was performed according to {@link #setHasReset}. */ 442 @CanIgnoreReturnValue setResetStatusCode( @ppSearchResult.ResultCode int resetStatusCode)443 public @NonNull Builder setResetStatusCode( 444 @AppSearchResult.ResultCode int resetStatusCode) { 445 mResetStatusCode = resetStatusCode; 446 return this; 447 } 448 449 /** 450 * Constructs a new {@link InitializeStats} from the contents of this 451 * {@link InitializeStats.Builder} 452 */ 453 @Override build()454 public @NonNull InitializeStats build() { 455 return new InitializeStats(/* builder= */ this); 456 } 457 } 458 } 459