Skip to content

Commit

Permalink
perf: Proto encode telemetry data
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziodemaria committed Nov 7, 2024
1 parent 8407647 commit 64072a4
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 63 deletions.
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "SwiftProtobuf",
"repositoryURL": "https://github.com/apple/swift-protobuf.git",
"state": {
"branch": null,
"revision": "ebc7251dd5b37f627c93698e4374084d98409633",
"version": "1.28.2"
}
},
{
"package": "OpenFeature",
"repositoryURL": "[email protected]:open-feature/swift-sdk.git",
Expand Down
5 changes: 4 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ let package = Package(
],
dependencies: [
.package(url: "[email protected]:open-feature/swift-sdk.git", from: "0.1.0"),
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.0.0"),
],
targets: [
.target(
name: "Confidence",
dependencies: [],
dependencies: [
.product(name: "SwiftProtobuf", package: "swift-protobuf")
],
plugins: []
),
.target(
Expand Down
2 changes: 1 addition & 1 deletion Sources/Confidence/Apply/FlagApplierWithRetries.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ final class FlagApplierWithRetries: FlagApplier {
request: ApplyFlagsRequest
) async -> ApplyFlagResult {
do {
let header = telemetry.getSnapshot()
let header: Data = telemetry.getSnapshot()
return try await httpClient.post(path: ":apply", data: request, header: header)
} catch {
return .failure(handleError(error: error))
Expand Down
2 changes: 1 addition & 1 deletion Sources/Confidence/Http/HttpClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ typealias HttpClientResult<T> = Result<HttpClientResponse<T>, Error>

internal protocol HttpClient {
func post<T: Decodable>(path: String, data: Encodable) async throws -> HttpClientResult<T>
func post<T: Decodable>(path: String, data: Encodable, header: Encodable) async throws -> HttpClientResult<T>
func post<T: Decodable>(path: String, data: Encodable, header: Data) async throws -> HttpClientResult<T>
}

struct HttpClientResponse<T> {
Expand Down
28 changes: 6 additions & 22 deletions Sources/Confidence/Http/NetworkClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class NetworkClient: HttpClient {
self.timeoutIntervalForRequests = timeoutIntervalForRequests
}

func post<T>(path: String, data: any Encodable, header: any Encodable) async throws -> HttpClientResult<T> where T : Decodable {
func post<T>(path: String, data: any Encodable, header: Data) async throws -> HttpClientResult<T> where T : Decodable {

Check failure on line 32 in Sources/Confidence/Http/NetworkClient.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Colon Spacing Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals (colon)
let request = try buildRequest(path: path, data: data, header: header)
return try await post(request: request)
}
Expand Down Expand Up @@ -107,7 +107,7 @@ extension NetworkClient {
return URL(string: "\(normalisedBase)\(normalisedPath)")
}

private func buildRequest(path: String, data: Encodable, header: Encodable? = nil) throws -> URLRequest {
private func buildRequest(path: String, data: Encodable, header: Data? = nil) throws -> URLRequest {
guard let url = constructURL(base: baseUrl, path: path) else {
throw ConfidenceError.internalError(message: "Could not create service url")
}
Expand All @@ -123,26 +123,10 @@ extension NetworkClient {
encoder.dateEncodingStrategy = .iso8601

if let header = header {
let jsonHeaderData = try encoder.encode(header)

if let headerJsonString = String(data: jsonHeaderData, encoding: .utf8) {
request.addValue(headerJsonString, forHTTPHeaderField: "Confidence-Metadata")
}
}
// TMP - TESTING
if let headers = request.allHTTPHeaderFields, let metadata = headers["Confidence-Metadata"] {
if let data = metadata.data(using: .utf8) {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
let prettyData = try JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)

if let prettyPrintedString = String(data: prettyData, encoding: .utf8) {
print(prettyPrintedString)
}
} catch {
print("Failed to pretty print JSON: \(error)")
}
}
request.addValue(header.base64EncodedString(), forHTTPHeaderField: "Confidence-Metadata")
// TMP - TESTING
let telemetryData = try LibraryData(serializedBytes: header)
print(telemetryData)
}

let jsonData = try encoder.encode(data)
Expand Down
40 changes: 26 additions & 14 deletions Sources/Confidence/Telemetry/TelemetryManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,39 @@ import Foundation
protocol TelemetryManager {
func incrementStaleAccess()
func incrementFlagTypeMismatch()
func getSnapshot() -> TelemetryPayload
func getSnapshot() -> Data
}

class Telemetry: TelemetryManager {
private let queue = DispatchQueue(label: "com.confidence.telemetry_manager")
private var staleAccessCounter = 0;
private var flagTypeMismatchCounter = 0;
private var staleAccessCounter: Int32 = 0;

Check failure on line 11 in Sources/Confidence/Telemetry/TelemetryManager.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Semicolon Violation: Lines should not have trailing semicolons (trailing_semicolon)
private var flagTypeMismatchCounter: Int32 = 0;

Check failure on line 12 in Sources/Confidence/Telemetry/TelemetryManager.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Semicolon Violation: Lines should not have trailing semicolons (trailing_semicolon)

public init() {}

static public let shared: TelemetryManager = Telemetry.init()

public func getSnapshot() -> TelemetryPayload {
TelemetryPayload(
libraryId: ConfidenceMetadata.defaultMetadata.id,
libraryVersion: ConfidenceMetadata.defaultMetadata.version,
countTraces: [
CountTrace.init(traceId: TraceId.staleAccess, count: getStaleAccessAndReset()),
CountTrace.init(traceId: TraceId.typeMismatch, count: getFlagTypeMismatchAndReset()),
],
durationsTraces: [])
public func getSnapshot() -> Data {
// Initialize your data using the generated types
var countTrace1 = CountTrace()
countTrace1.traceID = .traceStale
countTrace1.count = getStaleAccessAndReset()

var countTrace2 = CountTrace()
countTrace2.traceID = .traceTypeMismatch
countTrace2.count = getFlagTypeMismatchAndReset()

var libraryData = LibraryData()
libraryData.countTraces = [countTrace1, countTrace2]
libraryData.libraryID = .sdkSwiftCore
libraryData.libraryVersion = "1.0.1"
libraryData.durationsTraces = []
do {
return try libraryData.serializedData()
} catch {
print("Failed to encode telemetry data: \(error)")
return Data()
}
}

public func incrementStaleAccess() {
Expand All @@ -38,15 +50,15 @@ class Telemetry: TelemetryManager {
}
}

private func getStaleAccessAndReset() -> Int {
private func getStaleAccessAndReset() -> Int32 {
return queue.sync {
let currentCounter = staleAccessCounter
staleAccessCounter = 0;

Check failure on line 56 in Sources/Confidence/Telemetry/TelemetryManager.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Semicolon Violation: Lines should not have trailing semicolons (trailing_semicolon)
return currentCounter
}
}

private func getFlagTypeMismatchAndReset() -> Int {
private func getFlagTypeMismatchAndReset() -> Int32 {
return queue.sync {
let currentCounter = flagTypeMismatchCounter
flagTypeMismatchCounter = 0;

Check failure on line 64 in Sources/Confidence/Telemetry/TelemetryManager.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Trailing Semicolon Violation: Lines should not have trailing semicolons (trailing_semicolon)
Expand Down
Loading

0 comments on commit 64072a4

Please sign in to comment.