Skip to content

Commit

Permalink
performance: convert codables to directory under a separate thread (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
polok authored Oct 23, 2024
1 parent d405596 commit cd613b5
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 31 deletions.
50 changes: 25 additions & 25 deletions Sources/FeaturevisorSDK/Instance+Evaluation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension FeaturevisorInstance {
reason: .disabled
)

logger.debug("feature is disabled", evaluation.toDictionary())
logger.debug("feature is disabled", evaluation)

return evaluation
}
Expand All @@ -35,7 +35,7 @@ extension FeaturevisorInstance {
variationValue: variationValue
)

logger.debug("using sticky variation", evaluation.toDictionary())
logger.debug("using sticky variation", evaluation)

return evaluation
}
Expand All @@ -48,7 +48,7 @@ extension FeaturevisorInstance {
variationValue: variationValue
)

logger.debug("using initial variation", evaluation.toDictionary())
logger.debug("using initial variation", evaluation)

return evaluation
}
Expand All @@ -60,7 +60,7 @@ extension FeaturevisorInstance {
reason: .notFound
)

logger.warn("feature not found", evaluation.toDictionary())
logger.warn("feature not found", evaluation)

return evaluation
}
Expand All @@ -72,7 +72,7 @@ extension FeaturevisorInstance {
reason: .noVariations
)

logger.warn("no variations", evaluation.toDictionary())
logger.warn("no variations", evaluation)
return evaluation
}

Expand All @@ -97,7 +97,7 @@ extension FeaturevisorInstance {
variation: variation
)

logger.debug("forced variation found", evaluation.toDictionary())
logger.debug("forced variation found", evaluation)

return evaluation
}
Expand Down Expand Up @@ -133,7 +133,7 @@ extension FeaturevisorInstance {
variation: variation
)

logger.debug("override from rule", evaluation.toDictionary())
logger.debug("override from rule", evaluation)

return evaluation
}
Expand All @@ -157,7 +157,7 @@ extension FeaturevisorInstance {
variation: variation
)

logger.debug("allocated variation", evaluation.toDictionary())
logger.debug("allocated variation", evaluation)

return evaluation
}
Expand All @@ -172,7 +172,7 @@ extension FeaturevisorInstance {
bucketValue: bucketResult.bucketValue
)

logger.debug("no matched variation", evaluation.toDictionary())
logger.debug("no matched variation", evaluation)

return evaluation
}
Expand All @@ -191,7 +191,7 @@ extension FeaturevisorInstance {
sticky: stickyFeature
)

logger.debug("using sticky enabled", evaluation.toDictionary())
logger.debug("using sticky enabled", evaluation)

return evaluation
}
Expand All @@ -205,7 +205,7 @@ extension FeaturevisorInstance {
initial: initialFeature
)

logger.debug("using initial enabled", evaluation.toDictionary())
logger.debug("using initial enabled", evaluation)

return evaluation
}
Expand All @@ -219,7 +219,7 @@ extension FeaturevisorInstance {
reason: .notFound
)

logger.warn("feature not found", evaluation.toDictionary())
logger.warn("feature not found", evaluation)

return evaluation
}
Expand Down Expand Up @@ -247,7 +247,7 @@ extension FeaturevisorInstance {
force: force
)

logger.debug("forced enabled found", evaluation.toDictionary())
logger.debug("forced enabled found", evaluation)

return evaluation
}
Expand Down Expand Up @@ -336,7 +336,7 @@ extension FeaturevisorInstance {
enabled: false
)

logger.debug("not matched", evaluation.toDictionary())
logger.debug("not matched", evaluation)

return evaluation
}
Expand All @@ -353,7 +353,7 @@ extension FeaturevisorInstance {
traffic: matchedTraffic
)

logger.debug("override from rule", evaluation.toDictionary())
logger.debug("override from rule", evaluation)

return evaluation
}
Expand Down Expand Up @@ -401,7 +401,7 @@ extension FeaturevisorInstance {
if flag.enabled == false {
evaluation = Evaluation(featureKey: featureKey, reason: .disabled)

logger.debug("feature is disabled", evaluation.toDictionary())
logger.debug("feature is disabled", evaluation)

return evaluation
}
Expand All @@ -415,7 +415,7 @@ extension FeaturevisorInstance {
variableValue: variableValue
)

logger.debug("using sticky variable", evaluation.toDictionary())
logger.debug("using sticky variable", evaluation)

return evaluation
}
Expand All @@ -431,7 +431,7 @@ extension FeaturevisorInstance {
variableValue: variableValue
)

logger.debug("using initial variable", evaluation.toDictionary())
logger.debug("using initial variable", evaluation)

return evaluation
}
Expand All @@ -445,7 +445,7 @@ extension FeaturevisorInstance {
variableKey: variableKey
)

logger.warn("feature not found in datafile", evaluation.toDictionary())
logger.warn("feature not found in datafile", evaluation)

return evaluation
}
Expand All @@ -462,7 +462,7 @@ extension FeaturevisorInstance {
variableKey: variableKey
)

logger.warn("variable schema not found", evaluation.toDictionary())
logger.warn("variable schema not found", evaluation)

return evaluation
}
Expand All @@ -487,7 +487,7 @@ extension FeaturevisorInstance {
variableSchema: variableSchema
)

logger.debug("forced variable", evaluation.toDictionary())
logger.debug("forced variable", evaluation)

return evaluation
}
Expand Down Expand Up @@ -518,7 +518,7 @@ extension FeaturevisorInstance {
variableSchema: variableSchema
)

logger.debug("override from rule", evaluation.toDictionary())
logger.debug("override from rule", evaluation)

return evaluation
}
Expand Down Expand Up @@ -579,7 +579,7 @@ extension FeaturevisorInstance {
variableSchema: variableSchema
)

logger.debug("variable override", evaluation.toDictionary())
logger.debug("variable override", evaluation)

return evaluation
}
Expand All @@ -598,7 +598,7 @@ extension FeaturevisorInstance {
variableSchema: variableSchema
)

logger.debug("allocated variable", evaluation.toDictionary())
logger.debug("allocated variable", evaluation)

return evaluation
}
Expand All @@ -617,7 +617,7 @@ extension FeaturevisorInstance {
variableSchema: variableSchema
)

logger.debug("using default value", evaluation.toDictionary())
logger.debug("using default value", evaluation)

return evaluation
}
Expand Down
6 changes: 0 additions & 6 deletions Sources/FeaturevisorSDK/Instance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,6 @@ public struct Evaluation: Codable {
forKey: .variableSchema
)
}

func toDictionary() -> [String: Any] {
guard let data = try? JSONEncoder().encode(self) else { return [:] }
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments))
.flatMap { $0 as? [String: Any] } ?? [:]
}
}

let emptyDatafile = DatafileContent(
Expand Down
49 changes: 49 additions & 0 deletions Sources/FeaturevisorSDK/Logger+Codable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Foundation

extension Logger {

func debug<T: Codable>(_ message: LogMessage, _ object: T) {
Task { [weak self] in
let logDetails: LogDetails? = await self?.toLogDetails(object)
self?.log(level: .debug, message: message, details: logDetails)
}
}

func info<T: Codable>(_ message: LogMessage, _ object: T) {
Task { [weak self] in
let logDetails: LogDetails? = await self?.toLogDetails(object)
self?.log(level: .info, message: message, details: logDetails)
}
}

func warn<T: Codable>(_ message: LogMessage, _ object: T) {
Task { [weak self] in
let logDetails: LogDetails? = await self?.toLogDetails(object)
self?.log(level: .warn, message: message, details: logDetails)
}
}

func error<T: Codable>(_ message: LogMessage, _ object: T) {
Task { [weak self] in
let logDetails: LogDetails? = await self?.toLogDetails(object)
self?.log(level: .error, message: message, details: logDetails)
}
}
}

extension Logger {

fileprivate func toLogDetails<T: Codable>(_ object: T) async -> LogDetails? {
guard let data = try? JSONEncoder().encode(object) else {
return nil
}

guard
let dictionary = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
else {
return nil
}

return dictionary as? LogDetails
}
}
4 changes: 4 additions & 0 deletions Tests/FeaturevisorSDKTests/InstanceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ class FeaturevisorInstanceTests: XCTestCase {
func testShouldEmitWarningsForDeprecatedFeature() {

// GIVEN
let expectation: XCTestExpectation = expectation(description: "logger_log_exceptation")
var deprecatedCount = 0
var options: InstanceOptions = .default
options.datafile = DatafileContent(
Expand Down Expand Up @@ -871,6 +872,7 @@ class FeaturevisorInstanceTests: XCTestCase {

if message.contains("is deprecated") {
deprecatedCount += 1
expectation.fulfill()
}
}

Expand All @@ -885,6 +887,8 @@ class FeaturevisorInstanceTests: XCTestCase {
context: ["userId": .string("123")]
)

wait(for: [expectation], timeout: 1)

// THEN
XCTAssertEqual(testVariation, "control")
XCTAssertEqual(deprecatedTestVariation, "control")
Expand Down

0 comments on commit cd613b5

Please sign in to comment.