1
1
import Foundation
2
2
import Sovran
3
+ #if os(Linux) || os(Windows)
4
+ import FoundationNetworking
5
+ #endif
3
6
4
7
public struct RemoteMetric : Codable {
5
8
let type : String
@@ -68,8 +71,8 @@ public class Telemetry: Subscriber {
68
71
69
72
internal var session : any HTTPSession
70
73
internal var host : String = HTTPClient . getDefaultAPIHost ( )
71
- var sampleRate : Double = 0.10
72
- private var flushTimer : Int = 30 * 1000
74
+ var sampleRate : Double = 1.0 // inital sample rate should be 1.0, will be downsampled on start
75
+ private var flushTimer : Int = 30
73
76
internal var maxQueueSize : Int = 20
74
77
var errorLogSizeMax : Int = 4000
75
78
@@ -87,7 +90,8 @@ public class Telemetry: Subscriber {
87
90
internal var started = false
88
91
private var rateLimitEndTime : TimeInterval = 0
89
92
private var telemetryQueue = DispatchQueue ( label: " telemetryQueue " )
90
- private var telemetryTimer : Timer ?
93
+ private var updateQueue = DispatchQueue ( label: " updateQueue " )
94
+ private var telemetryTimer : QueueTimer ?
91
95
92
96
/// Starts the Telemetry send loop. Requires both `enable` to be set and a configuration to be retrieved from Segment.
93
97
func start( ) {
@@ -96,20 +100,27 @@ public class Telemetry: Subscriber {
96
100
97
101
if Double . random ( in: 0 ... 1 ) > sampleRate {
98
102
resetQueue ( )
103
+ } else {
104
+ telemetryQueue. async {
105
+ self . queue = self . queue. map { var metric = $0
106
+ metric. value = Int ( Double ( metric. value) / self . sampleRate)
107
+ return metric
108
+ }
109
+ }
99
110
}
100
111
101
- telemetryTimer = Timer . scheduledTimer ( withTimeInterval : TimeInterval ( flushTimer) / 1000.0 , repeats : true ) { [ weak self] _ in
112
+ self . telemetryTimer = QueueTimer ( interval : . seconds ( self . flushTimer) , queue : . main ) { [ weak self] in
102
113
if ( !( self ? . enable ?? false ) ) {
103
114
self ? . started = false
104
- self ? . telemetryTimer? . invalidate ( )
115
+ self ? . telemetryTimer? . suspend ( )
105
116
}
106
117
self ? . flush ( )
107
118
}
108
119
}
109
120
110
121
/// Resets the telemetry state, including the queue and seen errors.
111
122
func reset( ) {
112
- telemetryTimer? . invalidate ( )
123
+ telemetryTimer? . suspend ( )
113
124
resetQueue ( )
114
125
seenErrors. removeAll ( )
115
126
started = false
@@ -121,10 +132,12 @@ public class Telemetry: Subscriber {
121
132
/// - metric: The metric name.
122
133
/// - buildTags: A closure to build the tags dictionary.
123
134
func increment( metric: String , buildTags: ( inout [ String : String ] ) -> Void ) {
135
+ guard enable, sampleRate > 0.0 && sampleRate <= 1.0 , metric. hasPrefix ( Telemetry . METRICS_BASE_TAG) , queueHasSpace ( ) else { return }
136
+
124
137
var tags = [ String: String] ( )
125
138
buildTags ( & tags)
139
+ guard !tags. isEmpty else { return }
126
140
127
- guard enable, sampleRate > 0.0 && sampleRate <= 1.0 , metric. hasPrefix ( Telemetry . METRICS_BASE_TAG) , !tags. isEmpty, queueHasSpace ( ) else { return }
128
141
if Double . random ( in: 0 ... 1 ) > sampleRate { return }
129
142
130
143
addRemoteMetric ( metric: metric, tags: tags)
@@ -136,10 +149,11 @@ public class Telemetry: Subscriber {
136
149
/// - log: The log data.
137
150
/// - buildTags: A closure to build the tags dictionary.
138
151
func error( metric: String , log: String , buildTags: ( inout [ String : String ] ) -> Void ) {
152
+ guard enable, sampleRate > 0.0 && sampleRate <= 1.0 , metric. hasPrefix ( Telemetry . METRICS_BASE_TAG) , queueHasSpace ( ) else { return }
153
+
139
154
var tags = [ String: String] ( )
140
155
buildTags ( & tags)
141
-
142
- guard enable, sampleRate > 0.0 && sampleRate <= 1.0 , metric. hasPrefix ( Telemetry . METRICS_BASE_TAG) , !tags. isEmpty, queueHasSpace ( ) else { return }
156
+ guard !tags. isEmpty else { return }
143
157
144
158
var filteredTags = tags
145
159
if ( !sendWriteKeyOnError) {
@@ -248,8 +262,8 @@ public class Telemetry: Subscriber {
248
262
let fullTags = tags. merging ( additionalTags) { ( _, new) in new }
249
263
250
264
telemetryQueue. sync {
251
- if var found = queue. first ( where: { $0. metric == metric && $0. tags == fullTags } ) {
252
- found . value += value
265
+ if let index = queue. firstIndex ( where: { $0. metric == metric && $0. tags == fullTags } ) {
266
+ queue [ index ] . value += value
253
267
return
254
268
}
255
269
@@ -275,7 +289,7 @@ public class Telemetry: Subscriber {
275
289
public func subscribe( _ store: Store ) {
276
290
store. subscribe ( self ,
277
291
initialState: true ,
278
- queue: telemetryQueue ,
292
+ queue: updateQueue ,
279
293
handler: systemUpdate
280
294
)
281
295
}
0 commit comments