Skip to content

Commit cd613b5

Browse files
authored
performance: convert codables to directory under a separate thread (#77)
1 parent d405596 commit cd613b5

File tree

4 files changed

+78
-31
lines changed

4 files changed

+78
-31
lines changed

Diff for: Sources/FeaturevisorSDK/Instance+Evaluation.swift

+25-25
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extension FeaturevisorInstance {
2222
reason: .disabled
2323
)
2424

25-
logger.debug("feature is disabled", evaluation.toDictionary())
25+
logger.debug("feature is disabled", evaluation)
2626

2727
return evaluation
2828
}
@@ -35,7 +35,7 @@ extension FeaturevisorInstance {
3535
variationValue: variationValue
3636
)
3737

38-
logger.debug("using sticky variation", evaluation.toDictionary())
38+
logger.debug("using sticky variation", evaluation)
3939

4040
return evaluation
4141
}
@@ -48,7 +48,7 @@ extension FeaturevisorInstance {
4848
variationValue: variationValue
4949
)
5050

51-
logger.debug("using initial variation", evaluation.toDictionary())
51+
logger.debug("using initial variation", evaluation)
5252

5353
return evaluation
5454
}
@@ -60,7 +60,7 @@ extension FeaturevisorInstance {
6060
reason: .notFound
6161
)
6262

63-
logger.warn("feature not found", evaluation.toDictionary())
63+
logger.warn("feature not found", evaluation)
6464

6565
return evaluation
6666
}
@@ -72,7 +72,7 @@ extension FeaturevisorInstance {
7272
reason: .noVariations
7373
)
7474

75-
logger.warn("no variations", evaluation.toDictionary())
75+
logger.warn("no variations", evaluation)
7676
return evaluation
7777
}
7878

@@ -97,7 +97,7 @@ extension FeaturevisorInstance {
9797
variation: variation
9898
)
9999

100-
logger.debug("forced variation found", evaluation.toDictionary())
100+
logger.debug("forced variation found", evaluation)
101101

102102
return evaluation
103103
}
@@ -133,7 +133,7 @@ extension FeaturevisorInstance {
133133
variation: variation
134134
)
135135

136-
logger.debug("override from rule", evaluation.toDictionary())
136+
logger.debug("override from rule", evaluation)
137137

138138
return evaluation
139139
}
@@ -157,7 +157,7 @@ extension FeaturevisorInstance {
157157
variation: variation
158158
)
159159

160-
logger.debug("allocated variation", evaluation.toDictionary())
160+
logger.debug("allocated variation", evaluation)
161161

162162
return evaluation
163163
}
@@ -172,7 +172,7 @@ extension FeaturevisorInstance {
172172
bucketValue: bucketResult.bucketValue
173173
)
174174

175-
logger.debug("no matched variation", evaluation.toDictionary())
175+
logger.debug("no matched variation", evaluation)
176176

177177
return evaluation
178178
}
@@ -191,7 +191,7 @@ extension FeaturevisorInstance {
191191
sticky: stickyFeature
192192
)
193193

194-
logger.debug("using sticky enabled", evaluation.toDictionary())
194+
logger.debug("using sticky enabled", evaluation)
195195

196196
return evaluation
197197
}
@@ -205,7 +205,7 @@ extension FeaturevisorInstance {
205205
initial: initialFeature
206206
)
207207

208-
logger.debug("using initial enabled", evaluation.toDictionary())
208+
logger.debug("using initial enabled", evaluation)
209209

210210
return evaluation
211211
}
@@ -219,7 +219,7 @@ extension FeaturevisorInstance {
219219
reason: .notFound
220220
)
221221

222-
logger.warn("feature not found", evaluation.toDictionary())
222+
logger.warn("feature not found", evaluation)
223223

224224
return evaluation
225225
}
@@ -247,7 +247,7 @@ extension FeaturevisorInstance {
247247
force: force
248248
)
249249

250-
logger.debug("forced enabled found", evaluation.toDictionary())
250+
logger.debug("forced enabled found", evaluation)
251251

252252
return evaluation
253253
}
@@ -336,7 +336,7 @@ extension FeaturevisorInstance {
336336
enabled: false
337337
)
338338

339-
logger.debug("not matched", evaluation.toDictionary())
339+
logger.debug("not matched", evaluation)
340340

341341
return evaluation
342342
}
@@ -353,7 +353,7 @@ extension FeaturevisorInstance {
353353
traffic: matchedTraffic
354354
)
355355

356-
logger.debug("override from rule", evaluation.toDictionary())
356+
logger.debug("override from rule", evaluation)
357357

358358
return evaluation
359359
}
@@ -401,7 +401,7 @@ extension FeaturevisorInstance {
401401
if flag.enabled == false {
402402
evaluation = Evaluation(featureKey: featureKey, reason: .disabled)
403403

404-
logger.debug("feature is disabled", evaluation.toDictionary())
404+
logger.debug("feature is disabled", evaluation)
405405

406406
return evaluation
407407
}
@@ -415,7 +415,7 @@ extension FeaturevisorInstance {
415415
variableValue: variableValue
416416
)
417417

418-
logger.debug("using sticky variable", evaluation.toDictionary())
418+
logger.debug("using sticky variable", evaluation)
419419

420420
return evaluation
421421
}
@@ -431,7 +431,7 @@ extension FeaturevisorInstance {
431431
variableValue: variableValue
432432
)
433433

434-
logger.debug("using initial variable", evaluation.toDictionary())
434+
logger.debug("using initial variable", evaluation)
435435

436436
return evaluation
437437
}
@@ -445,7 +445,7 @@ extension FeaturevisorInstance {
445445
variableKey: variableKey
446446
)
447447

448-
logger.warn("feature not found in datafile", evaluation.toDictionary())
448+
logger.warn("feature not found in datafile", evaluation)
449449

450450
return evaluation
451451
}
@@ -462,7 +462,7 @@ extension FeaturevisorInstance {
462462
variableKey: variableKey
463463
)
464464

465-
logger.warn("variable schema not found", evaluation.toDictionary())
465+
logger.warn("variable schema not found", evaluation)
466466

467467
return evaluation
468468
}
@@ -487,7 +487,7 @@ extension FeaturevisorInstance {
487487
variableSchema: variableSchema
488488
)
489489

490-
logger.debug("forced variable", evaluation.toDictionary())
490+
logger.debug("forced variable", evaluation)
491491

492492
return evaluation
493493
}
@@ -518,7 +518,7 @@ extension FeaturevisorInstance {
518518
variableSchema: variableSchema
519519
)
520520

521-
logger.debug("override from rule", evaluation.toDictionary())
521+
logger.debug("override from rule", evaluation)
522522

523523
return evaluation
524524
}
@@ -579,7 +579,7 @@ extension FeaturevisorInstance {
579579
variableSchema: variableSchema
580580
)
581581

582-
logger.debug("variable override", evaluation.toDictionary())
582+
logger.debug("variable override", evaluation)
583583

584584
return evaluation
585585
}
@@ -598,7 +598,7 @@ extension FeaturevisorInstance {
598598
variableSchema: variableSchema
599599
)
600600

601-
logger.debug("allocated variable", evaluation.toDictionary())
601+
logger.debug("allocated variable", evaluation)
602602

603603
return evaluation
604604
}
@@ -617,7 +617,7 @@ extension FeaturevisorInstance {
617617
variableSchema: variableSchema
618618
)
619619

620-
logger.debug("using default value", evaluation.toDictionary())
620+
logger.debug("using default value", evaluation)
621621

622622
return evaluation
623623
}

Diff for: Sources/FeaturevisorSDK/Instance.swift

-6
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,6 @@ public struct Evaluation: Codable {
157157
forKey: .variableSchema
158158
)
159159
}
160-
161-
func toDictionary() -> [String: Any] {
162-
guard let data = try? JSONEncoder().encode(self) else { return [:] }
163-
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments))
164-
.flatMap { $0 as? [String: Any] } ?? [:]
165-
}
166160
}
167161

168162
let emptyDatafile = DatafileContent(

Diff for: Sources/FeaturevisorSDK/Logger+Codable.swift

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Foundation
2+
3+
extension Logger {
4+
5+
func debug<T: Codable>(_ message: LogMessage, _ object: T) {
6+
Task { [weak self] in
7+
let logDetails: LogDetails? = await self?.toLogDetails(object)
8+
self?.log(level: .debug, message: message, details: logDetails)
9+
}
10+
}
11+
12+
func info<T: Codable>(_ message: LogMessage, _ object: T) {
13+
Task { [weak self] in
14+
let logDetails: LogDetails? = await self?.toLogDetails(object)
15+
self?.log(level: .info, message: message, details: logDetails)
16+
}
17+
}
18+
19+
func warn<T: Codable>(_ message: LogMessage, _ object: T) {
20+
Task { [weak self] in
21+
let logDetails: LogDetails? = await self?.toLogDetails(object)
22+
self?.log(level: .warn, message: message, details: logDetails)
23+
}
24+
}
25+
26+
func error<T: Codable>(_ message: LogMessage, _ object: T) {
27+
Task { [weak self] in
28+
let logDetails: LogDetails? = await self?.toLogDetails(object)
29+
self?.log(level: .error, message: message, details: logDetails)
30+
}
31+
}
32+
}
33+
34+
extension Logger {
35+
36+
fileprivate func toLogDetails<T: Codable>(_ object: T) async -> LogDetails? {
37+
guard let data = try? JSONEncoder().encode(object) else {
38+
return nil
39+
}
40+
41+
guard
42+
let dictionary = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
43+
else {
44+
return nil
45+
}
46+
47+
return dictionary as? LogDetails
48+
}
49+
}

Diff for: Tests/FeaturevisorSDKTests/InstanceTests.swift

+4
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ class FeaturevisorInstanceTests: XCTestCase {
791791
func testShouldEmitWarningsForDeprecatedFeature() {
792792

793793
// GIVEN
794+
let expectation: XCTestExpectation = expectation(description: "logger_log_exceptation")
794795
var deprecatedCount = 0
795796
var options: InstanceOptions = .default
796797
options.datafile = DatafileContent(
@@ -871,6 +872,7 @@ class FeaturevisorInstanceTests: XCTestCase {
871872

872873
if message.contains("is deprecated") {
873874
deprecatedCount += 1
875+
expectation.fulfill()
874876
}
875877
}
876878

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

890+
wait(for: [expectation], timeout: 1)
891+
888892
// THEN
889893
XCTAssertEqual(testVariation, "control")
890894
XCTAssertEqual(deprecatedTestVariation, "control")

0 commit comments

Comments
 (0)