Skip to content

Commit 391e40c

Browse files
authored
Fixing watchOS crash and timer startup issue, fixing watchOS sample app (#372)
* Fixing watchOS crash and timer startup issue, fixing watchOS sample app
1 parent 64f8656 commit 391e40c

File tree

5 files changed

+33
-24
lines changed

5 files changed

+33
-24
lines changed

Diff for: Examples/apps/BasicExample/BasicExample/AppDelegate.swift

+1-5
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1616
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
1717
// Override point for customization after application launch.
1818

19-
let configuration = Configuration(writeKey: "eHitWfSPZKoXF8c6iVb6QRlIPA6P9X8G")
19+
let configuration = Configuration(writeKey: "WRITE KEY")
2020
.trackApplicationLifecycleEvents(true)
2121
.flushInterval(10)
2222
.flushAt(2)
2323

24-
Telemetry.shared.flushTimer = 5 * 1000
25-
Telemetry.shared.enable = true
26-
// Telemetry.shared.sendErrorLogData = true
27-
// Telemetry.shared.host = "webhook.site/8d339731-c5a7-45b5-9b82-d545b6e48e6c"
2824
analytics = Analytics(configuration: configuration)
2925

3026
return true

Diff for: Examples/apps/watchOSExample/watchOSExample WatchKit Extension/ExtensionDelegate.swift

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class ExtensionDelegate: NSObject, WKExtensionDelegate {
1818
.flushInterval(10)
1919

2020
analytics = Analytics(configuration: configuration)
21-
analytics?.add(plugin: ConsoleLogger(name: "consoleLogger"))
2221
analytics?.add(plugin: NotificationTracking())
2322
}
2423

Diff for: Examples/apps/watchOSExample/watchOSExample.xcodeproj/project.pbxproj

+1-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 52;
6+
objectVersion = 54;
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
465879B22685058800180335 /* ConsoleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 465879B12685058800180335 /* ConsoleLogger.swift */; };
1110
465879B4268641B900180335 /* SomeScreenController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 465879B3268641B900180335 /* SomeScreenController.swift */; };
1211
469ECD4D2684F9080028BE9A /* watchOSExample WatchKit App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 469ECD4C2684F9080028BE9A /* watchOSExample WatchKit App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
1312
469ECD532684F9080028BE9A /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 469ECD512684F9080028BE9A /* Interface.storyboard */; };
@@ -65,7 +64,6 @@
6564
/* End PBXCopyFilesBuildPhase section */
6665

6766
/* Begin PBXFileReference section */
68-
465879B12685058800180335 /* ConsoleLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConsoleLogger.swift; path = ../../../other_plugins/ConsoleLogger.swift; sourceTree = "<group>"; };
6967
465879B3268641B900180335 /* SomeScreenController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SomeScreenController.swift; sourceTree = "<group>"; };
7068
469ECD482684F9080028BE9A /* watchOSExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = watchOSExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
7169
469ECD4C2684F9080028BE9A /* watchOSExample WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "watchOSExample WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -129,7 +127,6 @@
129127
469ECD5F2684F9090028BE9A /* watchOSExample WatchKit Extension */ = {
130128
isa = PBXGroup;
131129
children = (
132-
465879B12685058800180335 /* ConsoleLogger.swift */,
133130
469ECD602684F9090028BE9A /* InterfaceController.swift */,
134131
465879B3268641B900180335 /* SomeScreenController.swift */,
135132
469ECD622684F9090028BE9A /* ExtensionDelegate.swift */,
@@ -291,7 +288,6 @@
291288
469ECD672684F9090028BE9A /* ComplicationController.swift in Sources */,
292289
469ECD632684F9090028BE9A /* ExtensionDelegate.swift in Sources */,
293290
46E73DA626F5389E0021042C /* NotificationTracking.swift in Sources */,
294-
465879B22685058800180335 /* ConsoleLogger.swift in Sources */,
295291
469ECD612684F9090028BE9A /* InterfaceController.swift in Sources */,
296292
);
297293
runOnlyForDeploymentPostprocessing = 0;

Diff for: Sources/Segment/Utilities/Telemetry.swift

+26-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import Foundation
22
import Sovran
3+
#if os(Linux) || os(Windows)
4+
import FoundationNetworking
5+
#endif
36

47
public struct RemoteMetric: Codable {
58
let type: String
@@ -68,8 +71,8 @@ public class Telemetry: Subscriber {
6871

6972
internal var session: any HTTPSession
7073
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
7376
internal var maxQueueSize: Int = 20
7477
var errorLogSizeMax: Int = 4000
7578

@@ -87,7 +90,8 @@ public class Telemetry: Subscriber {
8790
internal var started = false
8891
private var rateLimitEndTime: TimeInterval = 0
8992
private var telemetryQueue = DispatchQueue(label: "telemetryQueue")
90-
private var telemetryTimer: Timer?
93+
private var updateQueue = DispatchQueue(label: "updateQueue")
94+
private var telemetryTimer: QueueTimer?
9195

9296
/// Starts the Telemetry send loop. Requires both `enable` to be set and a configuration to be retrieved from Segment.
9397
func start() {
@@ -96,20 +100,27 @@ public class Telemetry: Subscriber {
96100

97101
if Double.random(in: 0...1) > sampleRate {
98102
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+
}
99110
}
100111

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
102113
if (!(self?.enable ?? false)) {
103114
self?.started = false
104-
self?.telemetryTimer?.invalidate()
115+
self?.telemetryTimer?.suspend()
105116
}
106117
self?.flush()
107118
}
108119
}
109120

110121
/// Resets the telemetry state, including the queue and seen errors.
111122
func reset() {
112-
telemetryTimer?.invalidate()
123+
telemetryTimer?.suspend()
113124
resetQueue()
114125
seenErrors.removeAll()
115126
started = false
@@ -121,10 +132,12 @@ public class Telemetry: Subscriber {
121132
/// - metric: The metric name.
122133
/// - buildTags: A closure to build the tags dictionary.
123134
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+
124137
var tags = [String: String]()
125138
buildTags(&tags)
139+
guard !tags.isEmpty else { return }
126140

127-
guard enable, sampleRate > 0.0 && sampleRate <= 1.0, metric.hasPrefix(Telemetry.METRICS_BASE_TAG), !tags.isEmpty, queueHasSpace() else { return }
128141
if Double.random(in: 0...1) > sampleRate { return }
129142

130143
addRemoteMetric(metric: metric, tags: tags)
@@ -136,10 +149,11 @@ public class Telemetry: Subscriber {
136149
/// - log: The log data.
137150
/// - buildTags: A closure to build the tags dictionary.
138151
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+
139154
var tags = [String: String]()
140155
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 }
143157

144158
var filteredTags = tags
145159
if (!sendWriteKeyOnError) {
@@ -248,8 +262,8 @@ public class Telemetry: Subscriber {
248262
let fullTags = tags.merging(additionalTags) { (_, new) in new }
249263

250264
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
253267
return
254268
}
255269

@@ -275,7 +289,7 @@ public class Telemetry: Subscriber {
275289
public func subscribe(_ store: Store) {
276290
store.subscribe(self,
277291
initialState: true,
278-
queue: telemetryQueue,
292+
queue: updateQueue,
279293
handler: systemUpdate
280294
)
281295
}

Diff for: Tests/Segment-Tests/Telemetry_Tests.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
#if !os(Linux) && !os(Windows)
12
import XCTest
3+
24
@testable import Segment
35

46
class TelemetryTests: XCTestCase {
@@ -163,4 +165,6 @@ class URLSessionMock: RestrictedHTTPSession {
163165
// Mock URLSessionDataTask
164166
class URLSessionDataTaskMock: URLSessionDataTask, @unchecked Sendable {
165167
override func resume() {}
166-
}
168+
}
169+
170+
#endif

0 commit comments

Comments
 (0)