Skip to content

Modify destinations to avoid processing if they don't have settings #36

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

Merged
merged 6 commits into from
Aug 6, 2021
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: 6 additions & 0 deletions Sources/Segment/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public extension Configuration {
return self
}

@discardableResult
func defaultSettings(_ settings: Settings) -> Configuration {
values.defaultSettings = settings
return self
}

@discardableResult
func autoAddSegmentDestination(_ value: Bool) -> Configuration {
values.autoAddSegmentDestination = value
Expand Down
9 changes: 9 additions & 0 deletions Sources/Segment/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ public struct Settings: Codable {
])
}

public init(writeKey: String) {
integrations = try! JSON([
SegmentDestination.Constants.integrationName.rawValue: [
SegmentDestination.Constants.apiKey.rawValue: writeKey,
SegmentDestination.Constants.apiHost.rawValue: HTTPClient.getDefaultAPIHost()
]
])
}

public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.integrations = try? values.decode(JSON.self, forKey: CodingKeys.integrations)
Expand Down
55 changes: 29 additions & 26 deletions Sources/Segment/Timeline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,37 +209,40 @@ extension DestinationPlugin {
// This will process plugins (think destination middleware) that are tied
// to this destination.

var result: E? = nil

// For destination plugins, we will always have some kind of `settings`,
// and if we don't, it means this destination hasn't been setup on app.segment.com,
// which in turn ALSO means that we shouldn't be sending events to it.


// apply .before and .enrichment types first ...
let beforeResult = timeline.applyPlugins(type: .before, event: incomingEvent)
let enrichmentResult = timeline.applyPlugins(type: .enrichment, event: beforeResult)

// now we execute any overrides we may have made. basically, the idea is to take an
// incoming event, like identify, and map it to whatever is appropriate for this destination.
var destinationResult: E? = nil
switch enrichmentResult {
case let e as IdentifyEvent:
destinationResult = identify(event: e) as? E
case let e as TrackEvent:
destinationResult = track(event: e) as? E
case let e as ScreenEvent:
destinationResult = screen(event: e) as? E
case let e as GroupEvent:
destinationResult = group(event: e) as? E
case let e as AliasEvent:
destinationResult = alias(event: e) as? E
default:
break

if let enabled = analytics?.settings()?.isDestinationEnabled(key: self.key), enabled == true {
// apply .before and .enrichment types first ...
let beforeResult = timeline.applyPlugins(type: .before, event: incomingEvent)
let enrichmentResult = timeline.applyPlugins(type: .enrichment, event: beforeResult)

// now we execute any overrides we may have made. basically, the idea is to take an
// incoming event, like identify, and map it to whatever is appropriate for this destination.
var destinationResult: E? = nil
switch enrichmentResult {
case let e as IdentifyEvent:
destinationResult = identify(event: e) as? E
case let e as TrackEvent:
destinationResult = track(event: e) as? E
case let e as ScreenEvent:
destinationResult = screen(event: e) as? E
case let e as GroupEvent:
destinationResult = group(event: e) as? E
case let e as AliasEvent:
destinationResult = alias(event: e) as? E
default:
break
}

// apply .after plugins ...
result = timeline.applyPlugins(type: .after, event: destinationResult)
}

// apply .after plugins ...
let afterResult = timeline.applyPlugins(type: .after, event: destinationResult)

return afterResult
return result
}
}

53 changes: 53 additions & 0 deletions Tests/Segment-Tests/Analytics_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,59 @@ final class Analytics_Tests: XCTestCase {

wait(for: [expectation], timeout: 1.0)
}

func testDestinationEnabled() {
// need to clear settings for this one.
UserDefaults.standard.removePersistentDomain(forName: "com.segment.storage.test")

let expectation = XCTestExpectation(description: "MyDestination Expectation")
let myDestination = MyDestination {
expectation.fulfill()
}

var settings = Settings(writeKey: "test")
if let existing = settings.integrations?.dictionaryValue {
var newIntegrations = existing
newIntegrations[myDestination.key] = true
settings.integrations = try! JSON(newIntegrations)
}
let configuration = Configuration(writeKey: "test")
configuration.defaultSettings(settings)
let analytics = Analytics(configuration: configuration)

analytics.add(plugin: myDestination)

waitUntilStarted(analytics: analytics)

analytics.track(name: "testDestinationEnabled")

wait(for: [expectation], timeout: 1.0)
}

// Linux doesn't support XCTExpectFailure
#if !os(Linux)
func testDestinationNotEnabled() {
// need to clear settings for this one.
UserDefaults.standard.removePersistentDomain(forName: "com.segment.storage.test")

let expectation = XCTestExpectation(description: "MyDestination Expectation")
let myDestination = MyDestination {
expectation.fulfill()
}

let configuration = Configuration(writeKey: "test")
let analytics = Analytics(configuration: configuration)

analytics.add(plugin: myDestination)

waitUntilStarted(analytics: analytics)

analytics.track(name: "testDestinationEnabled")

XCTExpectFailure()
wait(for: [expectation], timeout: 1.0)
}
#endif

func testAnonymousId() {
let analytics = Analytics(configuration: Configuration(writeKey: "test"))
Expand Down
10 changes: 9 additions & 1 deletion Tests/Segment-Tests/Support/TestUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,25 @@ class MyDestination: DestinationPlugin {
let type: PluginType
let key: String
var analytics: Analytics?
let trackCompletion: (() -> Void)?

init() {
init(trackCompletion: (() -> Void)? = nil) {
self.key = "MyDestination"
self.type = .destination
self.timeline = Timeline()
self.trackCompletion = trackCompletion
}

func update(settings: Settings) {
//
}

func track(event: TrackEvent) -> TrackEvent? {
if let completion = trackCompletion {
completion()
}
return event
}
}

class OutputReaderPlugin: Plugin {
Expand Down