diff --git a/FirebaseMLModelDownloader.podspec b/FirebaseMLModelDownloader.podspec index 43ff8608fef..c4dc0e29f23 100644 --- a/FirebaseMLModelDownloader.podspec +++ b/FirebaseMLModelDownloader.podspec @@ -39,12 +39,9 @@ Pod::Spec.new do |s| s.dependency 'FirebaseCore', '~> 12.8.0' s.dependency 'FirebaseCoreExtension', '~> 12.8.0' s.dependency 'FirebaseInstallations', '~> 12.8.0' - s.dependency 'GoogleDataTransport', '~> 10.1' s.dependency 'GoogleUtilities/UserDefaults', '~> 8.1' - s.dependency 'SwiftProtobuf', '~> 1.19' s.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'FIRMLModelDownloader_VERSION=' + s.version.to_s, 'OTHER_CFLAGS' => '-fno-autolink', } diff --git a/FirebaseMLModelDownloader/CHANGELOG.md b/FirebaseMLModelDownloader/CHANGELOG.md new file mode 100644 index 00000000000..171f744d453 --- /dev/null +++ b/FirebaseMLModelDownloader/CHANGELOG.md @@ -0,0 +1,2 @@ +# 12.8.0 +- [fixed] Remove unused legacy telemetry along with the large swift-protobuf dependency. diff --git a/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift b/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift index ef30f1aa70a..1132d49143c 100644 --- a/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift +++ b/FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift @@ -36,9 +36,6 @@ class ModelDownloadTask { /// Downloader instance. private let downloader: FileDownloader - /// Telemetry logger. - private let telemetryLogger: TelemetryLogger? - /// Download progress handler. typealias ProgressHandler = (Float) -> Void private var progressHandler: ProgressHandler? @@ -52,15 +49,13 @@ class ModelDownloadTask { defaults: GULUserDefaults, downloader: FileDownloader, progressHandler: ProgressHandler? = nil, - completion: @escaping Completion, - telemetryLogger: TelemetryLogger? = nil) { + completion: @escaping Completion) { self.remoteModelInfo = remoteModelInfo self.appName = appName self.defaults = defaults self.downloader = downloader self.progressHandler = progressHandler self.completion = completion - self.telemetryLogger = telemetryLogger } } @@ -96,23 +91,9 @@ extension ModelDownloadTask { DeviceLogger.logEvent(level: .debug, message: ModelDownloadTask.ErrorDescription.anotherDownloadInProgress, messageCode: .anotherDownloadInProgressError) - telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload, - status: .failed, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .downloadFailed) return } downloadStatus = .downloading - telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload, - status: .downloading, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .noError) downloader.downloadFile(with: remoteModelInfo.downloadURL, progressHandler: { downloadedBytes, totalBytes in /// Fraction of model file downloaded. @@ -141,45 +122,18 @@ extension ModelDownloadTask { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .hostnameError) - self.telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: self.remoteModelInfo.name, - size: self.remoteModelInfo.size, - path: "", - hash: self.remoteModelInfo.modelHash), - downloadErrorCode: .noConnection - ) case FileDownloaderError.unexpectedResponseType: let description = ModelDownloadTask.ErrorDescription.invalidHTTPResponse downloadError = .internalError(description: description) DeviceLogger.logEvent(level: .debug, message: description, messageCode: .invalidHTTPResponse) - self.telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: self.remoteModelInfo.name, - size: self.remoteModelInfo.size, - path: "", - hash: self.remoteModelInfo.modelHash), - downloadErrorCode: .downloadFailed - ) default: let description = ModelDownloadTask.ErrorDescription.unknownDownloadError downloadError = .internalError(description: description) DeviceLogger.logEvent(level: .debug, message: description, messageCode: .modelDownloadError) - self.telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: self.remoteModelInfo.name, - size: self.remoteModelInfo.size, - path: "", - hash: self.remoteModelInfo.modelHash), - downloadErrorCode: .downloadFailed - ) } self.completion(.failure(downloadError)) } @@ -197,59 +151,23 @@ extension ModelDownloadTask { message: ModelDownloadTask.ErrorDescription .invalidArgument(remoteModelInfo.name), messageCode: .invalidArgument) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .httpError(code: response.statusCode) - ) completion(.failure(.invalidArgument)) return } DeviceLogger.logEvent(level: .debug, message: ModelDownloadTask.ErrorDescription.expiredModelInfo, messageCode: .expiredModelInfo) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .urlExpired - ) completion(.failure(.expiredDownloadURL)) case 401, 403: DeviceLogger.logEvent(level: .debug, message: ModelDownloadTask.ErrorDescription.permissionDenied, messageCode: .permissionDenied) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .httpError(code: response.statusCode) - ) completion(.failure(.permissionDenied)) case 404: DeviceLogger.logEvent(level: .debug, message: ModelDownloadTask.ErrorDescription .modelNotFound(remoteModelInfo.name), messageCode: .modelNotFound) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .httpError(code: response.statusCode) - ) completion(.failure(.notFound)) default: let description = ModelDownloadTask.ErrorDescription @@ -257,15 +175,6 @@ extension ModelDownloadTask { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .modelDownloadError) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .httpError(code: response.statusCode) - ) completion(.failure(.internalError(description: description))) } return @@ -282,13 +191,6 @@ extension ModelDownloadTask { message: description, messageCode: .downloadedModelSaveError) // Downloading the file succeeding but saving failed. - telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload, - status: .succeeded, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .downloadFailed) completion(.failure(.internalError(description: description))) return } @@ -325,12 +227,6 @@ extension ModelDownloadTask { DeviceLogger.logEvent(level: .debug, message: ModelDownloadTask.DebugDescription.modelDownloaded, messageCode: .modelDownloaded) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .succeeded, - model: model, - downloadErrorCode: .noError - ) completion(.success(model)) } catch let error as DownloadError { if error == .notEnoughSpace { @@ -343,13 +239,6 @@ extension ModelDownloadTask { messageCode: .downloadedModelSaveError) } // Downloading the file succeeding but saving failed. - telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload, - status: .succeeded, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .downloadFailed) completion(.failure(error)) return } catch { @@ -357,13 +246,6 @@ extension ModelDownloadTask { message: ModelDownloadTask.ErrorDescription.modelSaveError, messageCode: .downloadedModelSaveError) // Downloading the file succeeding but saving failed. - telemetryLogger?.logModelDownloadEvent(eventName: .modelDownload, - status: .succeeded, - model: CustomModel(name: remoteModelInfo.name, - size: remoteModelInfo.size, - path: "", - hash: remoteModelInfo.modelHash), - downloadErrorCode: .downloadFailed) completion(.failure(.internalError(description: error.localizedDescription))) return } diff --git a/FirebaseMLModelDownloader/Sources/ModelDownloader.swift b/FirebaseMLModelDownloader/Sources/ModelDownloader.swift index 3241f50e317..98805edfc9e 100644 --- a/FirebaseMLModelDownloader/Sources/ModelDownloader.swift +++ b/FirebaseMLModelDownloader/Sources/ModelDownloader.swift @@ -48,9 +48,6 @@ public class ModelDownloader { /// User defaults for model info. private let userDefaults: GULUserDefaults - /// Telemetry logger tied to this instance of model downloader. - let telemetryLogger: TelemetryLogger? - /// Number of retries in case of model download URL expiry. var numberOfRetries: Int = 1 @@ -77,8 +74,6 @@ public class ModelDownloader { options = app.options installations = Installations.installations(app: app) userDefaults = defaults - // Respect Firebase-wide data collection setting. - telemetryLogger = TelemetryLogger(app: app) // Notification of app deletion. let notificationName = "FIRAppDeleteNotification" NotificationCenter.default.addObserver( @@ -170,12 +165,6 @@ public class ModelDownloader { message: ModelDownloader.DebugDescription.localModelFound, messageCode: .localModelFound) asyncOnMainQueue(completion(.success(localModel))) - telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .scheduled, - model: CustomModel(name: modelName, size: 0, path: "", hash: ""), - downloadErrorCode: .noError - ) // Update local model in the background. DispatchQueue.global(qos: .utility).async { [weak self] in self?.getRemoteModel( @@ -184,28 +173,16 @@ public class ModelDownloader { progressHandler: nil, completion: { result in switch result { - case let .success(model): + case .success: DeviceLogger.logEvent(level: .debug, message: ModelDownloader.DebugDescription .backgroundModelDownloaded, messageCode: .backgroundModelDownloaded) - self?.telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .succeeded, - model: model, - downloadErrorCode: .noError - ) case .failure: DeviceLogger.logEvent(level: .debug, message: ModelDownloader.ErrorDescription .backgroundModelDownload, messageCode: .backgroundDownloadError) - self?.telemetryLogger?.logModelDownloadEvent( - eventName: .modelDownload, - status: .failed, - model: CustomModel(name: modelName, size: 0, path: "", hash: ""), - downloadErrorCode: .downloadFailed - ) } } ) @@ -323,28 +300,16 @@ public class ModelDownloader { DeviceLogger.logEvent(level: .debug, message: ModelDownloader.DebugDescription.modelDeleted, messageCode: .modelDeleted) - telemetryLogger?.logModelDeletedEvent( - eventName: .remoteModelDeleteOnDevice, - isSuccessful: true - ) asyncOnMainQueue(completion(.success(()))) } catch let error as DownloadedModelError { DeviceLogger.logEvent(level: .debug, message: ModelDownloader.ErrorDescription.modelDeletionFailed(error), messageCode: .modelDeletionFailed) - telemetryLogger?.logModelDeletedEvent( - eventName: .remoteModelDeleteOnDevice, - isSuccessful: false - ) asyncOnMainQueue(completion(.failure(error))) } catch { DeviceLogger.logEvent(level: .debug, message: ModelDownloader.ErrorDescription.modelDeletionFailed(error), messageCode: .modelDeletionFailed) - telemetryLogger?.logModelDeletedEvent( - eventName: .remoteModelDeleteOnDevice, - isSuccessful: false - ) asyncOnMainQueue(completion(.failure(.internalError(description: error .localizedDescription)))) } @@ -408,8 +373,7 @@ extension ModelDownloader { projectID: projectID, apiKey: apiKey, appName: appName, installations: installations, - localModelInfo: localModelInfo, - telemetryLogger: telemetryLogger + localModelInfo: localModelInfo ) let downloader = ModelFileDownloader(conditions: conditions) downloadInfoAndModel( @@ -512,8 +476,7 @@ extension ModelDownloader { defaults: self.userDefaults, downloader: downloader, progressHandler: taskProgressHandler, - completion: taskCompletion, - telemetryLogger: self.telemetryLogger + completion: taskCompletion ) // Keep track of current download task to allow for merging duplicate requests. self.currentDownloadTask[modelName] = downloadTask diff --git a/FirebaseMLModelDownloader/Sources/ModelInfoRetriever.swift b/FirebaseMLModelDownloader/Sources/ModelInfoRetriever.swift index 12d26f1ed4f..ceb12c928cb 100644 --- a/FirebaseMLModelDownloader/Sources/ModelInfoRetriever.swift +++ b/FirebaseMLModelDownloader/Sources/ModelInfoRetriever.swift @@ -78,9 +78,6 @@ class ModelInfoRetriever { /// Local model info to validate model freshness. private let localModelInfo: LocalModelInfo? - /// Telemetry logger. - private let telemetryLogger: TelemetryLogger? - /// Associate model info retriever with current Firebase app, and model name. init(modelName: String, projectID: String, @@ -88,8 +85,7 @@ class ModelInfoRetriever { appName: String, authTokenProvider: @escaping AuthTokenProvider, session: ModelInfoRetrieverSession? = nil, - localModelInfo: LocalModelInfo? = nil, - telemetryLogger: TelemetryLogger? = nil) { + localModelInfo: LocalModelInfo? = nil) { self.modelName = modelName self.projectID = projectID self.apiKey = apiKey @@ -97,7 +93,6 @@ class ModelInfoRetriever { self.authTokenProvider = authTokenProvider self.session = session ?? URLSession(configuration: .ephemeral) self.localModelInfo = localModelInfo - self.telemetryLogger = telemetryLogger } /// Convenience init to use FirebaseInstallations as auth token provider. @@ -107,16 +102,14 @@ class ModelInfoRetriever { appName: String, installations: Installations, session: ModelInfoRetrieverSession? = nil, - localModelInfo: LocalModelInfo? = nil, - telemetryLogger: TelemetryLogger? = nil) { + localModelInfo: LocalModelInfo? = nil) { self.init(modelName: modelName, projectID: projectID, apiKey: apiKey, appName: appName, authTokenProvider: ModelInfoRetriever.authTokenProvider(installation: installations), session: session, - localModelInfo: localModelInfo, - telemetryLogger: telemetryLogger) + localModelInfo: localModelInfo) } /// Auth token provider to validate credentials. @@ -151,13 +144,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .invalidModelInfoFetchURL, messageCode: .invalidModelInfoFetchURL) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel(name: self.modelName, - size: 0, - path: "", - hash: ""), - modelInfoErrorCode: .connectionFailed) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .invalidModelInfoFetchURL))) return @@ -171,15 +157,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .modelInfoRetrievalError) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .connectionFailed) completion(.failure(.internalError(description: description))) } else { guard let httpResponse = response as? HTTPURLResponse else { @@ -187,15 +164,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .invalidHTTPResponse, messageCode: .invalidHTTPResponse) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .connectionFailed) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .invalidHTTPResponse))) return @@ -211,15 +179,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: ModelInfoRetriever.ErrorDescription.missingModelHash, messageCode: .missingModelHash) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .noHash) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .missingModelHash))) return @@ -229,15 +188,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .invalidHTTPResponse, messageCode: .invalidHTTPResponse) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .unknown) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .invalidHTTPResponse))) return @@ -249,15 +199,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.DebugDescription .modelInfoDownloaded, messageCode: .modelInfoDownloaded) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalSucceeded, - model: CustomModel( - name: self.modelName, - size: modelInfo.size, - path: "", - hash: modelInfo.modelHash - ), - modelInfoErrorCode: .noError) completion(.success(.modelInfo(modelInfo))) } catch { let description = ModelInfoRetriever.ErrorDescription @@ -265,15 +206,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .invalidModelInfoJSON) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .unknown) completion( .failure(.internalError(description: description)) ) @@ -285,15 +217,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .unexpectedModelInfoDeletion, messageCode: .modelInfoDeleted) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .unknown) completion( .failure(.internalError(description: ModelInfoRetriever.ErrorDescription .unexpectedModelInfoDeletion)) @@ -306,15 +229,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .missingModelHash, messageCode: .noModelHash) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .noHash) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .missingModelHash))) return @@ -325,15 +239,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .modelHashMismatch, messageCode: .modelHashMismatchError) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: modelHash - ), - modelInfoErrorCode: .hashMismatch) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .modelHashMismatch))) return @@ -342,15 +247,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.DebugDescription .modelInfoUnmodified, messageCode: .modelInfoUnmodified) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalSucceeded, - model: CustomModel( - name: self.modelName, - size: localInfo.size, - path: "", - hash: localInfo.modelHash - ), - modelInfoErrorCode: .noError) completion(.success(.notModified)) case 400: let errorMessage = self.getErrorFromResponse(data) @@ -359,16 +255,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .invalidArgument) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .httpError(code: httpResponse - .statusCode)) completion(.failure(.invalidArgument)) case 401, 403: // Error could be due to FirebaseML API not enabled for project, or invalid @@ -378,16 +264,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .permissionDenied) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .httpError(code: httpResponse - .statusCode)) completion(.failure(.permissionDenied)) case 404: let errorMessage = self.getErrorFromResponse(data) @@ -396,16 +272,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .modelNotFound) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .httpError(code: httpResponse - .statusCode)) completion(.failure(.notFound)) case 429: let errorMessage = self.getErrorFromResponse(data) @@ -414,16 +280,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .resourceExhausted) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .httpError(code: httpResponse - .statusCode)) completion(.failure(.resourceExhausted)) default: let errorMessage = self.getErrorFromResponse(data) @@ -432,16 +288,6 @@ class ModelInfoRetriever { DeviceLogger.logEvent(level: .debug, message: description, messageCode: .modelInfoRetrievalError) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .httpError(code: httpResponse - .statusCode)) completion(.failure(.internalError(description: description))) } } @@ -452,15 +298,6 @@ class ModelInfoRetriever { message: ModelInfoRetriever.ErrorDescription .authTokenError, messageCode: .authTokenError) - self.telemetryLogger?.logModelInfoRetrievalEvent(eventName: .modelDownload, - status: .modelInfoRetrievalFailed, - model: CustomModel( - name: self.modelName, - size: 0, - path: "", - hash: "" - ), - modelInfoErrorCode: .unknown) completion(.failure(.internalError(description: ModelInfoRetriever.ErrorDescription .authTokenError))) return diff --git a/FirebaseMLModelDownloader/Sources/TelemetryLogger.swift b/FirebaseMLModelDownloader/Sources/TelemetryLogger.swift deleted file mode 100644 index 79b91c8e2d2..00000000000 --- a/FirebaseMLModelDownloader/Sources/TelemetryLogger.swift +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -import FirebaseCore -import Foundation -import GoogleDataTransport - -/// Extension to set Firebase app info. -extension SystemInfo { - mutating func setAppInfo(apiKey: String?, projectID: String?) { - appID = Bundle.main.bundleIdentifier ?? "unknownBundleID" - let appVersionKey = "CFBundleShortVersionString" - appVersion = Bundle.main.infoDictionary?[appVersionKey] as? String ?? "unknownAppVersion" - mlSdkVersion = FirebaseVersion() - self.apiKey = apiKey ?? "unknownAPIKey" - firebaseProjectID = projectID ?? "unknownProjectID" - } -} - -/// Extension to set model info. -extension ModelInfo { - mutating func setModelInfo(modelName: String, modelHash: String) { - name = modelName - if !modelHash.isEmpty { - hash = modelHash - } - modelType = .custom - } -} - -/// Extension to set model options. -extension ModelOptions { - mutating func setModelOptions(modelName: String, modelHash: String) { - var modelInfo = ModelInfo() - modelInfo.setModelInfo(modelName: modelName, modelHash: modelHash) - self.modelInfo = modelInfo - } -} - -/// Extension to build model delete log event. -extension DeleteModelLogEvent { - mutating func setEvent(modelType: ModelInfo.ModelType = .custom, isSuccessful: Bool) { - self.modelType = modelType - self.isSuccessful = isSuccessful - } -} - -/// Extension to build model download log event. -extension ModelDownloadLogEvent { - mutating func setEvent(status: DownloadStatus, errorCode: ErrorCode, - roughDownloadDuration: UInt64? = 0, exactDownloadDuration: UInt64? = 0, - downloadFailureStatus: Int64? = 0, modelOptions: ModelOptions) { - downloadStatus = status - self.errorCode = errorCode - if let roughDownloadDuration { - roughDownloadDurationMs = roughDownloadDuration - } - if let exactDownloadDuration { - exactDownloadDurationMs = exactDownloadDuration - } - if let downloadFailureStatus { - self.downloadFailureStatus = downloadFailureStatus - } - options = modelOptions - } -} - -/// Extension to build log event. -extension FirebaseMlLogEvent { - mutating func setEvent(eventName: EventName, systemInfo: SystemInfo, - modelDownloadLogEvent: ModelDownloadLogEvent) { - self.eventName = eventName - self.systemInfo = systemInfo - self.modelDownloadLogEvent = modelDownloadLogEvent - } - - mutating func setEvent(eventName: EventName, systemInfo: SystemInfo, - deleteModelLogEvent: DeleteModelLogEvent) { - self.eventName = eventName - self.systemInfo = systemInfo - self.deleteModelLogEvent = deleteModelLogEvent - } -} - -/// Data object for Firelog event. -class FBMLDataObject: NSObject, GDTCOREventDataObject { - private let event: FirebaseMlLogEvent - - init(event: FirebaseMlLogEvent) { - self.event = event - } - - /// Encode Firelog event for transport. - func transportBytes() -> Data { - do { - let data = try event.serializedData() - return data - } catch { - DeviceLogger.logEvent(level: .debug, - message: TelemetryLogger.ErrorDescription.encodeEvent, - messageCode: .analyticsEventEncodeError) - return Data() - } - } -} - -/// Firelog logger. -class TelemetryLogger { - /// Mapping ID for the log source. - private let mappingID = "1326" - - /// Current Firebase app. - private let app: FirebaseApp - - /// Transport for Firelog events. - private let cctTransport: GDTCORTransport - - /// Init logger, could be nil if unable to get event transport. - init?(app: FirebaseApp) { - self.app = app - guard let cctTransport = GDTCORTransport( - mappingID: mappingID, - transformers: nil, - target: GDTCORTarget.CCT - ) else { - DeviceLogger.logEvent(level: .debug, - message: TelemetryLogger.ErrorDescription.initTelemetryLogger, - messageCode: .telemetryInitError) - return nil - } - self.cctTransport = cctTransport - } - - /// Log events to Firelog. - private func logModelEvent(event: FirebaseMlLogEvent) { - let eventForTransport: GDTCOREvent = cctTransport.eventForTransport() - eventForTransport.dataObject = FBMLDataObject(event: event) - cctTransport.sendTelemetryEvent(eventForTransport) - } - - /// Log model deleted event to Firelog. - func logModelDeletedEvent(eventName: EventName, isSuccessful: Bool) { - guard app.isDataCollectionDefaultEnabled else { return } - var systemInfo = SystemInfo() - let apiKey = app.options.apiKey - let projectID = app.options.projectID - systemInfo.setAppInfo(apiKey: apiKey, projectID: projectID) - var deleteModelLogEvent = DeleteModelLogEvent() - deleteModelLogEvent.setEvent(isSuccessful: isSuccessful) - var fbmlEvent = FirebaseMlLogEvent() - fbmlEvent.setEvent( - eventName: eventName, - systemInfo: systemInfo, - deleteModelLogEvent: deleteModelLogEvent - ) - logModelEvent(event: fbmlEvent) - } - - /// Log model info retrieval event to Firelog. - func logModelInfoRetrievalEvent(eventName: EventName, - status: ModelDownloadLogEvent.DownloadStatus, - model: CustomModel, - modelInfoErrorCode: ModelInfoErrorCode) { - guard app.isDataCollectionDefaultEnabled else { return } - var systemInfo = SystemInfo() - let apiKey = app.options.apiKey - let projectID = app.options.projectID - systemInfo.setAppInfo(apiKey: apiKey, projectID: projectID) - var errorCode = ErrorCode() - var failureCode: Int64? - switch modelInfoErrorCode { - case .noError: - errorCode = .noError - case .noHash: - errorCode = .modelInfoDownloadNoHash - case .connectionFailed: - errorCode = .modelInfoDownloadConnectionFailed - case .hashMismatch: - errorCode = .modelHashMismatch - case let .httpError(code): - errorCode = .modelInfoDownloadUnsuccessfulHTTPStatus - failureCode = Int64(code) - case .unknown: - errorCode = .unknownError - } - var modelOptions = ModelOptions() - modelOptions.setModelOptions( - modelName: model.name, - modelHash: model.hash - ) - var modelDownloadLogEvent = ModelDownloadLogEvent() - modelDownloadLogEvent.setEvent( - status: status, - errorCode: errorCode, - downloadFailureStatus: failureCode, - modelOptions: modelOptions - ) - var fbmlEvent = FirebaseMlLogEvent() - fbmlEvent.setEvent( - eventName: eventName, - systemInfo: systemInfo, - modelDownloadLogEvent: modelDownloadLogEvent - ) - logModelEvent(event: fbmlEvent) - } - - /// Log model download event to Firelog. - func logModelDownloadEvent(eventName: EventName, - status: ModelDownloadLogEvent.DownloadStatus, - model: CustomModel, - downloadErrorCode: ModelDownloadErrorCode) { - guard app.isDataCollectionDefaultEnabled else { return } - var modelOptions = ModelOptions() - modelOptions.setModelOptions(modelName: model.name, modelHash: model.hash) - var systemInfo = SystemInfo() - let apiKey = app.options.apiKey - let projectID = app.options.projectID - systemInfo.setAppInfo(apiKey: apiKey, projectID: projectID) - - var errorCode = ErrorCode() - var failureCode: Int64? - - switch downloadErrorCode { - case .noError: - errorCode = .noError - case .urlExpired: - errorCode = .uriExpired - case .noConnection: - errorCode = .noNetworkConnection - case .downloadFailed: - errorCode = .downloadFailed - case let .httpError(code): - errorCode = .unknownError - failureCode = Int64(code) - } - - var modelDownloadLogEvent = ModelDownloadLogEvent() - modelDownloadLogEvent.setEvent( - status: status, - errorCode: errorCode, - downloadFailureStatus: failureCode, - modelOptions: modelOptions - ) - - var fbmlEvent = FirebaseMlLogEvent() - fbmlEvent.setEvent( - eventName: eventName, - systemInfo: systemInfo, - modelDownloadLogEvent: modelDownloadLogEvent - ) - logModelEvent(event: fbmlEvent) - } -} - -/// Possible error messages while logging telemetry. -private extension TelemetryLogger { - /// Error descriptions. - enum ErrorDescription { - static let encodeEvent = "Unable to encode event for Firelog." - static let initTelemetryLogger = "Unable to create telemetry logger." - } -} diff --git a/FirebaseMLModelDownloader/Sources/proto/firebase_ml_log_sdk.pb.swift b/FirebaseMLModelDownloader/Sources/proto/firebase_ml_log_sdk.pb.swift deleted file mode 100644 index ff94e2d8db6..00000000000 --- a/FirebaseMLModelDownloader/Sources/proto/firebase_ml_log_sdk.pb.swift +++ /dev/null @@ -1,831 +0,0 @@ -// DO NOT EDIT. -// swift-format-ignore-file -// swiftlint:disable all -// -// Generated by the Swift generator plugin for the protocol buffer compiler. -// Source: firebase_ml_log_sdk.proto -// -// For information on using the generated types, please see the documentation: -// https://github.com/apple/swift-protobuf/ - -// Copyright 2021 Google LLC -// -// 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. - -import SwiftProtobuf - -// If the compiler emits an error on this type, it is because this file -// was generated by a version of the `protoc` Swift plug-in that is -// incompatible with the version of SwiftProtobuf to which you are linking. -// Please ensure that you are building against the same version of the API -// that was used to generate this file. -fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { - struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} - typealias Version = _2 -} - -enum EventName: SwiftProtobuf.Enum, Swift.CaseIterable { - typealias RawValue = Int - case unknownEvent // = 0 - case modelDownload // = 100 - case modelUpdate // = 101 - case remoteModelDeleteOnDevice // = 252 - case UNRECOGNIZED(Int) - - init() { - self = .unknownEvent - } - - init?(rawValue: Int) { - switch rawValue { - case 0: self = .unknownEvent - case 100: self = .modelDownload - case 101: self = .modelUpdate - case 252: self = .remoteModelDeleteOnDevice - default: self = .UNRECOGNIZED(rawValue) - } - } - - var rawValue: Int { - switch self { - case .unknownEvent: return 0 - case .modelDownload: return 100 - case .modelUpdate: return 101 - case .remoteModelDeleteOnDevice: return 252 - case .UNRECOGNIZED(let i): return i - } - } - - // The compiler won't synthesize support with the UNRECOGNIZED case. - static let allCases: [EventName] = [ - .unknownEvent, - .modelDownload, - .modelUpdate, - .remoteModelDeleteOnDevice, - ] - -} - -/// A list of error codes for various components of the system. For model downloading, the -/// range of error codes is 100 to 199. -enum ErrorCode: SwiftProtobuf.Enum, Swift.CaseIterable { - typealias RawValue = Int - - /// No error at all. - case noError // = 0 - - /// The temporary URI to download the model has expired. - case uriExpired // = 101 - - /// There is no network connection when trying to download the model file or - /// the model info. - case noNetworkConnection // = 102 - - /// The download started on a valid condition but didn't finish successfully. - case downloadFailed // = 104 - - /// We received an unsuccessful http status code when trying to download the - /// model info. An unsuccessful http status code is a code that's neither 200 - /// nor 304. See go/firebase-ml-model-hosting-design for a list of possible - /// status codes while downloading the model info. - case modelInfoDownloadUnsuccessfulHTTPStatus // = 105 - - /// Didn't receive a model hash while trying to download the model info. - case modelInfoDownloadNoHash // = 106 - - /// Failed to connect to the Firebase Console while trying to download the - /// model info. - case modelInfoDownloadConnectionFailed // = 107 - - /// Model hash mismatches the expected value. - case modelHashMismatch // = 116 - - /// An unknown error has occurred. This is for conditions that should never - /// happen. But we log them anyways. If there is a surge in UNKNOWN error - /// codes, we need to check our code. - case unknownError // = 9999 - case UNRECOGNIZED(Int) - - init() { - self = .noError - } - - init?(rawValue: Int) { - switch rawValue { - case 0: self = .noError - case 101: self = .uriExpired - case 102: self = .noNetworkConnection - case 104: self = .downloadFailed - case 105: self = .modelInfoDownloadUnsuccessfulHTTPStatus - case 106: self = .modelInfoDownloadNoHash - case 107: self = .modelInfoDownloadConnectionFailed - case 116: self = .modelHashMismatch - case 9999: self = .unknownError - default: self = .UNRECOGNIZED(rawValue) - } - } - - var rawValue: Int { - switch self { - case .noError: return 0 - case .uriExpired: return 101 - case .noNetworkConnection: return 102 - case .downloadFailed: return 104 - case .modelInfoDownloadUnsuccessfulHTTPStatus: return 105 - case .modelInfoDownloadNoHash: return 106 - case .modelInfoDownloadConnectionFailed: return 107 - case .modelHashMismatch: return 116 - case .unknownError: return 9999 - case .UNRECOGNIZED(let i): return i - } - } - - // The compiler won't synthesize support with the UNRECOGNIZED case. - static let allCases: [ErrorCode] = [ - .noError, - .uriExpired, - .noNetworkConnection, - .downloadFailed, - .modelInfoDownloadUnsuccessfulHTTPStatus, - .modelInfoDownloadNoHash, - .modelInfoDownloadConnectionFailed, - .modelHashMismatch, - .unknownError, - ] - -} - -/// Information about various parts of the system: app, Firebase, SDK. -struct SystemInfo: Sendable { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// The application's unique id. On iOS, this is the bundle ID. - var appID: String = String() - - /// Application version string. On iOS, this is "version_number" + "#" + "build_number". - var appVersion: String = String() - - /// Uniquely identifiable id associated with the Firebase project. Might be an - /// empty string if the developer does not pass a correct FirebaseOptions with - /// a valid Firebase Project ID. - var firebaseProjectID: String = String() - - /// Firebase ML SDK version. - var mlSdkVersion: String = String() - - /// The API key of the firebase project. - var apiKey: String = String() - - var unknownFields = SwiftProtobuf.UnknownStorage() - - init() {} -} - -/// Information about models. -struct ModelInfo: Sendable { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// The name of the model defined by the model creator. This string should be - /// meaningful to the creator and describes what the model does. For example, - /// the name can be "mobile vision face recognition" or "speech to text". - var name: String = String() - - /// The version of the model defined by the model creator. - var version: String = String() - - /// The expected checksum (SHA256) of the model file. Only hash of models - /// downloaded from cloud is logged. - var hash: String = String() - - var modelType: ModelInfo.ModelType = .typeUnknown - - var unknownFields = SwiftProtobuf.UnknownStorage() - - /// The model type is currently envisioned to be used mainly for model - /// download/update. - enum ModelType: SwiftProtobuf.Enum, Swift.CaseIterable { - typealias RawValue = Int - case typeUnknown // = 0 - case custom // = 1 - case UNRECOGNIZED(Int) - - init() { - self = .typeUnknown - } - - init?(rawValue: Int) { - switch rawValue { - case 0: self = .typeUnknown - case 1: self = .custom - default: self = .UNRECOGNIZED(rawValue) - } - } - - var rawValue: Int { - switch self { - case .typeUnknown: return 0 - case .custom: return 1 - case .UNRECOGNIZED(let i): return i - } - } - - // The compiler won't synthesize support with the UNRECOGNIZED case. - static let allCases: [ModelInfo.ModelType] = [ - .typeUnknown, - .custom, - ] - - } - - init() {} -} - -/// Detailed information about a model. -/// The message used to be named "CustomModelOptions". -struct ModelOptions: Sendable { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// Inherent properties about the model: name, version, URI, source. - var modelInfo: ModelInfo { - get {return _modelInfo ?? ModelInfo()} - set {_modelInfo = newValue} - } - /// Returns true if `modelInfo` has been explicitly set. - var hasModelInfo: Bool {return self._modelInfo != nil} - /// Clears the value of `modelInfo`. Subsequent reads from it will return its default value. - mutating func clearModelInfo() {self._modelInfo = nil} - - /// True if models can be updated. - var isModelUpdateEnabled: Bool = false - - var unknownFields = SwiftProtobuf.UnknownStorage() - - init() {} - - fileprivate var _modelInfo: ModelInfo? = nil -} - -/// Information about model downloading. A single model download request may -/// result in multiple log entries. "download_status" in the log entry indicates -/// during which stage it is logged. -/// This message used to be named "CustomModelDownloadLogEvent". -struct ModelDownloadLogEvent: Sendable { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// Model information and options for downloading. - var options: ModelOptions { - get {return _options ?? ModelOptions()} - set {_options = newValue} - } - /// Returns true if `options` has been explicitly set. - var hasOptions: Bool {return self._options != nil} - /// Clears the value of `options`. Subsequent reads from it will return its default value. - mutating func clearOptions() {self._options = nil} - - /// The rough duration of the download. This is not marked as - /// ST_SENSITIVE_TIMESTAMP because it is a duration instead of a timestamp. - /// We delegate the download to OS downloader. We may not be notified - /// when the download completes, such as when the app is killed. - var roughDownloadDurationMs: UInt64 = 0 - - /// The error code for model download. - var errorCode: ErrorCode = .noError - - /// The exact duration of the download. This is not marked as - /// ST_SENSITIVE_TIMESTAMP because it is a duration instead of a timestamp. - /// We know the exact duration when the download is completed while the app is - /// still alive and receives the completed notification from OS downloader. - var exactDownloadDurationMs: UInt64 = 0 - - /// The download status. - var downloadStatus: ModelDownloadLogEvent.DownloadStatus = .unknownStatus - - /// If this field is logged for DownloadStatus.MODEL_INFO_RETRIEVAL_FAILED, it - /// is the http status code from the firebase console. See - /// go/firebase-ml-model-hosting-design. Same on both Android and iOS. - /// If this field is logged for DownloadStatus.FAILED, it is the http status - /// code on iOS, and the DownloadManager's "COLUMN_REASON" value on Android. On - /// iOS, the status code can be a negative integer. - var downloadFailureStatus: Int64 = 0 - - var unknownFields = SwiftProtobuf.UnknownStorage() - - /// The download status. The model download is made up of two major stages: the - /// retrieval of the model info in Firebase backend, and then the download of - /// the model file in GCS. Whether or not the download is requested implicitly - /// or explicitly does not affect the later stages of the download. As a - /// result, later stages (i.e. enum tag 3+) do not distinguish between explicit - /// and implicit triggering. - enum DownloadStatus: SwiftProtobuf.Enum, Swift.CaseIterable { - typealias RawValue = Int - case unknownStatus // = 0 - - /// The download is requested by the developer, i.e. ensureModelDownloaded() - /// is called. - case explicitlyRequested // = 1 - - /// The download is requested by the SDK implicitly. - case implicitlyRequested // = 2 - - /// The retrieval of the model info succeeded. - case modelInfoRetrievalSucceeded // = 3 - - /// The retrieval of the model info failed. See error_code field for details. - case modelInfoRetrievalFailed // = 4 - - /// A new download with the OS downloader has been scheduled. - case scheduled // = 5 - - /// There is an existing downloading session. No new download is scheduled. - case downloading // = 6 - - /// The download of the model file succeeded. - case succeeded // = 7 - - /// The download of the model file failed. - case failed // = 8 - - /// Update is enabled and available while the existing model is downloaded or - /// live. - case updateAvailable // = 10 - case UNRECOGNIZED(Int) - - init() { - self = .unknownStatus - } - - init?(rawValue: Int) { - switch rawValue { - case 0: self = .unknownStatus - case 1: self = .explicitlyRequested - case 2: self = .implicitlyRequested - case 3: self = .modelInfoRetrievalSucceeded - case 4: self = .modelInfoRetrievalFailed - case 5: self = .scheduled - case 6: self = .downloading - case 7: self = .succeeded - case 8: self = .failed - case 10: self = .updateAvailable - default: self = .UNRECOGNIZED(rawValue) - } - } - - var rawValue: Int { - switch self { - case .unknownStatus: return 0 - case .explicitlyRequested: return 1 - case .implicitlyRequested: return 2 - case .modelInfoRetrievalSucceeded: return 3 - case .modelInfoRetrievalFailed: return 4 - case .scheduled: return 5 - case .downloading: return 6 - case .succeeded: return 7 - case .failed: return 8 - case .updateAvailable: return 10 - case .UNRECOGNIZED(let i): return i - } - } - - // The compiler won't synthesize support with the UNRECOGNIZED case. - static let allCases: [ModelDownloadLogEvent.DownloadStatus] = [ - .unknownStatus, - .explicitlyRequested, - .implicitlyRequested, - .modelInfoRetrievalSucceeded, - .modelInfoRetrievalFailed, - .scheduled, - .downloading, - .succeeded, - .failed, - .updateAvailable, - ] - - } - - init() {} - - fileprivate var _options: ModelOptions? = nil -} - -/// Information about deleting a downloaded model on device. -struct DeleteModelLogEvent: Sendable { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// The type of the downloaded model requested to be deleted. - var modelType: ModelInfo.ModelType = .typeUnknown - - /// Whether the downloaded model is deleted successfully. - var isSuccessful: Bool = false - - var unknownFields = SwiftProtobuf.UnknownStorage() - - init() {} -} - -/// Main log event for FirebaseMl, that contains individual API events, like model -/// download. -/// NEXT ID: 44. -struct FirebaseMlLogEvent: @unchecked Sendable { - // SwiftProtobuf.Message conformance is added in an extension below. See the - // `Message` and `Message+*Additions` files in the SwiftProtobuf library for - // methods supported on all messages. - - /// Information about various parts of the system: app, Firebase, SDK. - var systemInfo: SystemInfo { - get {return _storage._systemInfo ?? SystemInfo()} - set {_uniqueStorage()._systemInfo = newValue} - } - /// Returns true if `systemInfo` has been explicitly set. - var hasSystemInfo: Bool {return _storage._systemInfo != nil} - /// Clears the value of `systemInfo`. Subsequent reads from it will return its default value. - mutating func clearSystemInfo() {_uniqueStorage()._systemInfo = nil} - - /// The event name. - var eventName: EventName { - get {return _storage._eventName} - set {_uniqueStorage()._eventName = newValue} - } - - /// Information about model download. - var modelDownloadLogEvent: ModelDownloadLogEvent { - get {return _storage._modelDownloadLogEvent ?? ModelDownloadLogEvent()} - set {_uniqueStorage()._modelDownloadLogEvent = newValue} - } - /// Returns true if `modelDownloadLogEvent` has been explicitly set. - var hasModelDownloadLogEvent: Bool {return _storage._modelDownloadLogEvent != nil} - /// Clears the value of `modelDownloadLogEvent`. Subsequent reads from it will return its default value. - mutating func clearModelDownloadLogEvent() {_uniqueStorage()._modelDownloadLogEvent = nil} - - /// Information about deleting a downloaded model. - var deleteModelLogEvent: DeleteModelLogEvent { - get {return _storage._deleteModelLogEvent ?? DeleteModelLogEvent()} - set {_uniqueStorage()._deleteModelLogEvent = newValue} - } - /// Returns true if `deleteModelLogEvent` has been explicitly set. - var hasDeleteModelLogEvent: Bool {return _storage._deleteModelLogEvent != nil} - /// Clears the value of `deleteModelLogEvent`. Subsequent reads from it will return its default value. - mutating func clearDeleteModelLogEvent() {_uniqueStorage()._deleteModelLogEvent = nil} - - var unknownFields = SwiftProtobuf.UnknownStorage() - - init() {} - - fileprivate var _storage = _StorageClass.defaultInstance -} - -// MARK: - Code below here is support for the SwiftProtobuf runtime. - -extension EventName: SwiftProtobuf._ProtoNameProviding { - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0UNKNOWN_EVENT\0\u{2}d\u{1}MODEL_DOWNLOAD\0\u{1}MODEL_UPDATE\0\u{2}W\u{2}REMOTE_MODEL_DELETE_ON_DEVICE\0") -} - -extension ErrorCode: SwiftProtobuf._ProtoNameProviding { - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0NO_ERROR\0\u{2}e\u{1}URI_EXPIRED\0\u{1}NO_NETWORK_CONNECTION\0\u{2}\u{2}DOWNLOAD_FAILED\0\u{1}MODEL_INFO_DOWNLOAD_UNSUCCESSFUL_HTTP_STATUS\0\u{1}MODEL_INFO_DOWNLOAD_NO_HASH\0\u{1}MODEL_INFO_DOWNLOAD_CONNECTION_FAILED\0\u{2}\u{9}MODEL_HASH_MISMATCH\0\u{2}[Z\u{2}UNKNOWN_ERROR\0") -} - -extension SystemInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = "SystemInfo" - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}app_id\0\u{3}app_version\0\u{3}firebase_project_id\0\u{3}ml_sdk_version\0\u{4}\u{3}api_key\0") - - mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularStringField(value: &self.appID) }() - case 2: try { try decoder.decodeSingularStringField(value: &self.appVersion) }() - case 3: try { try decoder.decodeSingularStringField(value: &self.firebaseProjectID) }() - case 4: try { try decoder.decodeSingularStringField(value: &self.mlSdkVersion) }() - case 7: try { try decoder.decodeSingularStringField(value: &self.apiKey) }() - default: break - } - } - } - - func traverse(visitor: inout V) throws { - if !self.appID.isEmpty { - try visitor.visitSingularStringField(value: self.appID, fieldNumber: 1) - } - if !self.appVersion.isEmpty { - try visitor.visitSingularStringField(value: self.appVersion, fieldNumber: 2) - } - if !self.firebaseProjectID.isEmpty { - try visitor.visitSingularStringField(value: self.firebaseProjectID, fieldNumber: 3) - } - if !self.mlSdkVersion.isEmpty { - try visitor.visitSingularStringField(value: self.mlSdkVersion, fieldNumber: 4) - } - if !self.apiKey.isEmpty { - try visitor.visitSingularStringField(value: self.apiKey, fieldNumber: 7) - } - try unknownFields.traverse(visitor: &visitor) - } - - static func ==(lhs: SystemInfo, rhs: SystemInfo) -> Bool { - if lhs.appID != rhs.appID {return false} - if lhs.appVersion != rhs.appVersion {return false} - if lhs.firebaseProjectID != rhs.firebaseProjectID {return false} - if lhs.mlSdkVersion != rhs.mlSdkVersion {return false} - if lhs.apiKey != rhs.apiKey {return false} - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} - -extension ModelInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = "ModelInfo" - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}name\0\u{1}version\0\u{2}\u{3}hash\0\u{3}model_type\0") - - mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularStringField(value: &self.name) }() - case 2: try { try decoder.decodeSingularStringField(value: &self.version) }() - case 5: try { try decoder.decodeSingularStringField(value: &self.hash) }() - case 6: try { try decoder.decodeSingularEnumField(value: &self.modelType) }() - default: break - } - } - } - - func traverse(visitor: inout V) throws { - if !self.name.isEmpty { - try visitor.visitSingularStringField(value: self.name, fieldNumber: 1) - } - if !self.version.isEmpty { - try visitor.visitSingularStringField(value: self.version, fieldNumber: 2) - } - if !self.hash.isEmpty { - try visitor.visitSingularStringField(value: self.hash, fieldNumber: 5) - } - if self.modelType != .typeUnknown { - try visitor.visitSingularEnumField(value: self.modelType, fieldNumber: 6) - } - try unknownFields.traverse(visitor: &visitor) - } - - static func ==(lhs: ModelInfo, rhs: ModelInfo) -> Bool { - if lhs.name != rhs.name {return false} - if lhs.version != rhs.version {return false} - if lhs.hash != rhs.hash {return false} - if lhs.modelType != rhs.modelType {return false} - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} - -extension ModelInfo.ModelType: SwiftProtobuf._ProtoNameProviding { - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0TYPE_UNKNOWN\0\u{1}CUSTOM\0") -} - -extension ModelOptions: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = "ModelOptions" - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}model_info\0\u{4}\u{3}is_model_update_enabled\0") - - mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularMessageField(value: &self._modelInfo) }() - case 4: try { try decoder.decodeSingularBoolField(value: &self.isModelUpdateEnabled) }() - default: break - } - } - } - - func traverse(visitor: inout V) throws { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - try { if let v = self._modelInfo { - try visitor.visitSingularMessageField(value: v, fieldNumber: 1) - } }() - if self.isModelUpdateEnabled != false { - try visitor.visitSingularBoolField(value: self.isModelUpdateEnabled, fieldNumber: 4) - } - try unknownFields.traverse(visitor: &visitor) - } - - static func ==(lhs: ModelOptions, rhs: ModelOptions) -> Bool { - if lhs._modelInfo != rhs._modelInfo {return false} - if lhs.isModelUpdateEnabled != rhs.isModelUpdateEnabled {return false} - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} - -extension ModelDownloadLogEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = "ModelDownloadLogEvent" - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}options\0\u{3}rough_download_duration_ms\0\u{3}error_code\0\u{3}exact_download_duration_ms\0\u{3}download_status\0\u{3}download_failure_status\0") - - mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularMessageField(value: &self._options) }() - case 2: try { try decoder.decodeSingularUInt64Field(value: &self.roughDownloadDurationMs) }() - case 3: try { try decoder.decodeSingularEnumField(value: &self.errorCode) }() - case 4: try { try decoder.decodeSingularUInt64Field(value: &self.exactDownloadDurationMs) }() - case 5: try { try decoder.decodeSingularEnumField(value: &self.downloadStatus) }() - case 6: try { try decoder.decodeSingularInt64Field(value: &self.downloadFailureStatus) }() - default: break - } - } - } - - func traverse(visitor: inout V) throws { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - try { if let v = self._options { - try visitor.visitSingularMessageField(value: v, fieldNumber: 1) - } }() - if self.roughDownloadDurationMs != 0 { - try visitor.visitSingularUInt64Field(value: self.roughDownloadDurationMs, fieldNumber: 2) - } - if self.errorCode != .noError { - try visitor.visitSingularEnumField(value: self.errorCode, fieldNumber: 3) - } - if self.exactDownloadDurationMs != 0 { - try visitor.visitSingularUInt64Field(value: self.exactDownloadDurationMs, fieldNumber: 4) - } - if self.downloadStatus != .unknownStatus { - try visitor.visitSingularEnumField(value: self.downloadStatus, fieldNumber: 5) - } - if self.downloadFailureStatus != 0 { - try visitor.visitSingularInt64Field(value: self.downloadFailureStatus, fieldNumber: 6) - } - try unknownFields.traverse(visitor: &visitor) - } - - static func ==(lhs: ModelDownloadLogEvent, rhs: ModelDownloadLogEvent) -> Bool { - if lhs._options != rhs._options {return false} - if lhs.roughDownloadDurationMs != rhs.roughDownloadDurationMs {return false} - if lhs.errorCode != rhs.errorCode {return false} - if lhs.exactDownloadDurationMs != rhs.exactDownloadDurationMs {return false} - if lhs.downloadStatus != rhs.downloadStatus {return false} - if lhs.downloadFailureStatus != rhs.downloadFailureStatus {return false} - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} - -extension ModelDownloadLogEvent.DownloadStatus: SwiftProtobuf._ProtoNameProviding { - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0UNKNOWN_STATUS\0\u{1}EXPLICITLY_REQUESTED\0\u{1}IMPLICITLY_REQUESTED\0\u{1}MODEL_INFO_RETRIEVAL_SUCCEEDED\0\u{1}MODEL_INFO_RETRIEVAL_FAILED\0\u{1}SCHEDULED\0\u{1}DOWNLOADING\0\u{1}SUCCEEDED\0\u{1}FAILED\0\u{2}\u{2}UPDATE_AVAILABLE\0") -} - -extension DeleteModelLogEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = "DeleteModelLogEvent" - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}model_type\0\u{3}is_successful\0") - - mutating func decodeMessage(decoder: inout D) throws { - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularEnumField(value: &self.modelType) }() - case 2: try { try decoder.decodeSingularBoolField(value: &self.isSuccessful) }() - default: break - } - } - } - - func traverse(visitor: inout V) throws { - if self.modelType != .typeUnknown { - try visitor.visitSingularEnumField(value: self.modelType, fieldNumber: 1) - } - if self.isSuccessful != false { - try visitor.visitSingularBoolField(value: self.isSuccessful, fieldNumber: 2) - } - try unknownFields.traverse(visitor: &visitor) - } - - static func ==(lhs: DeleteModelLogEvent, rhs: DeleteModelLogEvent) -> Bool { - if lhs.modelType != rhs.modelType {return false} - if lhs.isSuccessful != rhs.isSuccessful {return false} - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} - -extension FirebaseMlLogEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - static let protoMessageName: String = "FirebaseMlLogEvent" - static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}system_info\0\u{3}event_name\0\u{3}model_download_log_event\0\u{4}%delete_model_log_event\0") - - fileprivate class _StorageClass { - var _systemInfo: SystemInfo? = nil - var _eventName: EventName = .unknownEvent - var _modelDownloadLogEvent: ModelDownloadLogEvent? = nil - var _deleteModelLogEvent: DeleteModelLogEvent? = nil - - // This property is used as the initial default value for new instances of the type. - // The type itself is protecting the reference to its storage via CoW semantics. - // This will force a copy to be made of this reference when the first mutation occurs; - // hence, it is safe to mark this as `nonisolated(unsafe)`. - static nonisolated(unsafe) let defaultInstance = _StorageClass() - - private init() {} - - init(copying source: _StorageClass) { - _systemInfo = source._systemInfo - _eventName = source._eventName - _modelDownloadLogEvent = source._modelDownloadLogEvent - _deleteModelLogEvent = source._deleteModelLogEvent - } - } - - fileprivate mutating func _uniqueStorage() -> _StorageClass { - if !isKnownUniquelyReferenced(&_storage) { - _storage = _StorageClass(copying: _storage) - } - return _storage - } - - mutating func decodeMessage(decoder: inout D) throws { - _ = _uniqueStorage() - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - while let fieldNumber = try decoder.nextFieldNumber() { - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every case branch when no optimizations are - // enabled. https://github.com/apple/swift-protobuf/issues/1034 - switch fieldNumber { - case 1: try { try decoder.decodeSingularMessageField(value: &_storage._systemInfo) }() - case 2: try { try decoder.decodeSingularEnumField(value: &_storage._eventName) }() - case 3: try { try decoder.decodeSingularMessageField(value: &_storage._modelDownloadLogEvent) }() - case 40: try { try decoder.decodeSingularMessageField(value: &_storage._deleteModelLogEvent) }() - default: break - } - } - } - } - - func traverse(visitor: inout V) throws { - try withExtendedLifetime(_storage) { (_storage: _StorageClass) in - // The use of inline closures is to circumvent an issue where the compiler - // allocates stack space for every if/case branch local when no optimizations - // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and - // https://github.com/apple/swift-protobuf/issues/1182 - try { if let v = _storage._systemInfo { - try visitor.visitSingularMessageField(value: v, fieldNumber: 1) - } }() - if _storage._eventName != .unknownEvent { - try visitor.visitSingularEnumField(value: _storage._eventName, fieldNumber: 2) - } - try { if let v = _storage._modelDownloadLogEvent { - try visitor.visitSingularMessageField(value: v, fieldNumber: 3) - } }() - try { if let v = _storage._deleteModelLogEvent { - try visitor.visitSingularMessageField(value: v, fieldNumber: 40) - } }() - } - try unknownFields.traverse(visitor: &visitor) - } - - static func ==(lhs: FirebaseMlLogEvent, rhs: FirebaseMlLogEvent) -> Bool { - if lhs._storage !== rhs._storage { - let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in - let _storage = _args.0 - let rhs_storage = _args.1 - if _storage._systemInfo != rhs_storage._systemInfo {return false} - if _storage._eventName != rhs_storage._eventName {return false} - if _storage._modelDownloadLogEvent != rhs_storage._modelDownloadLogEvent {return false} - if _storage._deleteModelLogEvent != rhs_storage._deleteModelLogEvent {return false} - return true - } - if !storagesAreEqual {return false} - } - if lhs.unknownFields != rhs.unknownFields {return false} - return true - } -} diff --git a/FirebaseMLModelDownloader/Sources/proto/firebase_ml_log_sdk.proto b/FirebaseMLModelDownloader/Sources/proto/firebase_ml_log_sdk.proto deleted file mode 100644 index 8b91f912d99..00000000000 --- a/FirebaseMLModelDownloader/Sources/proto/firebase_ml_log_sdk.proto +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -syntax = "proto3"; - -// This is a slimmed down version of our internal logging proto used only for -// testing, to valid that the incoming json will convert as expected! -// All numbers and naming should be kept consistent with the internal proto. - -// Information about various parts of the system: app, Firebase, SDK. -message SystemInfo { - // The application's unique id. On iOS, this is the bundle ID. - string app_id = 1 ; - - // Application version string. On iOS, this is "version_number" + "#" + "build_number". - string app_version = 2; - - // Uniquely identifiable id associated with the Firebase project. Might be an - // empty string if the developer does not pass a correct FirebaseOptions with - // a valid Firebase Project ID. - string firebase_project_id = 3; - - // Firebase ML SDK version. - string ml_sdk_version = 4; - - // The API key of the firebase project. - string api_key = 7 ; - -} - -// Information about models. -message ModelInfo { - - // The name of the model defined by the model creator. This string should be - // meaningful to the creator and describes what the model does. For example, - // the name can be "mobile vision face recognition" or "speech to text". - string name = 1 ; - - // The version of the model defined by the model creator. - string version = 2 ; - - // The expected checksum (SHA256) of the model file. Only hash of models - // downloaded from cloud is logged. - string hash = 5; - - // The model type is currently envisioned to be used mainly for model - // download/update. - enum ModelType { - TYPE_UNKNOWN = 0; - CUSTOM = 1; - } - ModelType model_type = 6; -} - -enum EventName { - UNKNOWN_EVENT = 0; - MODEL_DOWNLOAD = 100; - MODEL_UPDATE = 101; - REMOTE_MODEL_DELETE_ON_DEVICE = 252; -} - -// A list of error codes for various components of the system. For model downloading, the -// range of error codes is 100 to 199. -enum ErrorCode { - // No error at all. - NO_ERROR = 0; - - // The temporary URI to download the model has expired. - URI_EXPIRED = 101; - - // There is no network connection when trying to download the model file or - // the model info. - NO_NETWORK_CONNECTION = 102; - - // The download started on a valid condition but didn't finish successfully. - DOWNLOAD_FAILED = 104; - - // We received an unsuccessful http status code when trying to download the - // model info. An unsuccessful http status code is a code that's neither 200 - // nor 304. See go/firebase-ml-model-hosting-design for a list of possible - // status codes while downloading the model info. - MODEL_INFO_DOWNLOAD_UNSUCCESSFUL_HTTP_STATUS = 105; - - // Didn't receive a model hash while trying to download the model info. - MODEL_INFO_DOWNLOAD_NO_HASH = 106; - - // Failed to connect to the Firebase Console while trying to download the - // model info. - MODEL_INFO_DOWNLOAD_CONNECTION_FAILED = 107; - - // Model hash mismatches the expected value. - MODEL_HASH_MISMATCH = 116; - - // An unknown error has occurred. This is for conditions that should never - // happen. But we log them anyways. If there is a surge in UNKNOWN error - // codes, we need to check our code. - UNKNOWN_ERROR = 9999; -} - -// Detailed information about a model. -// The message used to be named "CustomModelOptions". -message ModelOptions { - // Inherent properties about the model: name, version, URI, source. - ModelInfo model_info = 1; - - // True if models can be updated. - bool is_model_update_enabled = 4; -} - -// Information about model downloading. A single model download request may -// result in multiple log entries. "download_status" in the log entry indicates -// during which stage it is logged. -// This message used to be named "CustomModelDownloadLogEvent". -message ModelDownloadLogEvent { - // The download status. The model download is made up of two major stages: the - // retrieval of the model info in Firebase backend, and then the download of - // the model file in GCS. Whether or not the download is requested implicitly - // or explicitly does not affect the later stages of the download. As a - // result, later stages (i.e. enum tag 3+) do not distinguish between explicit - // and implicit triggering. - enum DownloadStatus { - UNKNOWN_STATUS = 0; - - // The download is requested by the developer, i.e. ensureModelDownloaded() - // is called. - EXPLICITLY_REQUESTED = 1; - - // The download is requested by the SDK implicitly. - IMPLICITLY_REQUESTED = 2; - - // The retrieval of the model info succeeded. - MODEL_INFO_RETRIEVAL_SUCCEEDED = 3; - - // The retrieval of the model info failed. See error_code field for details. - MODEL_INFO_RETRIEVAL_FAILED = 4; - - // A new download with the OS downloader has been scheduled. - SCHEDULED = 5; - - // There is an existing downloading session. No new download is scheduled. - DOWNLOADING = 6; - - // The download of the model file succeeded. - SUCCEEDED = 7; - - // The download of the model file failed. - FAILED = 8; - - // Update is enabled and available while the existing model is downloaded or - // live. - UPDATE_AVAILABLE = 10; - } - - // Model information and options for downloading. - ModelOptions options = 1; - - // The rough duration of the download. This is not marked as - // ST_SENSITIVE_TIMESTAMP because it is a duration instead of a timestamp. - // We delegate the download to OS downloader. We may not be notified - // when the download completes, such as when the app is killed. - uint64 rough_download_duration_ms = 2; - - // The error code for model download. - ErrorCode error_code = 3; - - // The exact duration of the download. This is not marked as - // ST_SENSITIVE_TIMESTAMP because it is a duration instead of a timestamp. - // We know the exact duration when the download is completed while the app is - // still alive and receives the completed notification from OS downloader. - uint64 exact_download_duration_ms = 4; - - // The download status. - DownloadStatus download_status = 5; - - // If this field is logged for DownloadStatus.MODEL_INFO_RETRIEVAL_FAILED, it - // is the http status code from the firebase console. See - // go/firebase-ml-model-hosting-design. Same on both Android and iOS. - // If this field is logged for DownloadStatus.FAILED, it is the http status - // code on iOS, and the DownloadManager's "COLUMN_REASON" value on Android. On - // iOS, the status code can be a negative integer. - int64 download_failure_status = 6; -} - -// Information about deleting a downloaded model on device. -message DeleteModelLogEvent { - // The type of the downloaded model requested to be deleted. - ModelInfo.ModelType model_type = 1; - // Whether the downloaded model is deleted successfully. - bool is_successful = 2; -} - -// Main log event for FirebaseMl, that contains individual API events, like model -// download. -// NEXT ID: 44. -message FirebaseMlLogEvent { - // Information about various parts of the system: app, Firebase, SDK. - SystemInfo system_info = 1; - - // The event name. - EventName event_name = 2; - - // Information about model download. - ModelDownloadLogEvent model_download_log_event = 3; - - // Information about deleting a downloaded model. - DeleteModelLogEvent delete_model_log_event = 40; -} diff --git a/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift b/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift index ad08f3a273d..96e9f75cc05 100644 --- a/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift +++ b/FirebaseMLModelDownloader/Tests/Unit/ModelDownloaderUnitTests.swift @@ -264,31 +264,6 @@ messageCode: .testError) } - /// Compare proto serialization methods. - func testTelemetryEncoding() { - let fakeModel = CustomModel( - name: fakeModelName, - size: 10, - path: fakeModelPath, - hash: fakeModelHash - ) - var modelOptions = ModelOptions() - modelOptions.setModelOptions(modelName: fakeModel.name, modelHash: fakeModel.hash) - - guard let binaryData = try? modelOptions.serializedData(), - let jsonData = try? modelOptions.jsonUTF8Data(), - let binaryEvent = try? ModelOptions(serializedBytes: binaryData), - let jsonEvent = try? ModelOptions(jsonUTF8Data: jsonData) else { - XCTFail("Encoding error.") - return - } - - XCTAssertNotNil(binaryData) - XCTAssertNotNil(jsonData) - XCTAssertLessThan(binaryData.count, jsonData.count) - XCTAssertEqual(binaryEvent, jsonEvent) - } - /// Get model info if server returns a new model info. func testGetModelInfoWith200() { let session = fakeModelInfoSessionWithURL(fakeDownloadURL, statusCode: 200) diff --git a/Package.swift b/Package.swift index 091ce49d6ce..3807eaa92de 100644 --- a/Package.swift +++ b/Package.swift @@ -137,10 +137,6 @@ let package = Package( url: "https://github.com/google/promises.git", "2.4.0" ..< "3.0.0" ), - .package( - url: "https://github.com/apple/swift-protobuf.git", - "1.19.0" ..< "2.0.0" - ), googleAppMeasurementDependency(), .package( url: "https://github.com/google/GoogleDataTransport.git", @@ -817,17 +813,9 @@ let package = Package( "FirebaseCore", "FirebaseCoreExtension", "FirebaseInstallations", - .product(name: "GoogleDataTransport", package: "GoogleDataTransport"), .product(name: "GULUserDefaults", package: "GoogleUtilities"), - .product(name: "SwiftProtobuf", package: "swift-protobuf"), ], path: "FirebaseMLModelDownloader/Sources", - exclude: [ - "proto/firebase_ml_log_sdk.proto", - ], - cSettings: [ - .define("FIRMLModelDownloader_VERSION", to: firebaseVersion), - ], swiftSettings: [ .swiftLanguageMode(SwiftLanguageMode.v5), ]