From 9e7804ba91ee8b5ef72bb31b3c4c79c00ac9e454 Mon Sep 17 00:00:00 2001 From: Fabrizio Demaria Date: Mon, 11 Nov 2024 13:50:24 +0100 Subject: [PATCH 1/2] feat: Resolve Debug at DEBUG level logging --- .../ConfidenceDemoApp/ConfidenceDemoApp.swift | 5 ++++- Sources/Confidence/Confidence.swift | 3 ++- Sources/Confidence/ConfidenceClientOptions.swift | 9 ++++++++- .../Confidence/RemoteResolveConfidenceClient.swift | 13 ++++++++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ConfidenceDemoApp/ConfidenceDemoApp/ConfidenceDemoApp.swift b/ConfidenceDemoApp/ConfidenceDemoApp/ConfidenceDemoApp.swift index 073efd95..6d79beb7 100644 --- a/ConfidenceDemoApp/ConfidenceDemoApp/ConfidenceDemoApp.swift +++ b/ConfidenceDemoApp/ConfidenceDemoApp/ConfidenceDemoApp.swift @@ -20,7 +20,10 @@ struct ConfidenceDemoApp: App { WindowGroup { let secret = ProcessInfo.processInfo.environment["CLIENT_SECRET"] ?? "" let confidence = Confidence.Builder(clientSecret: secret, loggerLevel: .TRACE) - .withContext(initialContext: ["targeting_key": ConfidenceValue(string: UUID.init().uuidString)]) + .withContext(initialContext: [ + "targeting_key": ConfidenceValue(string: UUID.init().uuidString), + "user_id": .init(string: "user2") + ]) .build() let status = Status() diff --git a/Sources/Confidence/Confidence.swift b/Sources/Confidence/Confidence.swift index f5e5dc75..e0e4d255 100644 --- a/Sources/Confidence/Confidence.swift +++ b/Sources/Confidence/Confidence.swift @@ -397,7 +397,8 @@ extension Confidence { let options = ConfidenceClientOptions( credentials: ConfidenceClientCredentials.clientSecret(secret: clientSecret), region: region, - timeoutIntervalForRequest: timeout) + timeoutIntervalForRequest: timeout, + debugLogger: debugLogger) let metadata = ConfidenceMetadata( name: sdkId, version: "1.0.1") // x-release-please-version diff --git a/Sources/Confidence/ConfidenceClientOptions.swift b/Sources/Confidence/ConfidenceClientOptions.swift index fe64d3bb..b46c797d 100644 --- a/Sources/Confidence/ConfidenceClientOptions.swift +++ b/Sources/Confidence/ConfidenceClientOptions.swift @@ -5,17 +5,24 @@ struct ConfidenceClientOptions { public var region: ConfidenceRegion public var initializationStrategy: InitializationStrategy public var timeoutIntervalForRequest: Double + private let debugLogger: DebugLogger? public init( credentials: ConfidenceClientCredentials, region: ConfidenceRegion? = nil, initializationStrategy: InitializationStrategy = .fetchAndActivate, - timeoutIntervalForRequest: Double + timeoutIntervalForRequest: Double, + debugLogger: DebugLogger? = nil ) { self.credentials = credentials self.region = region ?? .global self.initializationStrategy = initializationStrategy self.timeoutIntervalForRequest = timeoutIntervalForRequest + self.debugLogger = debugLogger + } + + func getLogger() -> DebugLogger? { + return debugLogger } } diff --git a/Sources/Confidence/RemoteResolveConfidenceClient.swift b/Sources/Confidence/RemoteResolveConfidenceClient.swift index 479dead8..a9747365 100644 --- a/Sources/Confidence/RemoteResolveConfidenceClient.swift +++ b/Sources/Confidence/RemoteResolveConfidenceClient.swift @@ -26,14 +26,25 @@ class RemoteConfidenceResolveClient: ConfidenceResolveClient { // MARK: Resolver public func resolve(flags: [String], ctx: ConfidenceStruct) async throws -> ResolvesResult { + let ctxNetworkValue = TypeMapper.convert(structure: ctx) let request = ResolveFlagsRequest( flags: flags.map { "flags/\($0)" }, - evaluationContext: TypeMapper.convert(structure: ctx), + evaluationContext: ctxNetworkValue, clientSecret: options.credentials.getSecret(), apply: applyOnResolve, sdk: Sdk(id: metadata.name, version: metadata.version) ) + if let debugLogger = options.getLogger() { + let encoder = JSONEncoder() + if let jsonData = try? encoder.encode(ctxNetworkValue), + let jsonCtx = String(data: jsonData, encoding: .utf8) { + debugLogger.logMessage( + message: "[Resolve Debug] https://app.confidence.spotify.com/flags/resolver-test?context=\(jsonCtx)", + isWarning: false) + } + } + do { let result: HttpClientResult = try await self.httpClient.post(path: ":resolve", data: request) From 5c617fca70ce3ae0131292d8672a1a27f48a6454 Mon Sep 17 00:00:00 2001 From: Fabrizio Demaria Date: Tue, 12 Nov 2024 09:52:40 +0100 Subject: [PATCH 2/2] feat: Move debug resolve to get evaluation --- Sources/Confidence/Confidence.swift | 6 +++--- Sources/Confidence/ConfidenceClientOptions.swift | 9 +-------- Sources/Confidence/DebugLogger.swift | 11 +++++++++++ Sources/Confidence/FlagEvaluation.swift | 7 ++++++- .../Confidence/RemoteResolveConfidenceClient.swift | 13 +------------ Tests/ConfidenceTests/Helpers/DebugLoggerFake.swift | 4 ++++ 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Sources/Confidence/Confidence.swift b/Sources/Confidence/Confidence.swift index e0e4d255..8e5d8896 100644 --- a/Sources/Confidence/Confidence.swift +++ b/Sources/Confidence/Confidence.swift @@ -154,7 +154,8 @@ public class Confidence: ConfidenceEventSender { flagName: key, defaultValue: defaultValue, context: getContext(), - flagApplier: flagApplier + flagApplier: flagApplier, + debugLogger: debugLogger ) } } @@ -397,8 +398,7 @@ extension Confidence { let options = ConfidenceClientOptions( credentials: ConfidenceClientCredentials.clientSecret(secret: clientSecret), region: region, - timeoutIntervalForRequest: timeout, - debugLogger: debugLogger) + timeoutIntervalForRequest: timeout) let metadata = ConfidenceMetadata( name: sdkId, version: "1.0.1") // x-release-please-version diff --git a/Sources/Confidence/ConfidenceClientOptions.swift b/Sources/Confidence/ConfidenceClientOptions.swift index b46c797d..fe64d3bb 100644 --- a/Sources/Confidence/ConfidenceClientOptions.swift +++ b/Sources/Confidence/ConfidenceClientOptions.swift @@ -5,24 +5,17 @@ struct ConfidenceClientOptions { public var region: ConfidenceRegion public var initializationStrategy: InitializationStrategy public var timeoutIntervalForRequest: Double - private let debugLogger: DebugLogger? public init( credentials: ConfidenceClientCredentials, region: ConfidenceRegion? = nil, initializationStrategy: InitializationStrategy = .fetchAndActivate, - timeoutIntervalForRequest: Double, - debugLogger: DebugLogger? = nil + timeoutIntervalForRequest: Double ) { self.credentials = credentials self.region = region ?? .global self.initializationStrategy = initializationStrategy self.timeoutIntervalForRequest = timeoutIntervalForRequest - self.debugLogger = debugLogger - } - - func getLogger() -> DebugLogger? { - return debugLogger } } diff --git a/Sources/Confidence/DebugLogger.swift b/Sources/Confidence/DebugLogger.swift index fe7922c2..b5dbd92f 100644 --- a/Sources/Confidence/DebugLogger.swift +++ b/Sources/Confidence/DebugLogger.swift @@ -6,6 +6,7 @@ internal protocol DebugLogger { func logMessage(message: String, isWarning: Bool) func logFlags(action: String, flag: String) func logContext(action: String, context: ConfidenceStruct) + func logResolveDebugURL(flagName: String, context: ConfidenceStruct) } private extension Logger { @@ -15,6 +16,16 @@ private extension Logger { } internal class DebugLoggerImpl: DebugLogger { + private let encoder = JSONEncoder() + + func logResolveDebugURL(flagName: String, context: ConfidenceStruct) { + let ctxNetworkValue = TypeMapper.convert(structure: context) + if let ctxNetworkData = try? encoder.encode(ctxNetworkValue), + let ctxNetworkString = String(data: ctxNetworkData, encoding: .utf8) { + log(messageLevel: .DEBUG, message: "[Resolve Debug] https://app.confidence.spotify.com/flags/resolver-test?flag=flags/\(flagName)&context=\(ctxNetworkString)") + } + } + private let loggerLevel: LoggerLevel init(loggerLevel: LoggerLevel) { diff --git a/Sources/Confidence/FlagEvaluation.swift b/Sources/Confidence/FlagEvaluation.swift index d64e43ca..611aa26a 100644 --- a/Sources/Confidence/FlagEvaluation.swift +++ b/Sources/Confidence/FlagEvaluation.swift @@ -29,7 +29,8 @@ extension FlagResolution { flagName: String, defaultValue: T, context: ConfidenceStruct, - flagApplier: FlagApplier? = nil + flagApplier: FlagApplier? = nil, + debugLogger: DebugLogger? = nil ) -> Evaluation { do { let parsedKey = try FlagPath.getPath(for: flagName) @@ -44,6 +45,10 @@ extension FlagResolution { ) } + if let debugLogger = debugLogger { + debugLogger.logResolveDebugURL(flagName: parsedKey.flag, context: context) + } + if let evaluation = checkBackendErrors(resolvedFlag: resolvedFlag, defaultValue: defaultValue) { return evaluation } diff --git a/Sources/Confidence/RemoteResolveConfidenceClient.swift b/Sources/Confidence/RemoteResolveConfidenceClient.swift index a9747365..479dead8 100644 --- a/Sources/Confidence/RemoteResolveConfidenceClient.swift +++ b/Sources/Confidence/RemoteResolveConfidenceClient.swift @@ -26,25 +26,14 @@ class RemoteConfidenceResolveClient: ConfidenceResolveClient { // MARK: Resolver public func resolve(flags: [String], ctx: ConfidenceStruct) async throws -> ResolvesResult { - let ctxNetworkValue = TypeMapper.convert(structure: ctx) let request = ResolveFlagsRequest( flags: flags.map { "flags/\($0)" }, - evaluationContext: ctxNetworkValue, + evaluationContext: TypeMapper.convert(structure: ctx), clientSecret: options.credentials.getSecret(), apply: applyOnResolve, sdk: Sdk(id: metadata.name, version: metadata.version) ) - if let debugLogger = options.getLogger() { - let encoder = JSONEncoder() - if let jsonData = try? encoder.encode(ctxNetworkValue), - let jsonCtx = String(data: jsonData, encoding: .utf8) { - debugLogger.logMessage( - message: "[Resolve Debug] https://app.confidence.spotify.com/flags/resolver-test?context=\(jsonCtx)", - isWarning: false) - } - } - do { let result: HttpClientResult = try await self.httpClient.post(path: ":resolve", data: request) diff --git a/Tests/ConfidenceTests/Helpers/DebugLoggerFake.swift b/Tests/ConfidenceTests/Helpers/DebugLoggerFake.swift index db9ddb55..20d24a95 100644 --- a/Tests/ConfidenceTests/Helpers/DebugLoggerFake.swift +++ b/Tests/ConfidenceTests/Helpers/DebugLoggerFake.swift @@ -25,6 +25,10 @@ internal class DebugLoggerFake: DebugLogger { // no-op } + func logResolveDebugURL(flagName: String, context: ConfidenceStruct) { + // no-op + } + func getUploadBatchSuccessCount() -> Int { return uploadBatchSuccessCounter.get() }