Skip to content

Commit 2c4c19b

Browse files
authored
Logging on-device + Firelog (#7386)
* Restores ML Pods after M77. * Fix Package.swift * Re-add catalyst to GHA workflow. * Add new error type for expired url + fix tests. * On-device logging + updates to tests. * Add new error type for expired url + fix tests. * On-device logging + updates to tests. * Revert to enum for ModelFileManager.swift * Remove GoogleService-Info.plist * Remove GoogleService-Info.plist
1 parent a5f6ded commit 2c4c19b

File tree

7 files changed

+240
-39
lines changed

7 files changed

+240
-39
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ FirebaseSegmentation/Tests/Sample/GoogleService-Info.plist
3636

3737
# FirebaseMLModelDownloader integration tests GoogleService-Info.plist
3838
FirebaseMLModelDownloader/Tests/Integration/Resources/GoogleService-Info.plist
39+
FirebaseMLModelDownloader/Apps/Sample/Resources/GoogleService-Info.plist
3940

4041
# FirebasePerformance dev test App and integration tests GoogleService-Info.plist
4142
FirebasePerformance/**/GoogleService-Info.plist

FirebaseMLModelDownloader/Sources/DeviceLogger.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,28 @@ import Foundation
2323
// TODO: Create list of all possible messages with code - according to format.
2424
enum LoggerMessageCode: Int {
2525
case modelDownloaded = 1
26-
case downloadedModelMovedToURL
26+
case downloadedModelFileSaved
27+
case downloadedModelInfoSaved
28+
case downloaderInstanceCreated
29+
case downloaderInstanceRetrieved
30+
case downloaderInstanceDeleted
31+
case localModelFound
32+
case backgroundModelDownloaded
33+
case modelNameParseError
34+
case localModelInfoRetrievalError
35+
case outdatedModelPathError
36+
case allLocalModelsFound
37+
case listModelsError
38+
case modelNotFound
39+
case modelDeleted
40+
case invalidOptions
41+
case retryDownload
42+
case anotherDownloadInProgressError
43+
case validModelDownloadResponse
44+
case hostnameError
45+
case invalidDownloadSessionError
46+
case invalidResponseError
47+
case modelDownloadError
2748
case downloadedModelSaveError
2849
case analyticsEventEncodeError
2950
case telemetryInitError

FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ extension ModelDownloadTask {
6262
}
6363

6464
func download(progressHandler: ProgressHandler?, completion: @escaping Completion) {
65+
/// Prevent multiple concurrent downloads.
66+
guard downloadStatus == .notStarted else {
67+
completion(.failure(.internalError(description: ModelDownloadTask.ErrorDescription
68+
.anotherDownloadInProgress)))
69+
DeviceLogger.logEvent(level: .debug,
70+
message: ModelDownloadTask.ErrorDescription.anotherDownloadInProgress,
71+
messageCode: .anotherDownloadInProgressError)
72+
return
73+
}
6574
downloader.downloadFile(with: remoteModelInfo.downloadURL,
6675
progressHandler: { downloadedBytes, totalBytes in
6776
/// Fraction of model file downloaded.
@@ -70,6 +79,10 @@ extension ModelDownloadTask {
7079
}) { result in
7180
switch result {
7281
case let .success(response):
82+
DeviceLogger.logEvent(level: .debug,
83+
message: ModelDownloadTask.DebugDescription
84+
.receivedServerResponse,
85+
messageCode: .validModelDownloadResponse)
7386
self.handleResponse(
7487
response: response.urlResponse,
7588
tempURL: response.fileURL,
@@ -79,20 +92,31 @@ extension ModelDownloadTask {
7992
var downloadError: DownloadError
8093
switch error {
8194
case let FileDownloaderError.networkError(error):
82-
downloadError = .internalError(description: ModelDownloadTask
83-
.ErrorDescription
84-
.invalidHostName(error
85-
.localizedDescription))
95+
let description = ModelDownloadTask.ErrorDescription
96+
.invalidHostName(error.localizedDescription)
97+
downloadError = .internalError(description: description)
98+
DeviceLogger.logEvent(level: .debug,
99+
message: description,
100+
messageCode: .hostnameError)
86101
// TODO: Handle this case better.
87102
case FileDownloaderError.sessionInvalidated:
88103
downloadError = .failedPrecondition
104+
DeviceLogger.logEvent(level: .debug,
105+
message: ModelDownloadTask.ErrorDescription.sessionInvalidated,
106+
messageCode: .invalidDownloadSessionError)
89107
case FileDownloaderError.unexpectedResponseType:
90-
downloadError = .internalError(description: ModelDownloadTask
91-
.ErrorDescription.invalidServerResponse)
108+
let description = ModelDownloadTask.ErrorDescription.invalidServerResponse
109+
downloadError = .internalError(description: description)
110+
DeviceLogger.logEvent(level: .debug,
111+
message: description,
112+
messageCode: .invalidResponseError)
92113

93114
default:
94-
downloadError = .internalError(description: ModelDownloadTask.ErrorDescription
95-
.unknownDownloadError)
115+
let description = ModelDownloadTask.ErrorDescription.unknownDownloadError
116+
downloadError = .internalError(description: description)
117+
DeviceLogger.logEvent(level: .debug,
118+
message: description,
119+
messageCode: .modelDownloadError)
96120
}
97121
completion(.failure(downloadError))
98122
}
@@ -104,9 +128,14 @@ extension ModelDownloadTask {
104128
guard (200 ..< 299).contains(response.statusCode) else {
105129
/// Possible failure due to download URL expiry.
106130
if response.statusCode == 400 {
107-
completion(.failure(.failedPrecondition))
131+
completion(.failure(.expiredDownloadURL))
108132
return
109133
}
134+
let description = ModelDownloadTask.ErrorDescription.modelDownloadFailed(response.statusCode)
135+
DeviceLogger.logEvent(level: .debug,
136+
message: description,
137+
messageCode: .modelDownloadError)
138+
completion(.failure(.internalError(description: description)))
110139
return
111140
}
112141

@@ -117,10 +146,16 @@ extension ModelDownloadTask {
117146

118147
do {
119148
try ModelFileManager.moveFile(at: tempURL, to: modelFileURL)
149+
DeviceLogger.logEvent(level: .debug,
150+
message: ModelDownloadTask.DebugDescription.savedModelFile,
151+
messageCode: .downloadedModelFileSaved)
120152
/// Generate local model info.
121153
let localModelInfo = LocalModelInfo(from: remoteModelInfo, path: modelFileURL.absoluteString)
122154
/// Write model to user defaults.
123155
localModelInfo.writeToDefaults(defaults, appName: appName)
156+
DeviceLogger.logEvent(level: .debug,
157+
message: ModelDownloadTask.DebugDescription.savedLocalModelInfo,
158+
messageCode: .downloadedModelInfoSaved)
124159
/// Build model from model info.
125160
let model = CustomModel(localModelInfo: localModelInfo)
126161
downloadStatus = .successful
@@ -154,7 +189,9 @@ extension ModelDownloadTask {
154189
extension ModelDownloadTask {
155190
/// Debug descriptions.
156191
private enum DebugDescription {
157-
static let modelSaved = "Model saved successfully to device."
192+
static let savedModelFile = "Model file saved successfully to device."
193+
static let savedLocalModelInfo = "Downloaded model info saved successfully to user defaults."
194+
static let receivedServerResponse = "Received a valid response from server."
158195
}
159196

160197
/// Error descriptions.
@@ -163,10 +200,16 @@ extension ModelDownloadTask {
163200
"Unable to resolve hostname or connect to host: \(error)"
164201
}
165202

203+
static let modelDownloadFailed = { (code: Int) in
204+
"Model download failed with HTTP error code: \(code)"
205+
}
206+
207+
static let sessionInvalidated = "Session invalidated due to failed pre-conditions."
166208
static let invalidServerResponse =
167-
"Could not get server response for model downloading."
209+
"Could not get valid server response for model downloading."
168210
static let unknownDownloadError = "Unable to download model due to unknown error."
169211
static let saveModel = "Unable to save downloaded remote model file."
170212
static let expiredModelInfo = "Unable to update expired model info."
213+
static let anotherDownloadInProgress = "Download already in progress."
171214
}
172215
}

0 commit comments

Comments
 (0)