Skip to content

Commit b6d8cd4

Browse files
authored
Ml logging (#2355)
* more logging * refactor event logger for use in multiple classes. * add logging messages * add more firedata logging. * add more firedata logging. * Add DownloadUrlExpired exception type. * more exception updates. * more exception updates. * adding more FirebaseMlException handling and logging * adding more FirebaseMlException handling and logging * updating api.txt * more user logs. * more user logs.
1 parent c822574 commit b6d8cd4

17 files changed

+464
-127
lines changed

firebase-ml-modeldownloader/api.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.google.firebase.ml.modeldownloader {
33

44
public class CustomModel {
55
method public long getDownloadId();
6-
method @Nullable public java.io.File getFile() throws com.google.firebase.ml.modeldownloader.FirebaseMlException;
6+
method @Nullable public java.io.File getFile();
77
method @NonNull public String getModelHash();
88
method @NonNull public String getName();
99
method public long getSize();
@@ -35,9 +35,11 @@ package com.google.firebase.ml.modeldownloader {
3535
field public static final int ALREADY_EXISTS = 6; // 0x6
3636
field public static final int CANCELLED = 1; // 0x1
3737
field public static final int DEADLINE_EXCEEDED = 4; // 0x4
38+
field public static final int DOWNLOAD_URL_EXPIRED = 121; // 0x79
3839
field public static final int FAILED_PRECONDITION = 9; // 0x9
3940
field public static final int INTERNAL = 13; // 0xd
4041
field public static final int INVALID_ARGUMENT = 3; // 0x3
42+
field public static final int MODEL_HASH_MISMATCH = 102; // 0x66
4143
field public static final int NOT_ENOUGH_SPACE = 101; // 0x65
4244
field public static final int NOT_FOUND = 5; // 0x5
4345
field public static final int OUT_OF_RANGE = 11; // 0xb
@@ -49,7 +51,7 @@ package com.google.firebase.ml.modeldownloader {
4951
field public static final int UNKNOWN = 2; // 0x2
5052
}
5153

52-
@IntDef({com.google.firebase.ml.modeldownloader.FirebaseMlException.CANCELLED, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNKNOWN, com.google.firebase.ml.modeldownloader.FirebaseMlException.INVALID_ARGUMENT, com.google.firebase.ml.modeldownloader.FirebaseMlException.DEADLINE_EXCEEDED, com.google.firebase.ml.modeldownloader.FirebaseMlException.NOT_FOUND, com.google.firebase.ml.modeldownloader.FirebaseMlException.ALREADY_EXISTS, com.google.firebase.ml.modeldownloader.FirebaseMlException.PERMISSION_DENIED, com.google.firebase.ml.modeldownloader.FirebaseMlException.RESOURCE_EXHAUSTED, com.google.firebase.ml.modeldownloader.FirebaseMlException.FAILED_PRECONDITION, com.google.firebase.ml.modeldownloader.FirebaseMlException.ABORTED, com.google.firebase.ml.modeldownloader.FirebaseMlException.OUT_OF_RANGE, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNIMPLEMENTED, com.google.firebase.ml.modeldownloader.FirebaseMlException.INTERNAL, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNAVAILABLE, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNAUTHENTICATED, com.google.firebase.ml.modeldownloader.FirebaseMlException.NOT_ENOUGH_SPACE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public static @interface FirebaseMlException.Code {
54+
@IntDef({com.google.firebase.ml.modeldownloader.FirebaseMlException.CANCELLED, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNKNOWN, com.google.firebase.ml.modeldownloader.FirebaseMlException.INVALID_ARGUMENT, com.google.firebase.ml.modeldownloader.FirebaseMlException.DEADLINE_EXCEEDED, com.google.firebase.ml.modeldownloader.FirebaseMlException.NOT_FOUND, com.google.firebase.ml.modeldownloader.FirebaseMlException.ALREADY_EXISTS, com.google.firebase.ml.modeldownloader.FirebaseMlException.PERMISSION_DENIED, com.google.firebase.ml.modeldownloader.FirebaseMlException.RESOURCE_EXHAUSTED, com.google.firebase.ml.modeldownloader.FirebaseMlException.FAILED_PRECONDITION, com.google.firebase.ml.modeldownloader.FirebaseMlException.ABORTED, com.google.firebase.ml.modeldownloader.FirebaseMlException.OUT_OF_RANGE, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNIMPLEMENTED, com.google.firebase.ml.modeldownloader.FirebaseMlException.INTERNAL, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNAVAILABLE, com.google.firebase.ml.modeldownloader.FirebaseMlException.UNAUTHENTICATED, com.google.firebase.ml.modeldownloader.FirebaseMlException.NOT_ENOUGH_SPACE, com.google.firebase.ml.modeldownloader.FirebaseMlException.MODEL_HASH_MISMATCH, com.google.firebase.ml.modeldownloader.FirebaseMlException.DOWNLOAD_URL_EXPIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public static @interface FirebaseMlException.Code {
5355
}
5456

5557
public class FirebaseModelDownloader {

firebase-ml-modeldownloader/src/androidTest/java/com/google/firebase/ml/modeldownloader/TestGetModelLocal.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
*/
4242
@RunWith(AndroidJUnit4.class)
4343
public class TestGetModelLocal {
44-
private FirebaseModelDownloader firebaseModelDownloader;
44+
4545
private static final String MODEL_NAME_LOCAL = "getLocalModel";
4646
private static final String MODEL_NAME_LOCAL_2 = "getLocalModel2";
4747
private static final String MODEL_HASH = "origHash324";
@@ -51,14 +51,13 @@ public class TestGetModelLocal {
5151
private FirebaseApp app;
5252
private File firstDeviceModelFile;
5353
private File firstLoadTempModelFile;
54-
private SharedPreferencesUtil sharedPreferencesUtil;
5554

5655
@Before
5756
public void before() {
5857
app = FirebaseApp.initializeApp(ApplicationProvider.getApplicationContext());
59-
firebaseModelDownloader = FirebaseModelDownloader.getInstance(app);
58+
FirebaseModelDownloader firebaseModelDownloader = FirebaseModelDownloader.getInstance(app);
6059

61-
sharedPreferencesUtil = new SharedPreferencesUtil(app);
60+
SharedPreferencesUtil sharedPreferencesUtil = new SharedPreferencesUtil(app);
6261
// reset shared preferences and downloads for models used by this test.
6362
firebaseModelDownloader.deleteDownloadedModel(MODEL_NAME_LOCAL);
6463
firebaseModelDownloader.deleteDownloadedModel(MODEL_NAME_LOCAL_2);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public String getName() {
129129
* progress, returns null, if file update is in progress returns last fully downloaded model.
130130
*/
131131
@Nullable
132-
public File getFile() throws FirebaseMlException {
132+
public File getFile() {
133133
return getFile(ModelFileDownloadService.getInstance());
134134
}
135135

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import androidx.annotation.IntDef;
1818
import androidx.annotation.NonNull;
19-
import androidx.annotation.Nullable;
2019
import com.google.android.gms.common.internal.Preconditions;
2120
import com.google.firebase.FirebaseException;
2221
import java.lang.annotation.Retention;
@@ -84,7 +83,6 @@ public class FirebaseMlException extends FirebaseException {
8483
* Internal errors. Means some invariants expected by underlying system has been broken. If you
8584
* see one of these errors, something is very broken.
8685
*/
87-
// annz used
8886
public static final int INTERNAL = 13;
8987

9088
/**
@@ -101,9 +99,17 @@ public class FirebaseMlException extends FirebaseException {
10199
// ===============================================================================================
102100
// Error codes: 100 to 149 reserved for errors during model downloading/loading.
103101
/** There is not enough space left on the device. */
104-
// annz used
105102
public static final int NOT_ENOUGH_SPACE = 101;
106103

104+
/** The downloaded model's hash doesn't match the expected value. */
105+
public static final int MODEL_HASH_MISMATCH = 102;
106+
107+
/**
108+
* These download url expired before download could complete. Usually, multiple download attempt
109+
* will be performed before this is returned.
110+
*/
111+
public static final int DOWNLOAD_URL_EXPIRED = 121;
112+
107113
/**
108114
* The set of Firebase ML status codes. The codes are based on <a
109115
* href="https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto">Canonical
@@ -125,7 +131,9 @@ public class FirebaseMlException extends FirebaseException {
125131
INTERNAL,
126132
UNAVAILABLE,
127133
UNAUTHENTICATED,
128-
NOT_ENOUGH_SPACE
134+
NOT_ENOUGH_SPACE,
135+
MODEL_HASH_MISMATCH,
136+
DOWNLOAD_URL_EXPIRED
129137
})
130138
@Retention(RetentionPolicy.CLASS)
131139
public @interface Code {}
@@ -138,13 +146,6 @@ public FirebaseMlException(@NonNull String detailMessage, @Code int code) {
138146
this.code = code;
139147
}
140148

141-
/** @hide */
142-
public FirebaseMlException(
143-
@NonNull String detailMessage, @Code int code, @Nullable Throwable cause) {
144-
super(Preconditions.checkNotEmpty(detailMessage, "Provided message must not be empty."), cause);
145-
this.code = code;
146-
}
147-
148149
/** Gets the error code for the Firebase ML operation that failed. */
149150
@Code
150151
public int getCode() {

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

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
package com.google.firebase.ml.modeldownloader;
1515

1616
import android.os.Build.VERSION_CODES;
17+
import android.util.Log;
1718
import androidx.annotation.NonNull;
1819
import androidx.annotation.Nullable;
1920
import androidx.annotation.RequiresApi;
2021
import androidx.annotation.VisibleForTesting;
21-
import com.google.android.datatransport.TransportFactory;
2222
import com.google.android.gms.common.internal.Preconditions;
2323
import com.google.android.gms.tasks.Task;
2424
import com.google.android.gms.tasks.TaskCompletionSource;
@@ -40,6 +40,7 @@
4040

4141
public class FirebaseModelDownloader {
4242

43+
private static final String TAG = "FirebaseModelDownld";
4344
private final FirebaseOptions firebaseOptions;
4445
private final SharedPreferencesUtil sharedPreferencesUtil;
4546
private final ModelFileDownloadService fileDownloadService;
@@ -51,15 +52,13 @@ public class FirebaseModelDownloader {
5152

5253
@RequiresApi(api = VERSION_CODES.KITKAT)
5354
FirebaseModelDownloader(
54-
FirebaseApp firebaseApp,
55-
FirebaseInstallationsApi firebaseInstallationsApi,
56-
TransportFactory transportFactory) {
55+
FirebaseApp firebaseApp, FirebaseInstallationsApi firebaseInstallationsApi) {
5756
this.firebaseOptions = firebaseApp.getOptions();
5857
this.sharedPreferencesUtil = new SharedPreferencesUtil(firebaseApp);
5958
this.eventLogger = FirebaseMlLogger.getInstance();
60-
this.fileDownloadService = new ModelFileDownloadService(firebaseApp, transportFactory);
59+
this.fileDownloadService = new ModelFileDownloadService(firebaseApp);
6160
this.modelDownloadService =
62-
new CustomModelDownloadService(firebaseApp, firebaseInstallationsApi, transportFactory);
61+
new CustomModelDownloadService(firebaseApp, firebaseInstallationsApi);
6362

6463
this.executor = Executors.newSingleThreadExecutor();
6564
fileManager = ModelFileManager.getInstance();
@@ -250,7 +249,7 @@ private Task<CustomModel> getCustomModelTask(
250249
CustomModel currentModel = sharedPreferencesUtil.getCustomModelDetails(modelName);
251250

252251
if (currentModel == null && modelHash != null) {
253-
// todo(annzimmer) log something about mismatched state and use hash = null
252+
Log.d(TAG, "Model hash provided but no current model; triggering fresh download.");
254253
modelHash = null;
255254
}
256255

@@ -273,7 +272,7 @@ private Task<CustomModel> getCustomModelTask(
273272
return getCompletedLocalCustomModelTask(updatedModel);
274273
}
275274
// clean up model internally
276-
deleteModelDetails(currentModel.getName());
275+
deleteModelDetails(modelName);
277276
return Tasks.forException(
278277
new FirebaseMlException(
279278
"Possible caching issues: no model associated with " + modelName + ".",
@@ -308,16 +307,34 @@ && new File(currentModel.getLocalFilePath()).exists()) {
308307
if (currentModel.getDownloadId() != 0) {
309308
CustomModel downloadingModel =
310309
sharedPreferencesUtil.getDownloadingCustomModelDetails(modelName);
311-
if (downloadingModel != null
312-
&& downloadingModel
313-
.getModelHash()
314-
.equals(incomingModelDetails.getResult().getModelHash())) {
315-
return Tasks.forResult(downloadingModel);
310+
if (downloadingModel != null) {
311+
if (downloadingModel
312+
.getModelHash()
313+
.equals(incomingModelDetails.getResult().getModelHash())) {
314+
return Tasks.forResult(downloadingModel);
315+
}
316+
Log.d(
317+
TAG, "Hash does not match with expected: " + downloadingModel.getModelHash());
318+
// Note we log "DownloadStatus.SUCCEEDED" because the model file's download itself
319+
// succeeded. Just the hash validation failed.
320+
eventLogger.logDownloadEventWithErrorCode(
321+
downloadingModel,
322+
true,
323+
DownloadStatus.SUCCEEDED,
324+
ErrorCode.MODEL_HASH_MISMATCH);
325+
return Tasks.forException(
326+
new FirebaseMlException(
327+
"Hash does not match with expected",
328+
FirebaseMlException.MODEL_HASH_MISMATCH));
316329
}
317-
// todo(annzimmer) this shouldn't happen unless they are calling the sdk with
318-
// multiple
319-
// sets of download types/conditions.
320-
// this should be a download in progress - add appropriate handling.
330+
Log.d(TAG, "Download details missing for model");
331+
// Note we log "DownloadStatus.SUCCEEDED" because the model file's download itself
332+
// succeeded. Just the file copy failed.
333+
eventLogger.logDownloadEventWithErrorCode(
334+
downloadingModel, true, DownloadStatus.SUCCEEDED, ErrorCode.DOWNLOAD_FAILED);
335+
return Tasks.forException(
336+
new FirebaseMlException(
337+
"Download details missing for model", FirebaseMlException.INTERNAL));
321338
}
322339
}
323340

@@ -343,7 +360,9 @@ private Task<CustomModel> retryExpiredUrlDownload(
343360
@Nullable CustomModelDownloadConditions conditions,
344361
Task<Void> downloadTask,
345362
int retryCounter) {
346-
if (downloadTask.getException().getMessage().contains("Retry: Expired URL")) {
363+
if (downloadTask.getException() instanceof FirebaseMlException
364+
&& ((FirebaseMlException) downloadTask.getException()).getCode()
365+
== FirebaseMlException.DOWNLOAD_URL_EXPIRED) {
347366
// this is likely an expired url - retry.
348367
Task<CustomModel> retryModelDetails =
349368
modelDownloadService.getNewDownloadUrlWithExpiry(
@@ -367,13 +386,18 @@ private Task<CustomModel> retryExpiredUrlDownload(
367386
modelName, conditions, downloadTask, retryCounter - 1);
368387
}
369388
return Tasks.forException(
370-
new Exception("File download failed. Too many attempts."));
389+
new FirebaseMlException(
390+
"File download failed after multiple attempts, possible expired url.",
391+
FirebaseMlException.DOWNLOAD_URL_EXPIRED));
371392
});
372393
}
373394
return Tasks.forException(retryModelDetailTask.getException());
374395
});
396+
} else if (downloadTask.getException() instanceof FirebaseMlException) {
397+
return Tasks.forException(downloadTask.getException());
375398
}
376-
return Tasks.forException(new Exception("File download failed."));
399+
return Tasks.forException(
400+
new FirebaseMlException("File download failed.", FirebaseMlException.INTERNAL));
377401
}
378402

379403
private Task<CustomModel> finishModelDownload(@NonNull String modelName) {

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,11 @@ public List<Component<?>> getComponents() {
4747
return Arrays.asList(
4848
Component.builder(FirebaseModelDownloader.class)
4949
.add(Dependency.required(FirebaseApp.class))
50-
.add(Dependency.required(TransportFactory.class))
5150
.add(Dependency.required(FirebaseInstallationsApi.class))
5251
.factory(
5352
c ->
5453
new FirebaseModelDownloader(
55-
c.get(FirebaseApp.class),
56-
c.get(FirebaseInstallationsApi.class),
57-
c.get(TransportFactory.class)))
54+
c.get(FirebaseApp.class), c.get(FirebaseInstallationsApi.class)))
5855
.build(),
5956
Component.builder(SharedPreferencesUtil.class)
6057
.add(Dependency.required(FirebaseApp.class))
@@ -77,22 +74,15 @@ public List<Component<?>> getComponents() {
7774
.build(),
7875
Component.builder(ModelFileDownloadService.class)
7976
.add(Dependency.required(FirebaseApp.class))
80-
.add(Dependency.required(TransportFactory.class))
81-
.factory(
82-
c ->
83-
new ModelFileDownloadService(
84-
c.get(FirebaseApp.class), c.get(TransportFactory.class)))
77+
.factory(c -> new ModelFileDownloadService(c.get(FirebaseApp.class)))
8578
.build(),
8679
Component.builder(CustomModelDownloadService.class)
8780
.add(Dependency.required(FirebaseApp.class))
88-
.add(Dependency.required(TransportFactory.class))
8981
.add(Dependency.required(FirebaseInstallationsApi.class))
9082
.factory(
9183
c ->
9284
new CustomModelDownloadService(
93-
c.get(FirebaseApp.class),
94-
c.get(FirebaseInstallationsApi.class),
95-
c.get(TransportFactory.class)))
85+
c.get(FirebaseApp.class), c.get(FirebaseInstallationsApi.class)))
9686
.build(),
9787
LibraryVersionComponent.create("firebase-ml-modeldownloader", BuildConfig.VERSION_NAME));
9888
}

0 commit comments

Comments
 (0)