Skip to content

Commit 735684f

Browse files
committed
Add AILog.safeUnwrap static method to log on use of fallback values
1 parent b52a408 commit 735684f

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

FirebaseAI/Sources/AILog.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ enum AILog {
6565
case decodedUnsupportedPartData = 3014
6666
case codeExecutionResultUnrecognizedOutcome = 3015
6767
case executableCodeUnrecognizedLanguage = 3016
68+
case fallbackValueUsed = 3017
6869

6970
// SDK State Errors
7071
case generateContentResponseNoCandidates = 4000
@@ -126,4 +127,32 @@ enum AILog {
126127
static func additionalLoggingEnabled() -> Bool {
127128
return ProcessInfo.processInfo.arguments.contains(enableArgumentKey)
128129
}
130+
131+
/// Returns the unwrapped optional value if non-nil or returns the fallback value and logs.
132+
///
133+
/// This convenience method is intended for use in place of `optionalValue ?? fallbackValue` with
134+
/// the addition of logging on use of the fallback value.
135+
///
136+
/// - Parameters:
137+
/// - optionalValue: The value to unwrap.
138+
/// - fallbackValue: The fallback (default) value to return when `optionalValue` is `nil`.
139+
/// - level: The logging level to use for fallback messages; defaults to
140+
/// `FirebaseLoggerLevel.warning`.
141+
/// - code: The message code to use for fallback messages; defaults to
142+
/// `MessageCode.fallbackValueUsed`.
143+
/// - caller: The name of the unwrapped value; defaults to the name of the computed property or
144+
/// function name from which the unwrapping occurred.
145+
static func safeUnwrap<T>(_ optionalValue: T?,
146+
fallback fallbackValue: T,
147+
level: FirebaseLoggerLevel = .warning,
148+
code: MessageCode = .fallbackValueUsed,
149+
caller: String = #function) -> T {
150+
guard let unwrappedValue = optionalValue else {
151+
AILog.log(level: level, code: code, """
152+
No value specified for '\(caller)' (\(T.self)); using fallback value '\(fallbackValue)'.
153+
""")
154+
return fallbackValue
155+
}
156+
return unwrappedValue
157+
}
129158
}

FirebaseAI/Sources/Types/Public/Part.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,16 @@ public struct ExecutableCodePart: Part {
229229
ExecutableCodePart.Language(
230230
// Fallback to "LANGUAGE_UNSPECIFIED" if the value is ever omitted by the backend; this should
231231
// never happen.
232-
executableCode.language ?? ExecutableCode.Language(kind: .unspecified)
232+
AILog.safeUnwrap(
233+
executableCode.language, fallback: ExecutableCode.Language(kind: .unspecified)
234+
)
233235
)
234236
}
235237

236238
/// The code that was executed.
237239
public var code: String {
238240
// Fallback to empty string if `code` is ever omitted by the backend; this should never happen.
239-
executableCode.code ?? ""
241+
AILog.safeUnwrap(executableCode.code, fallback: "")
240242
}
241243

242244
public var isThought: Bool { _isThought ?? false }
@@ -290,15 +292,14 @@ public struct CodeExecutionResultPart: Part {
290292
CodeExecutionResultPart.Outcome(
291293
// Fallback to "OUTCOME_UNSPECIFIED" if this value is ever omitted by the backend; this should
292294
// never happen.
293-
codeExecutionResult.outcome ?? CodeExecutionResult.Outcome(kind: .unspecified)
295+
AILog.safeUnwrap(
296+
codeExecutionResult.outcome, fallback: CodeExecutionResult.Outcome(kind: .unspecified)
297+
)
294298
)
295299
}
296300

297301
/// The output of the code execution.
298-
public var output: String {
299-
// Fallback to empty string if `output` is omitted by the backend; this should never happen.
300-
codeExecutionResult.output ?? ""
301-
}
302+
public var output: String? { codeExecutionResult.output }
302303

303304
public var isThought: Bool { _isThought ?? false }
304305

0 commit comments

Comments
 (0)