Skip to content

Commit 7bb68ad

Browse files
authored
[Vertex AI] Migrate logging to FirebaseLogger (#13638)
1 parent b1a19b4 commit 7bb68ad

File tree

6 files changed

+178
-113
lines changed

6 files changed

+178
-113
lines changed

FirebaseVertexAI/Sources/GenerateContentResponse.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ public struct GenerateContentResponse: Sendable {
4242
/// The response's content as text, if it exists.
4343
public var text: String? {
4444
guard let candidate = candidates.first else {
45-
Logging.default
46-
.error("[FirebaseVertexAI] Could not get text from a response that had no candidates.")
45+
VertexLog.error(
46+
code: .generateContentResponseNoCandidates,
47+
"Could not get text from a response that had no candidates."
48+
)
4749
return nil
4850
}
4951
let textValues: [String] = candidate.content.parts.compactMap { part in
@@ -53,8 +55,10 @@ public struct GenerateContentResponse: Sendable {
5355
return text
5456
}
5557
guard textValues.count > 0 else {
56-
Logging.default
57-
.error("[FirebaseVertexAI] Could not get a text part from the first candidate.")
58+
VertexLog.error(
59+
code: .generateContentResponseNoText,
60+
"Could not get a text part from the first candidate."
61+
)
5862
return nil
5963
}
6064
return textValues.joined(separator: " ")
@@ -330,8 +334,10 @@ extension FinishReason: Decodable {
330334
public init(from decoder: Decoder) throws {
331335
let value = try decoder.singleValueContainer().decode(String.self)
332336
guard let decodedFinishReason = FinishReason(rawValue: value) else {
333-
Logging.default
334-
.error("[FirebaseVertexAI] Unrecognized FinishReason with value \"\(value)\".")
337+
VertexLog.error(
338+
code: .generateContentResponseUnrecognizedFinishReason,
339+
"Unrecognized FinishReason with value \"\(value)\"."
340+
)
335341
self = .unknown
336342
return
337343
}
@@ -345,8 +351,10 @@ extension PromptFeedback.BlockReason: Decodable {
345351
public init(from decoder: Decoder) throws {
346352
let value = try decoder.singleValueContainer().decode(String.self)
347353
guard let decodedBlockReason = PromptFeedback.BlockReason(rawValue: value) else {
348-
Logging.default
349-
.error("[FirebaseVertexAI] Unrecognized BlockReason with value \"\(value)\".")
354+
VertexLog.error(
355+
code: .generateContentResponseUnrecognizedBlockReason,
356+
"Unrecognized BlockReason with value \"\(value)\"."
357+
)
350358
self = .unknown
351359
return
352360
}

FirebaseVertexAI/Sources/GenerativeAIService.swift

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import FirebaseAppCheckInterop
1616
import FirebaseAuthInterop
1717
import FirebaseCore
1818
import Foundation
19+
import os.log
1920

2021
@available(iOS 15.0, macOS 11.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
2122
struct GenerativeAIService {
@@ -60,9 +61,15 @@ struct GenerativeAIService {
6061

6162
// Verify the status code is 200
6263
guard response.statusCode == 200 else {
63-
Logging.network.error("[FirebaseVertexAI] The server responded with an error: \(response)")
64+
VertexLog.error(
65+
code: .loadRequestResponseError,
66+
"The server responded with an error: \(response)"
67+
)
6468
if let responseString = String(data: data, encoding: .utf8) {
65-
Logging.default.error("[FirebaseVertexAI] Response payload: \(responseString)")
69+
VertexLog.error(
70+
code: .loadRequestResponseErrorPayload,
71+
"Response payload: \(responseString)"
72+
)
6673
}
6774

6875
throw parseError(responseData: data)
@@ -108,14 +115,19 @@ struct GenerativeAIService {
108115

109116
// Verify the status code is 200
110117
guard response.statusCode == 200 else {
111-
Logging.network
112-
.error("[FirebaseVertexAI] The server responded with an error: \(response)")
118+
VertexLog.error(
119+
code: .loadRequestStreamResponseError,
120+
"The server responded with an error: \(response)"
121+
)
113122
var responseBody = ""
114123
for try await line in stream.lines {
115124
responseBody += line + "\n"
116125
}
117126

118-
Logging.default.error("[FirebaseVertexAI] Response payload: \(responseBody)")
127+
VertexLog.error(
128+
code: .loadRequestStreamResponseErrorPayload,
129+
"Response payload: \(responseBody)"
130+
)
119131
continuation.finish(throwing: parseError(responseBody: responseBody))
120132

121133
return
@@ -127,7 +139,7 @@ struct GenerativeAIService {
127139
let decoder = JSONDecoder()
128140
decoder.keyDecodingStrategy = .convertFromSnakeCase
129141
for try await line in stream.lines {
130-
Logging.network.debug("[FirebaseVertexAI] Stream response: \(line)")
142+
VertexLog.debug(code: .loadRequestStreamResponseLine, "Stream response: \(line)")
131143

132144
if line.hasPrefix("data:") {
133145
// We can assume 5 characters since it's utf-8 encoded, removing `data:`.
@@ -179,8 +191,10 @@ struct GenerativeAIService {
179191
let tokenResult = await appCheck.getToken(forcingRefresh: false)
180192
urlRequest.setValue(tokenResult.token, forHTTPHeaderField: "X-Firebase-AppCheck")
181193
if let error = tokenResult.error {
182-
Logging.default
183-
.debug("[FirebaseVertexAI] Failed to fetch AppCheck token. Error: \(error)")
194+
VertexLog.error(
195+
code: .appCheckTokenFetchFailed,
196+
"Failed to fetch AppCheck token. Error: \(error)"
197+
)
184198
}
185199
}
186200

@@ -202,10 +216,10 @@ struct GenerativeAIService {
202216
private func httpResponse(urlResponse: URLResponse) throws -> HTTPURLResponse {
203217
// Verify the status code is 200
204218
guard let response = urlResponse as? HTTPURLResponse else {
205-
Logging.default
206-
.error(
207-
"[FirebaseVertexAI] Response wasn't an HTTP response, internal error \(urlResponse)"
208-
)
219+
VertexLog.error(
220+
code: .generativeAIServiceNonHTTPResponse,
221+
"Response wasn't an HTTP response, internal error \(urlResponse)"
222+
)
209223
throw NSError(
210224
domain: "com.google.generative-ai",
211225
code: -1,
@@ -253,7 +267,7 @@ struct GenerativeAIService {
253267
// These errors do not produce specific GenerateContentError or CountTokensError cases.
254268
private func logRPCError(_ error: RPCError) {
255269
if error.isFirebaseMLServiceDisabledError() {
256-
Logging.default.error("""
270+
VertexLog.error(code: .firebaseMLAPIDisabled, """
257271
The Vertex AI for Firebase SDK requires the Firebase ML API `firebaseml.googleapis.com` to \
258272
be enabled for your project. Get started in the Firebase Console \
259273
(https://console.firebase.google.com/project/\(projectID)/genai/vertex) or verify that the \
@@ -269,9 +283,12 @@ struct GenerativeAIService {
269283
return try JSONDecoder().decode(type, from: data)
270284
} catch {
271285
if let json = String(data: data, encoding: .utf8) {
272-
Logging.network.error("[FirebaseVertexAI] JSON response: \(json)")
286+
VertexLog.error(code: .loadRequestParseResponseFailedJSON, "JSON response: \(json)")
273287
}
274-
Logging.default.error("[FirebaseVertexAI] Error decoding server JSON: \(error)")
288+
VertexLog.error(
289+
code: .loadRequestParseResponseFailedJSONError,
290+
"Error decoding server JSON: \(error)"
291+
)
275292
throw error
276293
}
277294
}
@@ -297,9 +314,12 @@ struct GenerativeAIService {
297314
}
298315

299316
private func printCURLCommand(from request: URLRequest) {
317+
guard VertexLog.additionalLoggingEnabled() else {
318+
return
319+
}
300320
let command = cURLCommand(from: request)
301-
Logging.verbose.debug("""
302-
[FirebaseVertexAI] Creating request with the equivalent cURL command:
321+
os_log(.debug, log: VertexLog.logObject, """
322+
\(VertexLog.service) Creating request with the equivalent cURL command:
303323
----- cURL command -----
304324
\(command, privacy: .private)
305325
------------------------

FirebaseVertexAI/Sources/GenerativeModel.swift

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,15 @@ public final class GenerativeModel {
8585
self.systemInstruction = systemInstruction
8686
self.requestOptions = requestOptions
8787

88-
if Logging.additionalLoggingEnabled() {
89-
if ProcessInfo.processInfo.arguments.contains(Logging.migrationEnableArgumentKey) {
90-
Logging.verbose.debug("""
91-
[FirebaseVertexAI] Verbose logging enabled with the \
92-
\(Logging.migrationEnableArgumentKey, privacy: .public) launch argument; please migrate to \
93-
the \(Logging.enableArgumentKey, privacy: .public) argument to ensure future compatibility.
94-
""")
95-
} else {
96-
Logging.verbose.debug("[FirebaseVertexAI] Verbose logging enabled.")
97-
}
88+
if VertexLog.additionalLoggingEnabled() {
89+
VertexLog.debug(code: .verboseLoggingEnabled, "Verbose logging enabled.")
9890
} else {
99-
Logging.default.info("""
91+
VertexLog.info(code: .verboseLoggingDisabled, """
10092
[FirebaseVertexAI] To enable additional logging, add \
101-
`\(Logging.enableArgumentKey, privacy: .public)` as a launch argument in Xcode.
93+
`\(VertexLog.enableArgumentKey)` as a launch argument in Xcode.
10294
""")
10395
}
104-
Logging.default.debug("[FirebaseVertexAI] Model \(name, privacy: .public) initialized.")
96+
VertexLog.debug(code: .generativeModelInitialized, "Model \(name) initialized.")
10597
}
10698

10799
/// Generates content from String and/or image inputs, given to the model as a prompt, that are

FirebaseVertexAI/Sources/Logging.swift

Lines changed: 0 additions & 71 deletions
This file was deleted.

FirebaseVertexAI/Sources/Safety.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ extension SafetyRating.HarmProbability: Decodable {
121121
public init(from decoder: Decoder) throws {
122122
let value = try decoder.singleValueContainer().decode(String.self)
123123
guard let decodedProbability = SafetyRating.HarmProbability(rawValue: value) else {
124-
Logging.default
125-
.error("[FirebaseVertexAI] Unrecognized HarmProbability with value \"\(value)\".")
124+
VertexLog.error(
125+
code: .generateContentResponseUnrecognizedHarmProbability,
126+
"Unrecognized HarmProbability with value \"\(value)\"."
127+
)
126128
self = .unknown
127129
return
128130
}
@@ -139,8 +141,10 @@ extension HarmCategory: Codable {
139141
public init(from decoder: Decoder) throws {
140142
let value = try decoder.singleValueContainer().decode(String.self)
141143
guard let decodedCategory = HarmCategory(rawValue: value) else {
142-
Logging.default
143-
.error("[FirebaseVertexAI] Unrecognized HarmCategory with value \"\(value)\".")
144+
VertexLog.error(
145+
code: .generateContentResponseUnrecognizedHarmCategory,
146+
"Unrecognized HarmCategory with value \"\(value)\"."
147+
)
144148
self = .unknown
145149
return
146150
}

0 commit comments

Comments
 (0)