-
Notifications
You must be signed in to change notification settings - Fork 192
/
Copy pathEventsClient.swift
162 lines (130 loc) · 5.14 KB
/
EventsClient.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import Foundation
public protocol EventsClientProtocol {
func startTrace(topic: String)
func saveTraceEvent(_ event: TraceEventItem)
func setTopic(_ topic: String)
func setTelemetryEnabled(_ enabled: Bool)
func saveMessageEvent(_ event: MessageEventType)
}
public class EventsClient: EventsClientProtocol {
private let eventsCollector: EventsCollector
private let eventsDispatcher: EventsDispatcher
private let logger: ConsoleLogging
private var stateStorage: TelemetryStateStorage
private let messageEventsStorage: MessageEventsStorage
private let initEventsStorage: InitEventsStorage
init(
eventsCollector: EventsCollector,
eventsDispatcher: EventsDispatcher,
logger: ConsoleLogging,
stateStorage: TelemetryStateStorage,
messageEventsStorage: MessageEventsStorage,
initEventsStorage: InitEventsStorage
) {
self.eventsCollector = eventsCollector
self.eventsDispatcher = eventsDispatcher
self.logger = logger
self.stateStorage = stateStorage
self.messageEventsStorage = messageEventsStorage
self.initEventsStorage = initEventsStorage
if !stateStorage.telemetryEnabled {
self.eventsCollector.storage.clearErrorEvents()
}
saveInitEvent()
Task { await sendStoredEvents() }
}
public func setLogging(level: LoggingLevel) {
logger.setLogging(level: level)
}
// Public method to start trace
public func startTrace(topic: String) {
guard stateStorage.telemetryEnabled else { return }
logger.debug("Will start trace with topic: \(topic)")
eventsCollector.startTrace(topic: topic)
}
public func setTopic(_ topic: String) {
guard stateStorage.telemetryEnabled else { return }
eventsCollector.setTopic(topic)
}
// Public method to save event
public func saveTraceEvent(_ event: TraceEventItem) {
guard stateStorage.telemetryEnabled else { return }
logger.debug("Will store a trace event: \(event)")
eventsCollector.saveEvent(event)
}
public func saveMessageEvent(_ event: MessageEventType) {
logger.debug("Will store a message event: \(event)")
messageEventsStorage.saveMessageEvent(event)
}
public func saveInitEvent() {
logger.debug("Will store an init event")
let bundleId = Bundle.main.bundleIdentifier ?? "Unknown"
let clientId = (try? Networking.interactor.getClientId()) ?? "Unknown"
let userAgent = EnvironmentInfo.userAgent
let props = InitEvent.Props(
properties: InitEvent.Properties(
clientId: clientId,
userAgent: userAgent
)
)
let event = InitEvent(
eventId: UUID().uuidString,
bundleId: bundleId,
timestamp: Int64(Date().timeIntervalSince1970 * 1000),
props: props
)
initEventsStorage.saveInitEvent(event)
}
// Public method to set telemetry enabled or disabled
public func setTelemetryEnabled(_ enabled: Bool) {
stateStorage.telemetryEnabled = enabled
if enabled {
Task { await sendStoredEvents() }
} else {
eventsCollector.storage.clearErrorEvents()
}
}
private func sendStoredEvents() async {
guard stateStorage.telemetryEnabled else { return }
let traceEvents = eventsCollector.storage.fetchErrorEvents()
let messageEvents = messageEventsStorage.fetchMessageEvents()
let initEvents = initEventsStorage.fetchInitEvents()
guard !traceEvents.isEmpty || !messageEvents.isEmpty || !initEvents.isEmpty else { return }
var combinedEvents: [AnyCodable] = []
combinedEvents.append(contentsOf: traceEvents.map { AnyCodable($0) })
combinedEvents.append(contentsOf: messageEvents.map { AnyCodable($0) })
combinedEvents.append(contentsOf: initEvents.map { AnyCodable($0) })
logger.debug("Will send combined events")
do {
let success: Bool = try await eventsDispatcher.executeWithRetry(events: combinedEvents)
if success {
logger.debug("Combined events sent successfully")
eventsCollector.storage.clearErrorEvents()
messageEventsStorage.clearMessageEvents()
initEventsStorage.clearInitEvents()
}
} catch {
logger.debug("Failed to send events after multiple attempts: \(error)")
}
}
}
#if DEBUG
public class MockEventsClient: EventsClientProtocol {
var startTraceCalled = false
var saveEventCalled = false
var telemetryEnabled = true
public init() {}
public func startTrace(topic: String) {
startTraceCalled = true
}
public func setTopic(_ topic: String) {}
public func saveTraceEvent(_ event: TraceEventItem) {
saveEventCalled = true
}
public func setTelemetryEnabled(_ enabled: Bool) {
telemetryEnabled = enabled
}
public func saveMessageEvent(_ event: MessageEventType) {
}
}
#endif