Skip to content

Commit 0c8ee73

Browse files
committed
Adding deleteModel logging and retrieve download success events.
1 parent 29e73e5 commit 0c8ee73

File tree

9 files changed

+208
-11
lines changed

9 files changed

+208
-11
lines changed

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,17 @@ public Task<Void> deleteDownloadedModel(@NonNull String modelName) {
460460
executor.execute(
461461
() -> {
462462
// remove all files associated with this model and then clean up model references.
463-
deleteModelDetails(modelName);
463+
boolean isSuccessful = deleteModelDetails(modelName);
464464
taskCompletionSource.setResult(null);
465+
eventLogger.logDeleteModel(isSuccessful);
465466
});
466467
return taskCompletionSource.getTask();
467468
}
468469

469-
private void deleteModelDetails(@NonNull String modelName) {
470-
fileManager.deleteAllModels(modelName);
470+
private boolean deleteModelDetails(@NonNull String modelName) {
471+
boolean isSuccessful = fileManager.deleteAllModels(modelName);
471472
sharedPreferencesUtil.clearModelDetails(modelName);
473+
return isSuccessful;
472474
}
473475

474476
/**

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/CustomModelDownloadService.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,18 @@ private Task<CustomModel> readCustomModelResponse(
322322
inputStream.close();
323323

324324
if (!downloadUrl.isEmpty() && expireTime > 0L) {
325-
return Tasks.forResult(
326-
new CustomModel(modelName, modelHash, fileSize, downloadUrl, expireTime));
325+
CustomModel model = new CustomModel(modelName, modelHash, fileSize, downloadUrl, expireTime);
326+
eventLogger.logModelInfoRetrieverSuccess(model);
327+
return Tasks.forResult(model);
327328
}
328-
return Tasks.forResult(null);
329+
eventLogger.logDownloadFailureWithReason(
330+
new CustomModel(modelName, modelHash, 0, 0L),
331+
false,
332+
ErrorCode.MODEL_INFO_DOWNLOAD_CONNECTION_FAILED.getValue());
333+
return Tasks.forException(
334+
new FirebaseMlException(
335+
"Model info could not be extracted from download response.",
336+
FirebaseMlException.INTERNAL));
329337
}
330338

331339
private static InputStream maybeUnGzip(InputStream input, String contentEncoding)

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/FirebaseMlLogEvent.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.firebase.encoders.annotations.Encodable;
2525
import com.google.firebase.encoders.json.JsonDataEncoderBuilder;
2626
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.EventName;
27+
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.ModelOptions.ModelInfo.ModelType;
2728
import java.lang.annotation.Retention;
2829
import java.lang.annotation.RetentionPolicy;
2930
import java.nio.charset.Charset;
@@ -59,7 +60,8 @@ public static Builder builder() {
5960
public enum EventName {
6061
UNKNOWN_EVENT(0),
6162
MODEL_DOWNLOAD(100),
62-
MODEL_UPDATE(101);
63+
MODEL_UPDATE(101),
64+
REMOTE_MODEL_DELETE_ON_DEVICE(252);
6365
private static final SparseArray<EventName> valueMap = new SparseArray<>();
6466

6567
private final int value;
@@ -68,6 +70,7 @@ public enum EventName {
6870
valueMap.put(0, UNKNOWN_EVENT);
6971
valueMap.put(100, MODEL_DOWNLOAD);
7072
valueMap.put(101, MODEL_UPDATE);
73+
valueMap.put(101, REMOTE_MODEL_DELETE_ON_DEVICE);
7174
}
7275

7376
EventName(int value) {
@@ -128,6 +131,9 @@ public abstract static class Builder {
128131
@Nullable
129132
public abstract ModelDownloadLogEvent getModelDownloadLogEvent();
130133

134+
@Nullable
135+
public abstract DeleteModelLogEvent getDeleteModelLogEvent();
136+
131137
@NonNull
132138
protected abstract Builder toBuilder();
133139

@@ -192,6 +198,7 @@ public int getValue() {
192198
public enum DownloadStatus {
193199
UNKNOWN_STATUS(0),
194200
EXPLICITLY_REQUESTED(1),
201+
MODEL_INFO_RETRIEVAL_SUCCEEDED(3),
195202
MODEL_INFO_RETRIEVAL_FAILED(4),
196203
SCHEDULED(5),
197204
DOWNLOADING(6),
@@ -205,6 +212,7 @@ public enum DownloadStatus {
205212
static {
206213
valueMap.put(0, UNKNOWN_STATUS);
207214
valueMap.put(1, EXPLICITLY_REQUESTED);
215+
valueMap.put(3, MODEL_INFO_RETRIEVAL_SUCCEEDED);
208216
valueMap.put(4, MODEL_INFO_RETRIEVAL_FAILED);
209217
valueMap.put(5, SCHEDULED);
210218
valueMap.put(6, DOWNLOADING);
@@ -327,6 +335,34 @@ public abstract static class Builder {
327335
}
328336
}
329337

338+
@AutoValue
339+
public abstract static class DeleteModelLogEvent {
340+
@NonNull
341+
public static Builder builder() {
342+
return new AutoValue_FirebaseMlLogEvent_DeleteModelLogEvent.Builder()
343+
.setModelType(ModelType.CUSTOM)
344+
.setIsSuccessful(true);
345+
}
346+
347+
@ModelType
348+
public abstract int getModelType();
349+
350+
public abstract boolean getIsSuccessful();
351+
352+
/** Builder for {@link DeleteModelLogEvent}. */
353+
@AutoValue.Builder
354+
public abstract static class Builder {
355+
@NonNull
356+
public abstract Builder setModelType(@ModelType int value);
357+
358+
@NonNull
359+
public abstract Builder setIsSuccessful(boolean value);
360+
361+
@NonNull
362+
public abstract DeleteModelLogEvent build();
363+
}
364+
}
365+
330366
@AutoValue.Builder
331367
public abstract static class Builder {
332368

@@ -339,6 +375,9 @@ public abstract static class Builder {
339375
@Nullable
340376
public abstract Builder setModelDownloadLogEvent(@Nullable ModelDownloadLogEvent value);
341377

378+
@Nullable
379+
public abstract Builder setDeleteModelLogEvent(@Nullable DeleteModelLogEvent value);
380+
342381
@NonNull
343382
public abstract FirebaseMlLogEvent build();
344383
}

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/FirebaseMlLogger.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.firebase.FirebaseApp;
2626
import com.google.firebase.ml.modeldownloader.BuildConfig;
2727
import com.google.firebase.ml.modeldownloader.CustomModel;
28+
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.DeleteModelLogEvent;
2829
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.EventName;
2930
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent;
3031
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.DownloadStatus;
@@ -96,6 +97,16 @@ void logModelInfoRetrieverFailure(CustomModel model, ErrorCode errorCode) {
9697
logModelInfoRetrieverFailure(model, errorCode, NO_FAILURE_VALUE);
9798
}
9899

100+
void logModelInfoRetrieverSuccess(CustomModel model) {
101+
logDownloadEvent(
102+
model,
103+
ErrorCode.NO_ERROR,
104+
false,
105+
/* shouldLogExactDownloadTime= */ false,
106+
DownloadStatus.MODEL_INFO_RETRIEVAL_SUCCEEDED,
107+
FirebaseMlLogEvent.NO_INT_VALUE);
108+
}
109+
99110
void logModelInfoRetrieverFailure(CustomModel model, ErrorCode errorCode, int httpResponseCode) {
100111
logDownloadEvent(
101112
model,
@@ -148,6 +159,25 @@ private boolean isStatsLoggingEnabled() {
148159
return sharedPreferencesUtil.getCustomModelStatsCollectionFlag();
149160
}
150161

162+
public void logDeleteModel(boolean success) {
163+
if (!isStatsLoggingEnabled()) {
164+
return;
165+
}
166+
167+
try {
168+
eventSender.sendEvent(
169+
FirebaseMlLogEvent.builder()
170+
.setDeleteModelLogEvent(
171+
DeleteModelLogEvent.builder().setIsSuccessful(success).build())
172+
.setEventName(EventName.REMOTE_MODEL_DELETE_ON_DEVICE)
173+
.setSystemInfo(getSystemInfo())
174+
.build());
175+
} catch (RuntimeException e) {
176+
// Swallow the exception since logging should not break the SDK usage
177+
Log.e(TAG, "Exception thrown from the logging side", e);
178+
}
179+
}
180+
151181
private void logDownloadEvent(
152182
CustomModel customModel,
153183
ErrorCode errorCode,

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/ModelFileManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,9 @@ public synchronized void deleteOldModels(
238238
* destination for a model in this method.
239239
*/
240240
@WorkerThread
241-
public synchronized void deleteAllModels(@NonNull String modelName) {
241+
public synchronized boolean deleteAllModels(@NonNull String modelName) {
242242
File modelFolder = getModelDirUnsafe(modelName);
243-
deleteRecursively(modelFolder);
243+
return deleteRecursively(modelFolder);
244244
}
245245

246246
/**

firebase-ml-modeldownloader/src/test/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloaderTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,7 @@ public void deleteDownloadedModel() throws Exception {
749749
assertThat(task.isComplete()).isTrue();
750750
verify(mockPrefs, times(1)).clearModelDetails(eq(MODEL_NAME));
751751
verify(mockFileManager, times(1)).deleteAllModels(eq(MODEL_NAME));
752+
verify(mockEventLogger, times(1)).logDeleteModel(eq(true));
752753
}
753754

754755
@Test

firebase-ml-modeldownloader/src/test/java/com/google/firebase/ml/modeldownloader/internal/FirebaseMlLogEventTest.java

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import com.google.firebase.ml.modeldownloader.BuildConfig;
2121
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.DownloadStatus;
22+
import com.google.firebase.ml.modeldownloader.proto.DeleteModelLogEvent;
2223
import com.google.firebase.ml.modeldownloader.proto.ErrorCode;
2324
import com.google.firebase.ml.modeldownloader.proto.EventName;
2425
import com.google.firebase.ml.modeldownloader.proto.FirebaseMlLogEvent;
@@ -44,7 +45,7 @@ public class FirebaseMlLogEventTest {
4445

4546
@Test
4647
// This verifies the incoming json matches the expected proto.
47-
public void testLogRequest_jsonToProto() throws InvalidProtocolBufferException {
48+
public void testLogRequestModelDownload_jsonToProto() throws InvalidProtocolBufferException {
4849

4950
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent logEventJson =
5051
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.builder()
@@ -129,4 +130,65 @@ public void testLogRequest_jsonToProto() throws InvalidProtocolBufferException {
129130

130131
assertThat(parsedProtoFirebaseMlLogEvent).isEqualTo(logEventProto);
131132
}
133+
134+
@Test
135+
// This verifies the incoming json matches the expected proto.
136+
public void testLogRequestDeleteModel_jsonToProto() throws InvalidProtocolBufferException {
137+
138+
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent logEventJson =
139+
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.builder()
140+
.setEventName(
141+
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.EventName
142+
.MODEL_DOWNLOAD)
143+
.setSystemInfo(
144+
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.SystemInfo
145+
.builder()
146+
.setAppId(APP_ID)
147+
.setAppVersion(APP_VERSION)
148+
.setFirebaseProjectId(PROJECT_ID)
149+
.setApiKey(API_KEY)
150+
.setMlSdkVersion(BuildConfig.VERSION_NAME)
151+
.build())
152+
.setDeleteModelLogEvent(
153+
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent
154+
.DeleteModelLogEvent.builder()
155+
.setModelType(
156+
com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent
157+
.ModelDownloadLogEvent.ModelOptions.ModelInfo.ModelType.CUSTOM)
158+
.setIsSuccessful(true)
159+
.build())
160+
.build();
161+
162+
// Create matching proto
163+
SystemInfo systemInfo =
164+
SystemInfo.newBuilder()
165+
.setAppId(APP_ID)
166+
.setAppVersion(APP_VERSION)
167+
.setFirebaseProjectId(PROJECT_ID)
168+
.setApiKey(API_KEY)
169+
.setMlSdkVersion(BuildConfig.VERSION_NAME)
170+
.build();
171+
172+
DeleteModelLogEvent deleteModelLogEvent =
173+
DeleteModelLogEvent.newBuilder()
174+
.setModelType(ModelInfo.ModelType.CUSTOM)
175+
.setIsSuccessful(true)
176+
.build();
177+
178+
FirebaseMlLogEvent logEventProto =
179+
FirebaseMlLogEvent.newBuilder()
180+
.setEventName(EventName.MODEL_DOWNLOAD)
181+
.setSystemInfo(systemInfo)
182+
.setDeleteModelLogEvent(deleteModelLogEvent)
183+
.build();
184+
185+
String json = FIREBASE_ML_JSON_ENCODER.encode(logEventJson);
186+
187+
FirebaseMlLogEvent.Builder protoLogEventBuilder = FirebaseMlLogEvent.newBuilder();
188+
189+
JsonFormat.parser().merge(json, protoLogEventBuilder);
190+
FirebaseMlLogEvent parsedProtoFirebaseMlLogEvent = protoLogEventBuilder.build();
191+
192+
assertThat(parsedProtoFirebaseMlLogEvent).isEqualTo(logEventProto);
193+
}
132194
}

firebase-ml-modeldownloader/src/test/java/com/google/firebase/ml/modeldownloader/internal/FirebaseMlLoggerTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@
3333
import com.google.firebase.ml.modeldownloader.BuildConfig;
3434
import com.google.firebase.ml.modeldownloader.CustomModel;
3535
import com.google.firebase.ml.modeldownloader.FirebaseMlException;
36+
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.DeleteModelLogEvent;
3637
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.EventName;
3738
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent;
3839
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.DownloadStatus;
3940
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.ErrorCode;
4041
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.ModelOptions;
4142
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.ModelOptions.ModelInfo;
43+
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.ModelDownloadLogEvent.ModelOptions.ModelInfo.ModelType;
4244
import com.google.firebase.ml.modeldownloader.internal.FirebaseMlLogEvent.SystemInfo;
4345
import org.junit.Before;
4446
import org.junit.Test;
@@ -164,6 +166,48 @@ public void logDownloadFailureWithReason_getModelDownloadBeginTimeMsNull() {
164166
verify(mockSharedPreferencesUtil, times(1)).getCustomModelStatsCollectionFlag();
165167
}
166168

169+
@Test
170+
public void logDownloadEventWithErrorCode() {
171+
when(mockSharedPreferencesUtil.getModelDownloadBeginTimeMs(any())).thenReturn(0L);
172+
mlLogger.logDownloadEventWithErrorCode(
173+
CUSTOM_MODEL_DOWNLOADING, false, DownloadStatus.SUCCEEDED, ErrorCode.DOWNLOAD_FAILED);
174+
175+
verify(mockStatsSender, Mockito.times(1))
176+
.sendEvent(
177+
eq(
178+
FirebaseMlLogEvent.builder()
179+
.setEventName(EventName.MODEL_DOWNLOAD)
180+
.setModelDownloadLogEvent(
181+
ModelDownloadLogEvent.builder()
182+
.setOptions(MODEL_OPTIONS)
183+
.setErrorCode(ErrorCode.DOWNLOAD_FAILED)
184+
.setDownloadStatus(DownloadStatus.SUCCEEDED)
185+
.build())
186+
.setSystemInfo(systemInfo)
187+
.build()));
188+
verify(mockSharedPreferencesUtil, times(1)).getCustomModelStatsCollectionFlag();
189+
}
190+
191+
@Test
192+
public void logDeleteModel() {
193+
when(mockSharedPreferencesUtil.getModelDownloadBeginTimeMs(any())).thenReturn(0L);
194+
mlLogger.logDeleteModel(true);
195+
196+
verify(mockStatsSender, Mockito.times(1))
197+
.sendEvent(
198+
eq(
199+
FirebaseMlLogEvent.builder()
200+
.setEventName(EventName.REMOTE_MODEL_DELETE_ON_DEVICE)
201+
.setDeleteModelLogEvent(
202+
DeleteModelLogEvent.builder()
203+
.setIsSuccessful(true)
204+
.setModelType(ModelType.CUSTOM)
205+
.build())
206+
.setSystemInfo(systemInfo)
207+
.build()));
208+
verify(mockSharedPreferencesUtil, times(1)).getCustomModelStatsCollectionFlag();
209+
}
210+
167211
@Test
168212
public void logDownloadEventWithExactDownloadTime() {
169213
mlLogger.logDownloadEventWithExactDownloadTime(

firebase-ml-modeldownloader/src/test/proto/firebase/ml/modeldownloader/firebase_ml_log_sdk.proto

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,16 @@ message ModelDownloadLogEvent {
200200
int64 download_failure_status = 6;
201201
}
202202

203+
// Information about deleting a downloaded model on device.
204+
message DeleteModelLogEvent {
205+
// The type of the downloaded model requested to be deleted.
206+
ModelInfo.ModelType model_type = 1;
207+
// Whether the downloaded model is deleted successfully.
208+
bool is_successful = 2;
209+
}
203210

204211
// Main log event for FirebaseMl, that contains individual API events, like face
205212
// detection.
206-
// NEXT ID: 44.
207213
message FirebaseMlLogEvent {
208214
// Information about various parts of the system: app, Firebase, SDK, TFLite.
209215
SystemInfo system_info = 1;
@@ -214,4 +220,9 @@ message FirebaseMlLogEvent {
214220
// Model downloading logs.
215221
// ==========================
216222
ModelDownloadLogEvent model_download_log_event = 3;
223+
224+
// API logs.
225+
// ==========================
226+
// Information about deleting a downloaded model.
227+
DeleteModelLogEvent delete_model_log_event = 40;
217228
}

0 commit comments

Comments
 (0)