Skip to content

Commit 92d37e4

Browse files
authored
Improve callsites of threshold logging (#113)
1 parent b82c37c commit 92d37e4

15 files changed

+68
-65
lines changed

Sources/AIProxy/AIProxy.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -885,19 +885,19 @@ public struct AIProxy {
885885
do {
886886
return try await AnonymousAccountStorage.sync()
887887
} catch {
888-
if ll(.critical) { aiproxyLogger.critical("Could not configure an AIProxy anonymous account: \(error.localizedDescription)") }
888+
logIf(.critical)?.critical("Could not configure an AIProxy anonymous account: \(error.localizedDescription)")
889889
}
890890
return nil
891891
}
892892

893893
public static func base64EncodeAudioPCMBuffer(from buffer: AVAudioPCMBuffer) -> String? {
894894
guard buffer.format.channelCount == 1 else {
895-
if ll(.error) { aiproxyLogger.error("This encoding routine assumes a single channel") }
895+
logIf(.error)?.error("This encoding routine assumes a single channel")
896896
return nil
897897
}
898898

899899
guard let audioBufferPtr = buffer.audioBufferList.pointee.mBuffers.mData else {
900-
if ll(.error) { aiproxyLogger.error("No audio buffer list available to encode") }
900+
logIf(.error)?.error("No audio buffer list available to encode")
901901
return nil
902902
}
903903

Sources/AIProxy/AIProxyCertificatePinning.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ open class AIProxyCertificatePinningDelegate: NSObject, URLSessionDelegate, URLS
7070
_ challenge: URLAuthenticationChallenge
7171
) -> (URLSession.AuthChallengeDisposition, URLCredential?) {
7272
guard let secTrust = challenge.protectionSpace.serverTrust else {
73-
if ll(.error) { aiproxyLogger.error("Could not access the server's security space") }
73+
logIf(.error)?.error("Could not access the server's security space")
7474
return (.cancelAuthenticationChallenge, nil)
7575
}
7676

7777
guard let certificate = getServerCert(secTrust: secTrust) else {
78-
if ll(.error) { aiproxyLogger.error("Could not access the server's TLS cert") }
78+
logIf(.error)?.error("Could not access the server's TLS cert")
7979
return (.cancelAuthenticationChallenge, nil)
8080
}
8181

Sources/AIProxy/AIProxyDeviceCheck.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct AIProxyDeviceCheck {
3434
internal static func getToken() async -> String? {
3535
guard DCDevice.current.isSupported else {
3636
if ProcessInfo.processInfo.environment["AIPROXY_DEVICE_CHECK_BYPASS"] == nil {
37-
if ll(.warning) { aiproxyLogger.warning("\(deviceCheckWarning, privacy: .public)") }
37+
logIf(.warning)?.warning("\(deviceCheckWarning, privacy: .public)")
3838
}
3939
return nil
4040
}
@@ -43,7 +43,7 @@ struct AIProxyDeviceCheck {
4343
let data = try await DCDevice.current.generateToken()
4444
return data.base64EncodedString()
4545
} catch {
46-
if ll(.error) { aiproxyLogger.error("Could not create DeviceCheck token. Are you using an explicit bundle identifier?") }
46+
logIf(.error)?.error("Could not create DeviceCheck token. Are you using an explicit bundle identifier?")
4747
return nil
4848
}
4949
}

Sources/AIProxy/AIProxyLogger.swift

+6-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ internal let aiproxyLogger = Logger(
1818
category: "AIProxy"
1919
)
2020

21-
// Why not create a wrapper around OSLog instead of forcing log callsites to include an `if ll(<level>)` check?
21+
// Why not create a wrapper around OSLog instead of forcing log callsites to include an `logIf(<level>)` check?
2222
// Because I like the Xcode log feature that links to the source location of the log.
2323
// If you create a wrapper, even one that is inlined, the Xcode source feature always links to the wrapper location.
24+
//
25+
// H/T Quinn the Eskimo!
26+
// https://developer.apple.com/forums/thread/774931
2427
@inline(__always)
25-
internal func ll(_ logLevel: AIProxyLogLevel) -> Bool {
26-
return logLevel.isAtOrAboveThresholdLevel(aiproxyCallerDesiredLogLevel)
28+
internal func logIf(_ logLevel: AIProxyLogLevel) -> Logger? {
29+
logLevel.isAtOrAboveThresholdLevel(aiproxyCallerDesiredLogLevel) ? aiproxyLogger : nil
2730
}

Sources/AIProxy/AnonymousAccount/AIProxyKeychain.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ struct AIProxyKeychain {
132132
if status == noErr {
133133
return queryResult as? Data
134134
}
135-
if ll(.error) { aiproxyLogger.error("Unexpected keychain error in searchKeychainCopyMatching: \(status)") }
135+
logIf(.error)?.error("Unexpected keychain error in searchKeychainCopyMatching: \(status)")
136136
return nil
137137
}
138138

Sources/AIProxy/AnonymousAccount/AnonymousAccountStorage.swift

+16-16
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ final class AnonymousAccountStorage {
6666
// meaning the one that was created earliest. The design of this class is to eventually resolve out
6767
// to the earliest account across multiple devices.
6868
if !AIProxyStorage.ukvsSync() {
69-
if ll(.error) { aiproxyLogger.error("Could not synchronize NSUbiquitousKeyValueStore. Please ensure you enabled the key/value store in Target > Signing & Capabilities > iCloud > Key-Value storage?") }
69+
logIf(.error)?.error("Could not synchronize NSUbiquitousKeyValueStore. Please ensure you enabled the key/value store in Target > Signing & Capabilities > iCloud > Key-Value storage?")
7070
}
7171
if let ukvsAccountData = AIProxyStorage.ukvsAccountData() {
7272
let ukvsAccount = try AnonymousAccount.deserialize(from: ukvsAccountData)
@@ -78,7 +78,7 @@ final class AnonymousAccountStorage {
7878
localAccount = ukvsAccount
7979
self.localAccountChain.append(ukvsAccount)
8080
if try await AIProxyStorage.updateLocalAccountChainInKeychain(self.localAccountChain) != noErr {
81-
if ll(.warning) { aiproxyLogger.warning("Could not update the local account chain") }
81+
logIf(.warning)?.warning("Could not update the local account chain")
8282
}
8383
} else {
8484
try AIProxyStorage.updateUKVS(localAccount)
@@ -108,17 +108,17 @@ final class AnonymousAccountStorage {
108108
localAccount = remoteAccount
109109
self.localAccountChain.append(remoteAccount)
110110
if try await AIProxyStorage.updateLocalAccountChainInKeychain(self.localAccountChain) != noErr {
111-
if ll(.warning) { aiproxyLogger.warning("Could not update the local account chain") }
111+
logIf(.warning)?.warning("Could not update the local account chain")
112112
}
113113
try AIProxyStorage.updateUKVS(localAccount)
114114
} else {
115115
if try await AIProxyStorage.updateRemoteAccountInKeychain(localAccount) != noErr {
116-
if ll(.warning) { aiproxyLogger.warning("Could not update the remote account") }
116+
logIf(.warning)?.warning("Could not update the remote account")
117117
}
118118
}
119119
}
120120
} else {
121-
if ll(.warning) { aiproxyLogger.warning("Keychain cloud sync claims that there is a duplicate item, but we can't fetch it.") }
121+
logIf(.warning)?.warning("Keychain cloud sync claims that there is a duplicate item, but we can't fetch it.")
122122
}
123123
}
124124

@@ -129,8 +129,8 @@ final class AnonymousAccountStorage {
129129
name: NSUbiquitousKeyValueStore.didChangeExternallyNotification,
130130
object: NSUbiquitousKeyValueStore.default)
131131

132-
if ll(.debug) { aiproxyLogger.debug("Local account chain is \(localAccountChain)") }
133-
if ll(.debug) { aiproxyLogger.debug("Anonymous account identifier is \(self.resolvedAccount?.uuid ?? "unknown")") }
132+
logIf(.debug)?.debug("Local account chain is \(localAccountChain)")
133+
logIf(.debug)?.debug("Anonymous account identifier is \(self.resolvedAccount?.uuid ?? "unknown")")
134134

135135
return localAccount.uuid
136136
}
@@ -154,10 +154,10 @@ final class AnonymousAccountStorage {
154154
}
155155

156156
switch changeReason.intValue {
157-
case NSUbiquitousKeyValueStoreServerChange: if ll(.info) { aiproxyLogger.info("AIProxy account changed due to remote server change") }
158-
case NSUbiquitousKeyValueStoreInitialSyncChange: if ll(.info) { aiproxyLogger.info("AIProxy account changed due to initial sync change") }
159-
case NSUbiquitousKeyValueStoreQuotaViolationChange: if ll(.info) { aiproxyLogger.info("AIProxy account changed due to quota violation") }
160-
case NSUbiquitousKeyValueStoreAccountChange: if ll(.info) { aiproxyLogger.info("AIProxy account changed due to icloud account change") }
157+
case NSUbiquitousKeyValueStoreServerChange: logIf(.info)?.info("AIProxy account changed due to remote server change")
158+
case NSUbiquitousKeyValueStoreInitialSyncChange: logIf(.info)?.info("AIProxy account changed due to initial sync change")
159+
case NSUbiquitousKeyValueStoreQuotaViolationChange: logIf(.info)?.info("AIProxy account changed due to quota violation")
160+
case NSUbiquitousKeyValueStoreAccountChange: logIf(.info)?.info("AIProxy account changed due to icloud account change")
161161
default:
162162
return
163163
}
@@ -172,12 +172,12 @@ final class AnonymousAccountStorage {
172172
}
173173

174174
guard ukvsAccount != resolvedAccount else {
175-
if ll(.info) { aiproxyLogger.info("UKVS remote sync is already up to date") }
175+
logIf(.info)?.info("UKVS remote sync is already up to date")
176176
return
177177
}
178178

179179
if ukvsAccount.timestamp <= resolvedAccount.timestamp {
180-
if ll(.info) { aiproxyLogger.info("UKVS account is older than our existing resolved account. Switching to the older account.") }
180+
logIf(.info)?.info("UKVS account is older than our existing resolved account. Switching to the older account.")
181181
self.resolvedAccount = ukvsAccount
182182
self.localAccountChain.append(ukvsAccount)
183183
DispatchQueue.main.async {
@@ -187,16 +187,16 @@ final class AnonymousAccountStorage {
187187
Task.detached {
188188
let updateLocal = try? await AIProxyStorage.updateLocalAccountChainInKeychain(self.localAccountChain)
189189
if updateLocal == nil || updateLocal! != noErr {
190-
if ll(.warning) { aiproxyLogger.warning("Could not update the local account chain") }
190+
logIf(.warning)?.warning("Could not update the local account chain")
191191
}
192192

193193
let updateRemote = try? await AIProxyStorage.updateRemoteAccountInKeychain(ukvsAccount)
194194
if updateRemote == nil || updateRemote! != noErr {
195-
if ll(.warning) { aiproxyLogger.warning("Could not update the remote account") }
195+
logIf(.warning)?.warning("Could not update the remote account")
196196
}
197197
}
198198
} else {
199-
if ll(.info) { aiproxyLogger.info("UKVS account is newer than our existing resolved account. Updating UKVS to use the older account.") }
199+
logIf(.info)?.info("UKVS account is newer than our existing resolved account. Updating UKVS to use the older account.")
200200
try? AIProxyStorage.updateUKVS(resolvedAccount)
201201
}
202202
}

Sources/AIProxy/Anthropic/AnthropicMessageStreamingContentBlockStart.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal struct AnthropicMessageStreamingContentBlockStart: Decodable {
1717
guard let chunkJSON = line.dropFirst(6).data(using: .utf8),
1818
let chunk = try? JSONDecoder().decode(Self.self, from: chunkJSON) else
1919
{
20-
if ll(.warning) { aiproxyLogger.warning("Received unexpected JSON from Anthropic: \(line)") }
20+
logIf(.warning)?.warning("Received unexpected JSON from Anthropic: \(line)")
2121
return nil
2222
}
2323
return chunk

Sources/AIProxy/Anthropic/AnthropicMessageStreamingDeltaBlock.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal struct AnthropicMessageStreamingDeltaBlock: Decodable {
1919
guard let chunkJSON = line.dropFirst(6).data(using: .utf8),
2020
let chunk = try? JSONDecoder().decode(Self.self, from: chunkJSON) else
2121
{
22-
if ll(.warning) { aiproxyLogger.warning("Received unexpected JSON from Anthropic: \(line)") }
22+
logIf(.warning)?.warning("Received unexpected JSON from Anthropic: \(line)")
2323
return nil
2424
}
2525
return chunk

Sources/AIProxy/AudioPCMPlayer.swift

+8-8
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ open class AudioPCMPlayer {
8181
}
8282

8383
deinit {
84-
if ll(.debug) { aiproxyLogger.debug("AudioPCMPlayer is being freed") }
84+
logIf(.debug)?.debug("AudioPCMPlayer is being freed")
8585
self.audioEngine.stop()
8686
}
8787

8888
public func playPCM16Audio(from base64String: String) {
8989
guard let audioData = Data(base64Encoded: base64String) else {
90-
if ll(.error) { aiproxyLogger.error("Could not decode base64 string for audio playback") }
90+
logIf(.error)?.error("Could not decode base64 string for audio playback")
9191
return
9292
}
9393

@@ -106,35 +106,35 @@ open class AudioPCMPlayer {
106106
pcmFormat: self.inputFormat,
107107
bufferListNoCopy: &bufferList
108108
) else {
109-
if ll(.error) { aiproxyLogger.error("Could not create input buffer for audio playback") }
109+
logIf(.error)?.error("Could not create input buffer for audio playback")
110110
return
111111
}
112112

113113
guard let outPCMBuf = AVAudioPCMBuffer(
114114
pcmFormat: self.playableFormat,
115115
frameCapacity: AVAudioFrameCount(self.playableFormat.sampleRate * 2.0)
116116
) else {
117-
if ll(.error) { aiproxyLogger.error("Could not create output buffer for audio playback") }
117+
logIf(.error)?.error("Could not create output buffer for audio playback")
118118
return
119119
}
120120

121121
guard let converter = AVAudioConverter(from: self.inputFormat, to: self.playableFormat) else {
122-
if ll(.error) { aiproxyLogger.error("Could not create audio converter needed to map from pcm16int to pcm32float") }
122+
logIf(.error)?.error("Could not create audio converter needed to map from pcm16int to pcm32float")
123123
return
124124
}
125125

126126
do {
127127
try converter.convert(to: outPCMBuf, from: inPCMBuf)
128128
} catch {
129-
if ll(.error) { aiproxyLogger.error("Could not map from pcm16int to pcm32float: \(error.localizedDescription)") }
129+
logIf(.error)?.error("Could not map from pcm16int to pcm32float: \(error.localizedDescription)")
130130
return
131131
}
132132

133133
if !self.audioEngine.isRunning {
134134
do {
135135
try self.audioEngine.start()
136136
} catch {
137-
if ll(.error) { aiproxyLogger.error("Could not start audio engine: \(error.localizedDescription)") }
137+
logIf(.error)?.error("Could not start audio engine: \(error.localizedDescription)")
138138
return
139139
}
140140
}
@@ -150,7 +150,7 @@ open class AudioPCMPlayer {
150150
}
151151

152152
public func interruptPlayback() {
153-
if ll(.debug) { aiproxyLogger.debug("Interrupting playback") }
153+
logIf(.debug)?.debug("Interrupting playback")
154154
self.playerNode.stop()
155155
}
156156
}

Sources/AIProxy/Deserializable.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ extension Decodable {
2424
guard line.hasPrefix("data: ") else {
2525
// Special case to ignore OpenRouter and DeepSeek SSE comments
2626
if line != ": OPENROUTER PROCESSING" && line != ": keep-alive" {
27-
if ll(.warning) { aiproxyLogger.warning("Received unexpected line from aiproxy: \(line)") }
27+
logIf(.warning)?.warning("Received unexpected line from aiproxy: \(line)")
2828
}
2929
return nil
3030
}
3131

3232
guard line != "data: [DONE]" else {
33-
if ll(.debug) { aiproxyLogger.debug("Streaming response has finished") }
33+
logIf(.debug)?.debug("Streaming response has finished")
3434
return nil
3535
}
3636

3737
guard let chunkJSON = line.dropFirst(6).data(using: .utf8),
3838
let chunk = try? JSONDecoder().decode(Self.self, from: chunkJSON) else
3939
{
40-
if ll(.warning) { aiproxyLogger.warning("Received unexpected JSON from aiproxy: \(line)") }
40+
logIf(.warning)?.warning("Received unexpected JSON from aiproxy: \(line)")
4141
return nil
4242
}
4343

Sources/AIProxy/FireworksAI/FireworksAIDirectService.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ open class FireworksAIDirectService: FireworksAIService, DirectService {
3333
secondsToWait: Int
3434
) async throws -> DeepSeekChatCompletionResponseBody {
3535
if body.model != "accounts/fireworks/models/deepseek-r1" {
36-
if ll(.warning) { aiproxyLogger.warning("Attempting to use deepSeekR1Request with an unknown model") }
36+
logIf(.warning)?.warning("Attempting to use deepSeekR1Request with an unknown model")
3737
}
3838
var body = body
3939
body.stream = false
@@ -67,7 +67,7 @@ open class FireworksAIDirectService: FireworksAIService, DirectService {
6767
secondsToWait: Int
6868
) async throws -> AsyncCompactMapSequence<AsyncLineSequence<URLSession.AsyncBytes>, DeepSeekChatCompletionChunk> {
6969
if body.model != "accounts/fireworks/models/deepseek-r1" {
70-
if ll(.warning) { aiproxyLogger.warning("Attempting to use deepSeekR1Request with an unknown model") }
70+
logIf(.warning)?.warning("Attempting to use deepSeekR1Request with an unknown model")
7171
}
7272
var body = body
7373
body.stream = true

Sources/AIProxy/FireworksAI/FireworksAIProxiedService.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ open class FireworksAIProxiedService: FireworksAIService, ProxiedService {
3939
secondsToWait: Int
4040
) async throws -> DeepSeekChatCompletionResponseBody {
4141
if body.model != "accounts/fireworks/models/deepseek-r1" {
42-
if ll(.warning) { aiproxyLogger.warning("Attempting to use deepSeekR1Request with an unknown model") }
42+
logIf(.warning)?.warning("Attempting to use deepSeekR1Request with an unknown model")
4343
}
4444
var body = body
4545
body.stream = false
@@ -71,7 +71,7 @@ open class FireworksAIProxiedService: FireworksAIService, ProxiedService {
7171
secondsToWait: Int
7272
) async throws -> AsyncCompactMapSequence<AsyncLineSequence<URLSession.AsyncBytes>, DeepSeekChatCompletionChunk> {
7373
if body.model != "accounts/fireworks/models/deepseek-r1" {
74-
if ll(.warning) { aiproxyLogger.warning("Attempting to use deepSeekR1Request with an unknown model") }
74+
logIf(.warning)?.warning("Attempting to use deepSeekR1Request with an unknown model")
7575
}
7676
var body = body
7777
body.stream = true

0 commit comments

Comments
 (0)