Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing watchOS crash and timer startup issue, fixing watchOS sample app #372

Merged
merged 6 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions Examples/apps/BasicExample/BasicExample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

let configuration = Configuration(writeKey: "eHitWfSPZKoXF8c6iVb6QRlIPA6P9X8G")
let configuration = Configuration(writeKey: "WRITE KEY")
.trackApplicationLifecycleEvents(true)
.flushInterval(10)
.flushAt(2)

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

return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class ExtensionDelegate: NSObject, WKExtensionDelegate {
.flushInterval(10)

analytics = Analytics(configuration: configuration)
analytics?.add(plugin: ConsoleLogger(name: "consoleLogger"))
analytics?.add(plugin: NotificationTracking())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

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

/* Begin PBXFileReference section */
465879B12685058800180335 /* ConsoleLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConsoleLogger.swift; path = ../../../other_plugins/ConsoleLogger.swift; sourceTree = "<group>"; };
465879B3268641B900180335 /* SomeScreenController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SomeScreenController.swift; sourceTree = "<group>"; };
469ECD482684F9080028BE9A /* watchOSExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = watchOSExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
469ECD4C2684F9080028BE9A /* watchOSExample WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "watchOSExample WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -129,7 +127,6 @@
469ECD5F2684F9090028BE9A /* watchOSExample WatchKit Extension */ = {
isa = PBXGroup;
children = (
465879B12685058800180335 /* ConsoleLogger.swift */,
469ECD602684F9090028BE9A /* InterfaceController.swift */,
465879B3268641B900180335 /* SomeScreenController.swift */,
469ECD622684F9090028BE9A /* ExtensionDelegate.swift */,
Expand Down Expand Up @@ -291,7 +288,6 @@
469ECD672684F9090028BE9A /* ComplicationController.swift in Sources */,
469ECD632684F9090028BE9A /* ExtensionDelegate.swift in Sources */,
46E73DA626F5389E0021042C /* NotificationTracking.swift in Sources */,
465879B22685058800180335 /* ConsoleLogger.swift in Sources */,
469ECD612684F9090028BE9A /* InterfaceController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
38 changes: 26 additions & 12 deletions Sources/Segment/Utilities/Telemetry.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Foundation
import Sovran
#if os(Linux) || os(Windows)
import FoundationNetworking
#endif

public struct RemoteMetric: Codable {
let type: String
Expand Down Expand Up @@ -68,8 +71,8 @@ public class Telemetry: Subscriber {

internal var session: any HTTPSession
internal var host: String = HTTPClient.getDefaultAPIHost()
var sampleRate: Double = 0.10
private var flushTimer: Int = 30 * 1000
var sampleRate: Double = 1.0 // inital sample rate should be 1.0, will be downsampled on start
private var flushTimer: Int = 30
internal var maxQueueSize: Int = 20
var errorLogSizeMax: Int = 4000

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

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

if Double.random(in: 0...1) > sampleRate {
resetQueue()
} else {
telemetryQueue.async {
self.queue = self.queue.map { var metric = $0
metric.value = Int(Double(metric.value) / self.sampleRate)
return metric
}
}
}

telemetryTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(flushTimer) / 1000.0, repeats: true) { [weak self] _ in
self.telemetryTimer = QueueTimer(interval: .seconds(self.flushTimer), queue: .main) { [weak self] in
if (!(self?.enable ?? false)) {
self?.started = false
self?.telemetryTimer?.invalidate()
self?.telemetryTimer?.suspend()
}
self?.flush()
}
}

/// Resets the telemetry state, including the queue and seen errors.
func reset() {
telemetryTimer?.invalidate()
telemetryTimer?.suspend()
resetQueue()
seenErrors.removeAll()
started = false
Expand All @@ -121,10 +132,12 @@ public class Telemetry: Subscriber {
/// - metric: The metric name.
/// - buildTags: A closure to build the tags dictionary.
func increment(metric: String, buildTags: (inout [String: String]) -> Void) {
guard enable, sampleRate > 0.0 && sampleRate <= 1.0, metric.hasPrefix(Telemetry.METRICS_BASE_TAG), queueHasSpace() else { return }

var tags = [String: String]()
buildTags(&tags)
guard !tags.isEmpty else { return }

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

addRemoteMetric(metric: metric, tags: tags)
Expand All @@ -136,10 +149,11 @@ public class Telemetry: Subscriber {
/// - log: The log data.
/// - buildTags: A closure to build the tags dictionary.
func error(metric: String, log: String, buildTags: (inout [String: String]) -> Void) {
guard enable, sampleRate > 0.0 && sampleRate <= 1.0, metric.hasPrefix(Telemetry.METRICS_BASE_TAG), queueHasSpace() else { return }

var tags = [String: String]()
buildTags(&tags)

guard enable, sampleRate > 0.0 && sampleRate <= 1.0, metric.hasPrefix(Telemetry.METRICS_BASE_TAG), !tags.isEmpty, queueHasSpace() else { return }
guard !tags.isEmpty else { return }

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

telemetryQueue.sync {
if var found = queue.first(where: { $0.metric == metric && $0.tags == fullTags }) {
found.value += value
if let index = queue.firstIndex(where: { $0.metric == metric && $0.tags == fullTags }) {
queue[index].value += value
return
}

Expand All @@ -275,7 +289,7 @@ public class Telemetry: Subscriber {
public func subscribe(_ store: Store) {
store.subscribe(self,
initialState: true,
queue: telemetryQueue,
queue: updateQueue,
handler: systemUpdate
)
}
Expand Down
6 changes: 5 additions & 1 deletion Tests/Segment-Tests/Telemetry_Tests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if !os(Linux) && !os(Windows)
import XCTest

@testable import Segment

class TelemetryTests: XCTestCase {
Expand Down Expand Up @@ -163,4 +165,6 @@ class URLSessionMock: RestrictedHTTPSession {
// Mock URLSessionDataTask
class URLSessionDataTaskMock: URLSessionDataTask, @unchecked Sendable {
override func resume() {}
}
}

#endif
Loading