Skip to content

Commit a7238b2

Browse files
authored
Merge pull request #241 from TelemetryDeck/feature/stop-duration-options
Add more options to new Duration Signals feature
2 parents 41dfe21 + 514193a commit a7238b2

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

Sources/TelemetryDeck/Helpers/DurationSignalTracker.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ final class DurationSignalTracker: @unchecked Sendable {
1313
private struct CachedData: Sendable {
1414
let startTime: Date
1515
let parameters: [String: String]
16+
let includeBackgroundTime: Bool
1617
}
1718

1819
private let queue = DispatchQueue(label: "com.telemetrydeck.DurationSignalTracker")
@@ -23,9 +24,13 @@ final class DurationSignalTracker: @unchecked Sendable {
2324
self.setupAppLifecycleObservers()
2425
}
2526

26-
func startTracking(_ signalName: String, parameters: [String: String]) {
27+
func startTracking(_ signalName: String, parameters: [String: String], includeBackgroundTime: Bool) {
2728
self.queue.sync {
28-
self.startedSignals[signalName] = CachedData(startTime: Date(), parameters: parameters)
29+
self.startedSignals[signalName] = CachedData(
30+
startTime: Date(),
31+
parameters: parameters,
32+
includeBackgroundTime: includeBackgroundTime
33+
)
2934
}
3035
}
3136

@@ -99,9 +104,15 @@ final class DurationSignalTracker: @unchecked Sendable {
99104
let backgroundDuration = Date().timeIntervalSince(lastEnteredBackground)
100105

101106
for (signalName, data) in self.startedSignals {
107+
// skip offsetting by background time if background time explicitly requested by developer
108+
if data.includeBackgroundTime {
109+
continue
110+
}
111+
102112
self.startedSignals[signalName] = CachedData(
103113
startTime: data.startTime.addingTimeInterval(backgroundDuration),
104-
parameters: data.parameters
114+
parameters: data.parameters,
115+
includeBackgroundTime: data.includeBackgroundTime
105116
)
106117
}
107118

Sources/TelemetryDeck/TelemetryDeck.swift

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public enum TelemetryDeck {
8989
/// - Parameters:
9090
/// - signalName: The name of the signal to track. This will be used to identify and stop the duration tracking later.
9191
/// - parameters: A dictionary of additional string key-value pairs that will be included when the duration signal is eventually sent. Default is empty.
92+
/// - includeBackgroundTime: An optional Bool where you can specify to actually include (and not exclude) the time when your app is in the background.
9293
///
9394
/// This function only starts tracking time – it does not send a signal. You must call `stopAndSendDurationSignal(_:parameters:)`
9495
/// with the same signal name to finalize and actually send the signal with the tracked duration.
@@ -98,34 +99,50 @@ public enum TelemetryDeck {
9899
/// If a new duration signal ist started while an existing duration signal with the same name was not stopped yet, the old one is replaced with the new one.
99100
@MainActor
100101
@available(watchOS 7.0, *)
101-
public static func startDurationSignal(_ signalName: String, parameters: [String: String] = [:]) {
102-
DurationSignalTracker.shared.startTracking(signalName, parameters: parameters)
102+
public static func startDurationSignal(
103+
_ signalName: String,
104+
parameters: [String: String] = [:],
105+
includeBackgroundTime: Bool = false
106+
) {
107+
DurationSignalTracker.shared.startTracking(signalName, parameters: parameters, includeBackgroundTime: includeBackgroundTime)
103108
}
104109

105110
/// Stops tracking the duration of a signal and sends it with the total duration.
106111
///
107112
/// - Parameters:
108113
/// - signalName: The name of the signal that was previously started with `startDurationSignal(_:parameters:)`.
109114
/// - parameters: Additional parameters to include with the signal. These will be merged with the parameters provided at the start. Default is empty.
115+
/// - floatValue: An optional floating-point number that can be used to provide numerical data about the signal. Default is `nil`.
116+
/// - customUserID: An optional string specifying a custom user identifier. If provided, it will override the default user identifier from the configuration. Default is `nil`.
110117
///
111118
/// This function finalizes the duration tracking by:
112119
/// 1. Stopping the timer for the given signal name
113-
/// 2. Calculating the duration in seconds (excluding background time)
120+
/// 2. Calculating the duration in seconds (excluding background time by default)
114121
/// 3. Sending a signal that includes the start parameters, stop parameters, and calculated duration
115122
///
116123
/// The duration is included in the `TelemetryDeck.Signal.durationInSeconds` parameter.
117124
///
118125
/// If no matching signal was started, this function does nothing.
119126
@MainActor
120127
@available(watchOS 7.0, *)
121-
public static func stopAndSendDurationSignal(_ signalName: String, parameters: [String: String] = [:]) {
128+
public static func stopAndSendDurationSignal(
129+
_ signalName: String,
130+
parameters: [String: String] = [:],
131+
floatValue: Double? = nil,
132+
customUserID: String? = nil
133+
) {
122134
guard let (exactDuration, startParameters) = DurationSignalTracker.shared.stopTracking(signalName) else { return }
123135
let roundedDuration = (exactDuration * 1_000).rounded(.down) / 1_000 // rounds down to 3 fraction digits
124136

125137
var durationParameters = ["TelemetryDeck.Signal.durationInSeconds": String(roundedDuration)]
126138
durationParameters.merge(startParameters) { $1 }
127139

128-
self.internalSignal(signalName, parameters: durationParameters.merging(parameters) { $1 })
140+
self.internalSignal(
141+
signalName,
142+
parameters: durationParameters.merging(parameters) { $1 },
143+
floatValue: floatValue,
144+
customUserID: customUserID
145+
)
129146
}
130147

131148
/// A signal being sent without enriching the signal name with a prefix. Also, any reserved signal name checks are skipped. Only for internal use.

0 commit comments

Comments
 (0)