Merge "Log stats for Optimize" into sc-dev

This commit is contained in:
Xiaoyu Jin 2021-07-22 19:16:15 +00:00 committed by Android (Google) Code Review
commit f5bfc7527c
12 changed files with 638 additions and 28 deletions

View File

@ -81,6 +81,14 @@ public final class AppSearchConfig implements AutoCloseable {
"sampling_interval_for_batch_call_stats";
public static final String KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS =
"sampling_interval_for_put_document_stats";
public static final String KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS =
"sampling_interval_for_initialize_stats";
public static final String KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS =
"sampling_interval_for_search_stats";
public static final String KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS =
"sampling_interval_for_global_search_stats";
public static final String KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS =
"sampling_interval_for_optimize_stats";
public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES =
"limit_config_max_document_size_bytes";
public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT =
@ -95,6 +103,10 @@ public final class AppSearchConfig implements AutoCloseable {
KEY_SAMPLING_INTERVAL_DEFAULT,
KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS,
KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES,
KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT,
KEY_BYTES_OPTIMIZE_THRESHOLD,
@ -245,6 +257,58 @@ public final class AppSearchConfig implements AutoCloseable {
}
}
/**
* Returns cached value for sampling interval for initialize.
*
* <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
*/
public int getCachedSamplingIntervalForInitializeStats() {
synchronized (mLock) {
throwIfClosedLocked();
return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
getCachedSamplingIntervalDefault());
}
}
/**
* Returns cached value for sampling interval for search.
*
* <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
*/
public int getCachedSamplingIntervalForSearchStats() {
synchronized (mLock) {
throwIfClosedLocked();
return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
getCachedSamplingIntervalDefault());
}
}
/**
* Returns cached value for sampling interval for globalSearch.
*
* <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
*/
public int getCachedSamplingIntervalForGlobalSearchStats() {
synchronized (mLock) {
throwIfClosedLocked();
return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
getCachedSamplingIntervalDefault());
}
}
/**
* Returns cached value for sampling interval for optimize.
*
* <p>For example, sampling_interval=10 means that one out of every 10 stats was logged.
*/
public int getCachedSamplingIntervalForOptimizeStats() {
synchronized (mLock) {
throwIfClosedLocked();
return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
getCachedSamplingIntervalDefault());
}
}
/** Returns the maximum serialized size an indexed document can be, in bytes. */
public int getCachedLimitConfigMaxDocumentSizeBytes() {
synchronized (mLock) {
@ -343,6 +407,10 @@ public final class AppSearchConfig implements AutoCloseable {
case KEY_SAMPLING_INTERVAL_DEFAULT:
case KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS:
case KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS:
case KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS:
case KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS:
case KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS:
case KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS:
synchronized (mLock) {
mBundleLocked.putInt(key, properties.getInt(key, DEFAULT_SAMPLING_INTERVAL));
}

View File

@ -59,6 +59,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemService;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
import com.android.server.appsearch.stats.StatsCollector;
import com.android.server.appsearch.util.PackageUtil;
@ -1479,20 +1480,42 @@ public class AppSearchManagerService extends SystemService {
private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
EXECUTOR.execute(() -> {
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
OptimizeStats.Builder builder = new OptimizeStats.Builder();
try {
instance.getAppSearchImpl().checkForOptimize(mutateBatchSize);
instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
} catch (AppSearchException e) {
Log.w(TAG, "Error occurred when check for optimize", e);
} finally {
OptimizeStats oStats = builder
.setTotalLatencyMillis(
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
.build();
if (oStats.getOriginalDocumentCount() > 0) {
// see if optimize has been run by checking originalDocumentCount
instance.getLogger().logStats(oStats);
}
}
});
}
private void checkForOptimize(AppSearchUserInstance instance) {
EXECUTOR.execute(() -> {
long totalLatencyStartMillis = SystemClock.elapsedRealtime();
OptimizeStats.Builder builder = new OptimizeStats.Builder();
try {
instance.getAppSearchImpl().checkForOptimize();
instance.getAppSearchImpl().checkForOptimize(builder);
} catch (AppSearchException e) {
Log.w(TAG, "Error occurred when check for optimize", e);
} finally {
OptimizeStats oStats = builder
.setTotalLatencyMillis(
(int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
.build();
if (oStats.getOriginalDocumentCount() > 0) {
// see if optimize has been run by checking originalDocumentCount
instance.getLogger().logStats(oStats);
}
}
});
}

View File

@ -55,6 +55,7 @@ import com.android.server.appsearch.external.localstorage.converter.SearchSpecTo
import com.android.server.appsearch.external.localstorage.converter.SetSchemaResponseToProtoConverter;
import com.android.server.appsearch.external.localstorage.converter.TypePropertyPathToProtoConverter;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@ -284,6 +285,9 @@ public final class AppSearchImpl implements Closeable {
// Log the time it took to read the data that goes into the cache maps
if (initStatsBuilder != null) {
// In case there is some error for getAllNamespaces, we can still
// set the latency for preparation.
// If there is no error, the value will be overridden by the actual one later.
initStatsBuilder
.setStatusCode(
statusProtoToResultCode(
@ -1326,8 +1330,7 @@ public final class AppSearchImpl implements Closeable {
deleteResultProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND);
// Update derived maps
int numDocumentsDeleted =
deleteResultProto.getDeleteStats().getNumDocumentsDeleted();
int numDocumentsDeleted = deleteResultProto.getDeleteStats().getNumDocumentsDeleted();
updateDocumentCountAfterRemovalLocked(packageName, numDocumentsDeleted);
} finally {
mReadWriteLock.writeLock().unlock();
@ -2162,12 +2165,13 @@ public final class AppSearchImpl implements Closeable {
* #CHECK_OPTIMIZE_INTERVAL}, {@link IcingSearchEngine#getOptimizeInfo()} will be triggered
* and the counter will be reset.
*/
public void checkForOptimize(int mutationSize) throws AppSearchException {
public void checkForOptimize(int mutationSize, @Nullable OptimizeStats.Builder builder)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
mOptimizeIntervalCountLocked += mutationSize;
if (mOptimizeIntervalCountLocked >= CHECK_OPTIMIZE_INTERVAL) {
checkForOptimize();
checkForOptimize(builder);
}
} finally {
mReadWriteLock.writeLock().unlock();
@ -2183,14 +2187,15 @@ public final class AppSearchImpl implements Closeable {
* <p>{@link IcingSearchEngine#optimize()} should be called only if {@link
* OptimizeStrategy#shouldOptimize(GetOptimizeInfoResultProto)} return true.
*/
public void checkForOptimize() throws AppSearchException {
public void checkForOptimize(@Nullable OptimizeStats.Builder builder)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResultLocked();
checkSuccess(optimizeInfo.getStatus());
mOptimizeIntervalCountLocked = 0;
if (mOptimizeStrategy.shouldOptimize(optimizeInfo)) {
optimize();
optimize(builder);
}
} finally {
mReadWriteLock.writeLock().unlock();
@ -2201,13 +2206,18 @@ public final class AppSearchImpl implements Closeable {
}
/** Triggers {@link IcingSearchEngine#optimize()} directly. */
public void optimize() throws AppSearchException {
public void optimize(@Nullable OptimizeStats.Builder builder) throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
mLogUtil.piiTrace("optimize, request");
OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize();
mLogUtil.piiTrace(
"optimize, response", optimizeResultProto.getStatus(), optimizeResultProto);
if (builder != null) {
builder.setStatusCode(statusProtoToResultCode(optimizeResultProto.getStatus()));
AppSearchLoggerHelper.copyNativeStats(
optimizeResultProto.getOptimizeStats(), builder);
}
checkSuccess(optimizeResultProto.getStatus());
} finally {
mReadWriteLock.writeLock().unlock();

View File

@ -17,10 +17,10 @@
package com.android.server.appsearch.external.localstorage;
import android.annotation.NonNull;
import android.app.appsearch.exceptions.AppSearchException;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@ -37,19 +37,22 @@ import com.android.server.appsearch.external.localstorage.stats.SearchStats;
*/
public interface AppSearchLogger {
/** Logs {@link CallStats} */
void logStats(@NonNull CallStats stats) throws AppSearchException;
void logStats(@NonNull CallStats stats);
/** Logs {@link PutDocumentStats} */
void logStats(@NonNull PutDocumentStats stats) throws AppSearchException;
void logStats(@NonNull PutDocumentStats stats);
/** Logs {@link InitializeStats} */
void logStats(@NonNull InitializeStats stats) throws AppSearchException;
void logStats(@NonNull InitializeStats stats);
/** Logs {@link SearchStats} */
void logStats(@NonNull SearchStats stats) throws AppSearchException;
void logStats(@NonNull SearchStats stats);
/** Logs {@link RemoveStats} */
void logStats(@NonNull RemoveStats stats) throws AppSearchException;
void logStats(@NonNull RemoveStats stats);
/** Logs {@link OptimizeStats} */
void logStats(@NonNull OptimizeStats stats);
// TODO(b/173532925) Add remaining logStats once we add all the stats.
}

View File

@ -19,12 +19,14 @@ package com.android.server.appsearch.external.localstorage;
import android.annotation.NonNull;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.google.android.icing.proto.DeleteStatsProto;
import com.google.android.icing.proto.InitializeStatsProto;
import com.google.android.icing.proto.OptimizeStatsProto;
import com.google.android.icing.proto.PutDocumentStatsProto;
import com.google.android.icing.proto.QueryStatsProto;
@ -92,8 +94,8 @@ public final class AppSearchLoggerHelper {
.setSchemaTypeCount(fromNativeStats.getNumSchemaTypes());
}
/*
* Copy native Query stats to buiilder.
/**
* Copies native Query stats to builder.
*
* @param fromNativeStats Stats copied from.
* @param toStatsBuilder Stats copied to.
@ -122,8 +124,8 @@ public final class AppSearchLoggerHelper {
fromNativeStats.getDocumentRetrievalLatencyMs());
}
/*
* Copy native Query stats to buiilder.
/**
* Copies native Delete stats to builder.
*
* @param fromNativeStats Stats copied from.
* @param toStatsBuilder Stats copied to.
@ -138,4 +140,28 @@ public final class AppSearchLoggerHelper {
.setDeleteType(fromNativeStats.getDeleteType().getNumber())
.setDeletedDocumentCount(fromNativeStats.getNumDocumentsDeleted());
}
/**
* Copies native {@link OptimizeStatsProto} to builder.
*
* @param fromNativeStats Stats copied from.
* @param toStatsBuilder Stats copied to.
*/
static void copyNativeStats(
@NonNull OptimizeStatsProto fromNativeStats,
@NonNull OptimizeStats.Builder toStatsBuilder) {
Objects.requireNonNull(fromNativeStats);
Objects.requireNonNull(toStatsBuilder);
toStatsBuilder
.setNativeLatencyMillis(fromNativeStats.getLatencyMs())
.setDocumentStoreOptimizeLatencyMillis(
fromNativeStats.getDocumentStoreOptimizeLatencyMs())
.setIndexRestorationLatencyMillis(fromNativeStats.getIndexRestorationLatencyMs())
.setOriginalDocumentCount(fromNativeStats.getNumOriginalDocuments())
.setDeletedDocumentCount(fromNativeStats.getNumDeletedDocuments())
.setExpiredDocumentCount(fromNativeStats.getNumExpiredDocuments())
.setStorageSizeBeforeBytes(fromNativeStats.getStorageSizeBefore())
.setStorageSizeAfterBytes(fromNativeStats.getStorageSizeAfter())
.setTimeSinceLastOptimizeMillis(fromNativeStats.getTimeSinceLastOptimizeMs());
}
}

View File

@ -0,0 +1,243 @@
/*
* Copyright 2021 The Android Open Source Project
*
* 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.android.server.appsearch.external.localstorage.stats;
import android.annotation.NonNull;
import android.app.appsearch.AppSearchResult;
import java.util.Objects;
/**
* Class holds detailed stats for Optimize.
*
* @hide
*/
public final class OptimizeStats {
/**
* The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal
* state.
*/
@AppSearchResult.ResultCode private final int mStatusCode;
private final int mTotalLatencyMillis;
private final int mNativeLatencyMillis;
// Time used to optimize the document store in millis.
private final int mNativeDocumentStoreOptimizeLatencyMillis;
// Time used to restore the index in millis.
private final int mNativeIndexRestorationLatencyMillis;
// Number of documents before the optimization.
private final int mNativeOriginalDocumentCount;
// Number of documents deleted during the optimization.
private final int mNativeDeletedDocumentCount;
// Number of documents expired during the optimization.
private final int mNativeExpiredDocumentCount;
// Size of storage in bytes before the optimization.
private final long mNativeStorageSizeBeforeBytes;
// Size of storage in bytes after the optimization.
private final long mNativeStorageSizeAfterBytes;
// The amount of time in millis since the last optimization ran calculated using wall clock time
private final long mNativeTimeSinceLastOptimizeMillis;
OptimizeStats(@NonNull Builder builder) {
Objects.requireNonNull(builder);
mStatusCode = builder.mStatusCode;
mTotalLatencyMillis = builder.mTotalLatencyMillis;
mNativeLatencyMillis = builder.mNativeLatencyMillis;
mNativeDocumentStoreOptimizeLatencyMillis =
builder.mNativeDocumentStoreOptimizeLatencyMillis;
mNativeIndexRestorationLatencyMillis = builder.mNativeIndexRestorationLatencyMillis;
mNativeOriginalDocumentCount = builder.mNativeOriginalDocumentCount;
mNativeDeletedDocumentCount = builder.mNativeDeletedDocumentCount;
mNativeExpiredDocumentCount = builder.mNativeExpiredDocumentCount;
mNativeStorageSizeBeforeBytes = builder.mNativeStorageSizeBeforeBytes;
mNativeStorageSizeAfterBytes = builder.mNativeStorageSizeAfterBytes;
mNativeTimeSinceLastOptimizeMillis = builder.mNativeTimeSinceLastOptimizeMillis;
}
/** Returns status code for this optimization. */
@AppSearchResult.ResultCode
public int getStatusCode() {
return mStatusCode;
}
/** Returns total latency of this optimization in millis. */
public int getTotalLatencyMillis() {
return mTotalLatencyMillis;
}
/** Returns how much time in millis spent in the native code. */
public int getNativeLatencyMillis() {
return mNativeLatencyMillis;
}
/** Returns time used to optimize the document store in millis. */
public int getDocumentStoreOptimizeLatencyMillis() {
return mNativeDocumentStoreOptimizeLatencyMillis;
}
/** Returns time used to restore the index in millis. */
public int getIndexRestorationLatencyMillis() {
return mNativeIndexRestorationLatencyMillis;
}
/** Returns number of documents before the optimization. */
public int getOriginalDocumentCount() {
return mNativeOriginalDocumentCount;
}
/** Returns number of documents deleted during the optimization. */
public int getDeletedDocumentCount() {
return mNativeDeletedDocumentCount;
}
/** Returns number of documents expired during the optimization. */
public int getExpiredDocumentCount() {
return mNativeExpiredDocumentCount;
}
/** Returns size of storage in bytes before the optimization. */
public long getStorageSizeBeforeBytes() {
return mNativeStorageSizeBeforeBytes;
}
/** Returns size of storage in bytes after the optimization. */
public long getStorageSizeAfterBytes() {
return mNativeStorageSizeAfterBytes;
}
/**
* Returns the amount of time in millis since the last optimization ran calculated using wall
* clock time.
*/
public long getTimeSinceLastOptimizeMillis() {
return mNativeTimeSinceLastOptimizeMillis;
}
/** Builder for {@link RemoveStats}. */
public static class Builder {
/**
* The status code returned by {@link AppSearchResult#getResultCode()} for the call or
* internal state.
*/
@AppSearchResult.ResultCode int mStatusCode;
int mTotalLatencyMillis;
int mNativeLatencyMillis;
int mNativeDocumentStoreOptimizeLatencyMillis;
int mNativeIndexRestorationLatencyMillis;
int mNativeOriginalDocumentCount;
int mNativeDeletedDocumentCount;
int mNativeExpiredDocumentCount;
long mNativeStorageSizeBeforeBytes;
long mNativeStorageSizeAfterBytes;
long mNativeTimeSinceLastOptimizeMillis;
/** Sets the status code. */
@NonNull
public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
mStatusCode = statusCode;
return this;
}
/** Sets total latency in millis. */
@NonNull
public Builder setTotalLatencyMillis(int totalLatencyMillis) {
mTotalLatencyMillis = totalLatencyMillis;
return this;
}
/** Sets native latency in millis. */
@NonNull
public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
mNativeLatencyMillis = nativeLatencyMillis;
return this;
}
/** Sets time used to optimize the document store. */
@NonNull
public Builder setDocumentStoreOptimizeLatencyMillis(
int documentStoreOptimizeLatencyMillis) {
mNativeDocumentStoreOptimizeLatencyMillis = documentStoreOptimizeLatencyMillis;
return this;
}
/** Sets time used to restore the index. */
@NonNull
public Builder setIndexRestorationLatencyMillis(int indexRestorationLatencyMillis) {
mNativeIndexRestorationLatencyMillis = indexRestorationLatencyMillis;
return this;
}
/** Sets number of documents before the optimization. */
@NonNull
public Builder setOriginalDocumentCount(int originalDocumentCount) {
mNativeOriginalDocumentCount = originalDocumentCount;
return this;
}
/** Sets number of documents deleted during the optimization. */
@NonNull
public Builder setDeletedDocumentCount(int deletedDocumentCount) {
mNativeDeletedDocumentCount = deletedDocumentCount;
return this;
}
/** Sets number of documents expired during the optimization. */
@NonNull
public Builder setExpiredDocumentCount(int expiredDocumentCount) {
mNativeExpiredDocumentCount = expiredDocumentCount;
return this;
}
/** Sets Storage size in bytes before optimization. */
@NonNull
public Builder setStorageSizeBeforeBytes(long storageSizeBeforeBytes) {
mNativeStorageSizeBeforeBytes = storageSizeBeforeBytes;
return this;
}
/** Sets storage size in bytes after optimization. */
@NonNull
public Builder setStorageSizeAfterBytes(long storageSizeAfterBytes) {
mNativeStorageSizeAfterBytes = storageSizeAfterBytes;
return this;
}
/**
* Sets the amount the time since the last optimize ran calculated using wall clock time.
*/
@NonNull
public Builder setTimeSinceLastOptimizeMillis(long timeSinceLastOptimizeMillis) {
mNativeTimeSinceLastOptimizeMillis = timeSinceLastOptimizeMillis;
return this;
}
/** Creates a {@link OptimizeStats}. */
@NonNull
public OptimizeStats build() {
return new OptimizeStats(/* builder= */ this);
}
}
}

View File

@ -32,6 +32,7 @@ import com.android.server.appsearch.AppSearchConfig;
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
@ -145,7 +146,7 @@ public final class PlatformLogger implements AppSearchLogger {
}
@Override
public void logStats(@NonNull InitializeStats stats) throws AppSearchException {
public void logStats(@NonNull InitializeStats stats) {
Objects.requireNonNull(stats);
synchronized (mLock) {
if (shouldLogForTypeLocked(CallStats.CALL_TYPE_INITIALIZE)) {
@ -155,7 +156,7 @@ public final class PlatformLogger implements AppSearchLogger {
}
@Override
public void logStats(@NonNull SearchStats stats) throws AppSearchException {
public void logStats(@NonNull SearchStats stats) {
Objects.requireNonNull(stats);
synchronized (mLock) {
if (shouldLogForTypeLocked(CallStats.CALL_TYPE_SEARCH)) {
@ -165,10 +166,20 @@ public final class PlatformLogger implements AppSearchLogger {
}
@Override
public void logStats(@NonNull RemoveStats stats) throws AppSearchException {
public void logStats(@NonNull RemoveStats stats) {
// TODO(b/173532925): Log stats
}
@Override
public void logStats(@NonNull OptimizeStats stats) {
Objects.requireNonNull(stats);
synchronized (mLock) {
if (shouldLogForTypeLocked(CallStats.CALL_TYPE_OPTIMIZE)) {
logStatsImplLocked(stats);
}
}
}
/**
* Removes cached UID for package.
*
@ -326,6 +337,27 @@ public final class PlatformLogger implements AppSearchLogger {
stats.getResetStatusCode());
}
@GuardedBy("mLock")
private void logStatsImplLocked(@NonNull OptimizeStats stats) {
mLastPushTimeMillisLocked = SystemClock.elapsedRealtime();
ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null,
CallStats.CALL_TYPE_OPTIMIZE);
AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_OPTIMIZE_STATS_REPORTED,
extraStats.mSamplingInterval,
extraStats.mSkippedSampleCount,
stats.getStatusCode(),
stats.getTotalLatencyMillis(),
stats.getNativeLatencyMillis(),
stats.getDocumentStoreOptimizeLatencyMillis(),
stats.getIndexRestorationLatencyMillis(),
stats.getOriginalDocumentCount(),
stats.getDeletedDocumentCount(),
stats.getExpiredDocumentCount(),
stats.getStorageSizeBeforeBytes(),
stats.getStorageSizeAfterBytes(),
stats.getTimeSinceLastOptimizeMillis());
}
/**
* Calculate the hash code as an integer by returning the last four bytes of its MD5.
*
@ -464,15 +496,19 @@ public final class PlatformLogger implements AppSearchLogger {
return mConfig.getCachedSamplingIntervalForBatchCallStats();
case CallStats.CALL_TYPE_PUT_DOCUMENT:
return mConfig.getCachedSamplingIntervalForPutDocumentStats();
case CallStats.CALL_TYPE_UNKNOWN:
case CallStats.CALL_TYPE_INITIALIZE:
return mConfig.getCachedSamplingIntervalForInitializeStats();
case CallStats.CALL_TYPE_SEARCH:
return mConfig.getCachedSamplingIntervalForSearchStats();
case CallStats.CALL_TYPE_GLOBAL_SEARCH:
return mConfig.getCachedSamplingIntervalForGlobalSearchStats();
case CallStats.CALL_TYPE_OPTIMIZE:
return mConfig.getCachedSamplingIntervalForOptimizeStats();
case CallStats.CALL_TYPE_UNKNOWN:
case CallStats.CALL_TYPE_SET_SCHEMA:
case CallStats.CALL_TYPE_GET_DOCUMENT:
case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_ID:
case CallStats.CALL_TYPE_SEARCH:
case CallStats.CALL_TYPE_OPTIMIZE:
case CallStats.CALL_TYPE_FLUSH:
case CallStats.CALL_TYPE_GLOBAL_SEARCH:
case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH:
// TODO(b/173532925) Some of them above will have dedicated sampling ratio config
default:

View File

@ -50,6 +50,14 @@ public class AppSearchConfigTest {
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo(
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
AppSearchConfig.DEFAULT_SAMPLING_INTERVAL);
assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentSizeBytes()).isEqualTo(
AppSearchConfig.DEFAULT_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES);
assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentCount()).isEqualTo(
@ -100,6 +108,11 @@ public class AppSearchConfigTest {
final int samplingIntervalDefault = -1;
final int samplingIntervalPutDocumentStats = -2;
final int samplingIntervalBatchCallStats = -3;
final int samplingIntervalInitializeStats = -4;
final int samplingIntervalSearchStats = -5;
final int samplingIntervalGlobalSearchStats = -6;
final int samplingIntervalOptimizeStats = -7;
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
Integer.toString(samplingIntervalDefault),
@ -112,6 +125,22 @@ public class AppSearchConfigTest {
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
Integer.toString(samplingIntervalBatchCallStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
Integer.toString(samplingIntervalInitializeStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
Integer.toString(samplingIntervalSearchStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
Integer.toString(samplingIntervalGlobalSearchStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
Integer.toString(samplingIntervalOptimizeStats),
false);
AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
@ -121,6 +150,14 @@ public class AppSearchConfigTest {
samplingIntervalPutDocumentStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
samplingIntervalBatchCallStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
samplingIntervalInitializeStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
samplingIntervalSearchStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
samplingIntervalGlobalSearchStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
samplingIntervalOptimizeStats);
}
@Test
@ -128,6 +165,10 @@ public class AppSearchConfigTest {
int samplingIntervalDefault = -1;
int samplingIntervalPutDocumentStats = -2;
int samplingIntervalBatchCallStats = -3;
int samplingIntervalInitializeStats = -4;
int samplingIntervalSearchStats = -5;
int samplingIntervalGlobalSearchStats = -6;
int samplingIntervalOptimizeStats = -7;
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
Integer.toString(samplingIntervalDefault),
@ -140,12 +181,32 @@ public class AppSearchConfigTest {
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
Integer.toString(samplingIntervalBatchCallStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
Integer.toString(samplingIntervalInitializeStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
Integer.toString(samplingIntervalSearchStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
Integer.toString(samplingIntervalGlobalSearchStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
Integer.toString(samplingIntervalOptimizeStats),
false);
AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR);
// Overrides
samplingIntervalDefault = -4;
samplingIntervalPutDocumentStats = -5;
samplingIntervalBatchCallStats = -6;
samplingIntervalInitializeStats = -7;
samplingIntervalSearchStats = -8;
samplingIntervalGlobalSearchStats = -9;
samplingIntervalOptimizeStats = -10;
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT,
Integer.toString(samplingIntervalDefault),
@ -158,6 +219,22 @@ public class AppSearchConfigTest {
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS,
Integer.toString(samplingIntervalBatchCallStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS,
Integer.toString(samplingIntervalInitializeStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS,
Integer.toString(samplingIntervalSearchStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS,
Integer.toString(samplingIntervalGlobalSearchStats),
false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH,
AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS,
Integer.toString(samplingIntervalOptimizeStats),
false);
assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo(
samplingIntervalDefault);
@ -165,6 +242,14 @@ public class AppSearchConfigTest {
samplingIntervalPutDocumentStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo(
samplingIntervalBatchCallStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo(
samplingIntervalInitializeStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo(
samplingIntervalSearchStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo(
samplingIntervalGlobalSearchStats);
assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo(
samplingIntervalOptimizeStats);
}
/**
@ -364,6 +449,18 @@ public class AppSearchConfigTest {
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getCachedSamplingIntervalForPutDocumentStats());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getCachedSamplingIntervalForInitializeStats());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getCachedSamplingIntervalForSearchStats());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getCachedSamplingIntervalForOptimizeStats());
Assert.assertThrows("Trying to use a closed AppSearchConfig instance.",
IllegalStateException.class,
() -> appSearchConfig.getCachedBytesOptimizeThreshold());

View File

@ -0,0 +1 @@
include /apex/appsearch/OWNERS

View File

@ -42,6 +42,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
import com.android.server.appsearch.icing.proto.DocumentProto;
import com.android.server.appsearch.icing.proto.GetOptimizeInfoResultProto;
@ -451,19 +452,26 @@ public class AppSearchImplTest {
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1);
// Increase mutation counter and stop before reach the threshold
mAppSearchImpl.checkForOptimize(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1);
mAppSearchImpl.checkForOptimize(
AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1, /*builder=*/ null);
// Verify the optimize() isn't triggered.
optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1);
// Increase the counter and reach the threshold, optimize() should be triggered.
mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1);
OptimizeStats.Builder builder = new OptimizeStats.Builder();
mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1, builder);
// Verify optimize() is triggered.
optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked();
assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0);
assertThat(optimizeInfo.getEstimatedOptimizableBytes()).isEqualTo(0);
// Verify the stats have been set.
OptimizeStats oStats = builder.build();
assertThat(oStats.getOriginalDocumentCount()).isEqualTo(1);
assertThat(oStats.getDeletedDocumentCount()).isEqualTo(1);
}
@Test

View File

@ -29,12 +29,14 @@ import android.app.appsearch.exceptions.AppSearchException;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
import com.android.server.appsearch.external.localstorage.stats.InitializeStats;
import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.android.server.appsearch.icing.proto.DeleteStatsProto;
import com.android.server.appsearch.icing.proto.DocumentProto;
import com.android.server.appsearch.icing.proto.InitializeStatsProto;
import com.android.server.appsearch.icing.proto.OptimizeStatsProto;
import com.android.server.appsearch.icing.proto.PutDocumentStatsProto;
import com.android.server.appsearch.icing.proto.PutResultProto;
import com.android.server.appsearch.icing.proto.QueryStatsProto;
@ -81,6 +83,7 @@ public class AppSearchLoggerTest {
@Nullable InitializeStats mInitializeStats;
@Nullable SearchStats mSearchStats;
@Nullable RemoveStats mRemoveStats;
@Nullable OptimizeStats mOptimizeStats;
@Override
public void logStats(@NonNull CallStats stats) {
@ -106,6 +109,11 @@ public class AppSearchLoggerTest {
public void logStats(@NonNull RemoveStats stats) {
mRemoveStats = stats;
}
@Override
public void logStats(@NonNull OptimizeStats stats) {
mOptimizeStats = stats;
}
}
@Test
@ -286,6 +294,48 @@ public class AppSearchLoggerTest {
assertThat(rStats.getDeletedDocumentCount()).isEqualTo(nativeNumDocumentDeleted);
}
@Test
public void testAppSearchLoggerHelper_testCopyNativeStats_optimize() {
int nativeLatencyMillis = 1;
int nativeDocumentStoreOptimizeLatencyMillis = 2;
int nativeIndexRestorationLatencyMillis = 3;
int nativeNumOriginalDocuments = 4;
int nativeNumDeletedDocuments = 5;
int nativeNumExpiredDocuments = 6;
long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1;
long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2;
long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3;
OptimizeStatsProto optimizeStatsProto =
OptimizeStatsProto.newBuilder()
.setLatencyMs(nativeLatencyMillis)
.setDocumentStoreOptimizeLatencyMs(nativeDocumentStoreOptimizeLatencyMillis)
.setIndexRestorationLatencyMs(nativeIndexRestorationLatencyMillis)
.setNumOriginalDocuments(nativeNumOriginalDocuments)
.setNumDeletedDocuments(nativeNumDeletedDocuments)
.setNumExpiredDocuments(nativeNumExpiredDocuments)
.setStorageSizeBefore(nativeStorageSizeBeforeBytes)
.setStorageSizeAfter(nativeStorageSizeAfterBytes)
.setTimeSinceLastOptimizeMs(nativeTimeSinceLastOptimizeMillis)
.build();
OptimizeStats.Builder oBuilder = new OptimizeStats.Builder();
AppSearchLoggerHelper.copyNativeStats(optimizeStatsProto, oBuilder);
OptimizeStats oStats = oBuilder.build();
assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
assertThat(oStats.getDocumentStoreOptimizeLatencyMillis())
.isEqualTo(nativeDocumentStoreOptimizeLatencyMillis);
assertThat(oStats.getIndexRestorationLatencyMillis())
.isEqualTo(nativeIndexRestorationLatencyMillis);
assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments);
assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments);
assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments);
assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes);
assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes);
assertThat(oStats.getTimeSinceLastOptimizeMillis())
.isEqualTo(nativeTimeSinceLastOptimizeMillis);
}
//
// Testing actual logging
//

View File

@ -348,4 +348,49 @@ public class AppSearchStatsTest {
assertThat(rStats.getDeleteType()).isEqualTo(deleteType);
assertThat(rStats.getDeletedDocumentCount()).isEqualTo(documentDeletedCount);
}
@Test
public void testAppSearchStats_OptimizeStats() {
int nativeLatencyMillis = 1;
int nativeDocumentStoreOptimizeLatencyMillis = 2;
int nativeIndexRestorationLatencyMillis = 3;
int nativeNumOriginalDocuments = 4;
int nativeNumDeletedDocuments = 5;
int nativeNumExpiredDocuments = 6;
long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1;
long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2;
long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3;
final OptimizeStats oStats =
new OptimizeStats.Builder()
.setStatusCode(TEST_STATUS_CODE)
.setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
.setNativeLatencyMillis(nativeLatencyMillis)
.setDocumentStoreOptimizeLatencyMillis(
nativeDocumentStoreOptimizeLatencyMillis)
.setIndexRestorationLatencyMillis(nativeIndexRestorationLatencyMillis)
.setOriginalDocumentCount(nativeNumOriginalDocuments)
.setDeletedDocumentCount(nativeNumDeletedDocuments)
.setExpiredDocumentCount(nativeNumExpiredDocuments)
.setStorageSizeBeforeBytes(nativeStorageSizeBeforeBytes)
.setStorageSizeAfterBytes(nativeStorageSizeAfterBytes)
.setTimeSinceLastOptimizeMillis(nativeTimeSinceLastOptimizeMillis)
.build();
assertThat(oStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
assertThat(oStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
assertThat(oStats.getDocumentStoreOptimizeLatencyMillis())
.isEqualTo(nativeDocumentStoreOptimizeLatencyMillis);
assertThat(oStats.getIndexRestorationLatencyMillis())
.isEqualTo(nativeIndexRestorationLatencyMillis);
assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments);
assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments);
assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments);
assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes);
assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes);
assertThat(oStats.getTimeSinceLastOptimizeMillis())
.isEqualTo(nativeTimeSinceLastOptimizeMillis);
}
}