Skip to content

Commit 35ca193

Browse files
author
Brandon Sneed
committed
updates
1 parent 4dbd63b commit 35ca193

4 files changed

Lines changed: 223 additions & 19 deletions

File tree

.swiftpm/xcode/xcshareddata/xcschemes/segmentcli.xcscheme

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
</CommandLineArgument>
9494
<CommandLineArgument
9595
argument = "analytics track Sf37SZu7TfysLklHCahTo5HlSP9m9O6h someGoofyEvent myBool=true myNumber=5 myFloat=3.14 myString=&quot;get schwifty&quot;"
96+
isEnabled = "NO">
97+
</CommandLineArgument>
98+
<CommandLineArgument
99+
argument = "analytics flush Sf37SZu7TfysLklHCahTo5HlSP9m9O6h"
96100
isEnabled = "YES">
97101
</CommandLineArgument>
98102
<CommandLineArgument

Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/segmentcli/Commands/Analytics.swift

Lines changed: 206 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ class AnalyticsGroup: CommandGroup {
1818
AnalyticsScreenCommand(),
1919
AnalyticsGroupCommand(),
2020
AnalyticsAliasCommand(),
21-
AnalyticsResetCommand()]
21+
AnalyticsResetCommand(),
22+
AnalyticsFlushCommand(),
23+
AnalyticsListCommand()]
2224
init() {}
2325
}
2426

@@ -61,25 +63,31 @@ class AnalyticsTrackCommand: Command {
6163
@Param var writeKey: String
6264
@Param var eventName: String
6365

66+
@Flag("-f", "--flush", description: "Flush event(s) to Segment before returning")
67+
var flush: Bool
68+
6469
@CollectedParam(minCount: 0, validation: keyValueValidation) var properties: [String]
6570

6671
func execute() throws {
6772
let spinner = Spinner(.dots, "Sending track event to Segment ...")
6873
spinner.start()
6974

70-
let config = Configuration(writeKey: writeKey)
71-
config.flushAt(1)
75+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
76+
analytics.waitUntilStarted()
7277

73-
let analytics = Analytics(configuration: config)
7478
executeAndWait { semaphore in
7579
analytics.track(name: eventName, properties: paramArryToDictionary(properties))
76-
// wait for the event to enter the system
80+
// wait till we know the event has been placed in the queue
7781
while analytics.hasUnsentEvents == false {
7882
RunLoop.main.run(until: Date.distantPast)
7983
}
80-
// wait for it to exit
81-
while analytics.hasUnsentEvents {
82-
RunLoop.main.run(until: Date.distantPast)
84+
if flush {
85+
analytics.flush()
86+
// wait for flush to complete
87+
while analytics.hasUnsentEvents {
88+
analytics.flush()
89+
RunLoop.main.run(until: Date.distantPast)
90+
}
8391
}
8492
semaphore.signal()
8593
}
@@ -95,30 +103,36 @@ class AnalyticsIdentifyCommand: Command {
95103

96104
@Param var writeKey: String
97105
@Param var userID: String
98-
106+
107+
@Flag("-f", "--flush", description: "Flush event(s) to Segment before returning")
108+
var flush: Bool
109+
99110
@CollectedParam(minCount: 0, validation: keyValueValidation) var traits: [String]
100111

101112
func execute() throws {
102113
let spinner = Spinner(.dots, "Sending identify event to Segment ...")
103114
spinner.start()
104115

105-
let config = Configuration(writeKey: writeKey)
106-
config.flushAt(1)
116+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
117+
analytics.waitUntilStarted()
107118

108-
let analytics = Analytics(configuration: config)
109119
executeAndWait { semaphore in
110-
analytics.identify(userId: userID, traits: paramArryToDictionary(traits))
111-
// wait for the event to enter the system
120+
analytics.identify(userId, traits: paramArryToDictionary(traits))
121+
// wait till we know the event has been placed in the queue
112122
while analytics.hasUnsentEvents == false {
113123
RunLoop.main.run(until: Date.distantPast)
114124
}
115-
// wait for it to exit
116-
while analytics.hasUnsentEvents {
117-
RunLoop.main.run(until: Date.distantPast)
125+
if flush {
126+
analytics.flush()
127+
// wait for flush to complete
128+
while analytics.hasUnsentEvents {
129+
analytics.flush()
130+
RunLoop.main.run(until: Date.distantPast)
131+
}
118132
}
119133
semaphore.signal()
120134
}
121-
135+
122136
spinner.stop()
123137
print("Identify Event for `\(userID)` sent!\n")
124138
}
@@ -128,31 +142,205 @@ class AnalyticsScreenCommand: Command {
128142
let name = "screen"
129143
let shortDescription = "Send a screen event to Segment"
130144

145+
@Param var writeKey: String
146+
@Param var eventName: String
147+
148+
@Flag("-f", "--flush", description: "Flush event(s) to Segment before returning")
149+
var flush: Bool
150+
151+
@CollectedParam(minCount: 0, validation: keyValueValidation) var properties: [String]
152+
131153
func execute() throws {
154+
let spinner = Spinner(.dots, "Sending track event to Segment ...")
155+
spinner.start()
156+
157+
Analytics.debugLogsEnabled = true
158+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
159+
160+
analytics.waitUntilStarted()
161+
162+
executeAndWait { semaphore in
163+
analytics.track(name: eventName, properties: paramArryToDictionary(properties))
164+
// wait till we know the event has been placed in the queue
165+
while analytics.hasUnsentEvents == false {
166+
RunLoop.main.run(until: Date.distantPast)
167+
}
168+
if flush {
169+
analytics.flush()
170+
// wait for flush to complete
171+
while analytics.hasUnsentEvents {
172+
analytics.flush()
173+
RunLoop.main.run(until: Date.distantPast)
174+
}
175+
}
176+
semaphore.signal()
177+
}
178+
179+
spinner.stop()
180+
print("Event `\(eventName)` sent!\n")
132181
}
133182
}
134183

135184
class AnalyticsGroupCommand: Command {
136185
let name = "group"
137186
let shortDescription = "Send a group event to Segment"
138187

188+
@Param var writeKey: String
189+
@Param var eventName: String
190+
191+
@Flag("-f", "--flush", description: "Flush event(s) to Segment before returning")
192+
var flush: Bool
193+
194+
@CollectedParam(minCount: 0, validation: keyValueValidation) var properties: [String]
195+
139196
func execute() throws {
197+
let spinner = Spinner(.dots, "Sending track event to Segment ...")
198+
spinner.start()
199+
200+
Analytics.debugLogsEnabled = true
201+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
202+
203+
analytics.waitUntilStarted()
204+
205+
executeAndWait { semaphore in
206+
analytics.track(name: eventName, properties: paramArryToDictionary(properties))
207+
// wait till we know the event has been placed in the queue
208+
while analytics.hasUnsentEvents == false {
209+
RunLoop.main.run(until: Date.distantPast)
210+
}
211+
if flush {
212+
analytics.flush()
213+
// wait for flush to complete
214+
while analytics.hasUnsentEvents {
215+
analytics.flush()
216+
RunLoop.main.run(until: Date.distantPast)
217+
}
218+
}
219+
semaphore.signal()
220+
}
221+
222+
spinner.stop()
223+
print("Event `\(eventName)` sent!\n")
140224
}
141225
}
142226

143227
class AnalyticsAliasCommand: Command {
144228
let name = "alias"
145229
let shortDescription = "Send an alias event to Segment"
146230

231+
@Param var writeKey: String
232+
@Param var eventName: String
233+
234+
@Flag("-f", "--flush", description: "Flush event(s) to Segment before returning")
235+
var flush: Bool
236+
237+
@CollectedParam(minCount: 0, validation: keyValueValidation) var properties: [String]
238+
147239
func execute() throws {
240+
let spinner = Spinner(.dots, "Sending track event to Segment ...")
241+
spinner.start()
242+
243+
Analytics.debugLogsEnabled = true
244+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
245+
246+
analytics.waitUntilStarted()
247+
248+
executeAndWait { semaphore in
249+
analytics.track(name: eventName, properties: paramArryToDictionary(properties))
250+
// wait till we know the event has been placed in the queue
251+
while analytics.hasUnsentEvents == false {
252+
RunLoop.main.run(until: Date.distantPast)
253+
}
254+
if flush {
255+
analytics.flush()
256+
// wait for flush to complete
257+
while analytics.hasUnsentEvents {
258+
analytics.flush()
259+
RunLoop.main.run(until: Date.distantPast)
260+
}
261+
}
262+
semaphore.signal()
263+
}
264+
265+
spinner.stop()
266+
print("Event `\(eventName)` sent!\n")
148267
}
149268
}
150269

151270
class AnalyticsResetCommand: Command {
152271
let name = "reset"
153272
let shortDescription = "Resets any stored data like anonID, userID, etc"
154273

274+
@Param var writeKey: String
275+
276+
@Flag("-h", "--hard", description: "Removes any pending event batches as well")
277+
var hard: Bool
278+
279+
func execute() throws {
280+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
281+
analytics.waitUntilStarted()
282+
283+
analytics.reset()
284+
285+
if hard {
286+
let allFiles = try? FileManager.default.contentsOfDirectory(at: eventStorageDirectory(writeKey: writeKey), includingPropertiesForKeys: [], options: .skipsHiddenFiles)
287+
if let files = allFiles, files.count > 0 {
288+
for file in files {
289+
try? FileManager.default.removeItem(at: file)
290+
}
291+
}
292+
}
293+
294+
print("\nSystem has been reset.")
295+
}
296+
}
297+
298+
class AnalyticsFlushCommand: Command {
299+
let name = "flush"
300+
let shortDescription = "Flush any locally pending events out to Segment"
301+
302+
@Param var writeKey: String
303+
155304
func execute() throws {
305+
let spinner = Spinner(.dots, "Flushing events to Segment ...")
306+
spinner.start()
307+
308+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
309+
analytics.waitUntilStarted()
310+
311+
executeAndWait { semaphore in
312+
analytics.flush()
313+
// wait for it to exit
314+
while analytics.hasUnsentEvents {
315+
RunLoop.main.run(until: Date.distantPast)
316+
}
317+
semaphore.signal()
318+
}
319+
320+
spinner.stop()
321+
print("All pending events have been sent!\n")
322+
}
323+
}
324+
325+
class AnalyticsListCommand: Command {
326+
let name = "list"
327+
let shortDescription = "List currently pending event batches"
328+
329+
@Param var writeKey: String
330+
331+
func execute() throws {
332+
let analytics = Analytics(configuration: Configuration(writeKey: writeKey))
333+
analytics.waitUntilStarted()
334+
335+
let files = analytics.pendingUploads
336+
if let files = files, files.count > 0 {
337+
print("\n\nPending event batches:\n")
338+
for file in files {
339+
print(" \(file.path)")
340+
}
341+
} else {
342+
print("\nThere are no pending event batches to be sent.")
343+
}
156344
}
157345
}
158346

Sources/segmentcli/Utilities/Misc.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import Foundation
99
import SwiftCLI
10+
import Segment
1011

1112
// MARK: - Helper methods
1213

@@ -48,3 +49,14 @@ func exitWithError(_ error: Error) {
4849
// useful for error handling
4950
extension String: Error {}
5051

52+
// MARK: - Segment helper functions
53+
54+
func eventStorageDirectory(writeKey: String) -> URL {
55+
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
56+
let docURL = urls[0]
57+
let segmentURL = docURL.appendingPathComponent("segment/\(writeKey)/")
58+
// try to create it, will fail if already exists, nbd.
59+
// tvOS, watchOS regularly clear out data.
60+
try? FileManager.default.createDirectory(at: segmentURL, withIntermediateDirectories: true, attributes: nil)
61+
return segmentURL
62+
}

0 commit comments

Comments
 (0)