Comments (13)
This currently works as intended. The idea was before you've received results from Segment's /settings endpoint, you may have a preference for EU vs US endpoints. Segment settings has the final say, but we acknowledge this is problematic when intending to use a proxy (which I assume you're wanting to do). We'll look at this soon and try and figure out a good path forward. In the meantime feel free to fork and comment out the following line in SegmentDestination.swift
apiHost = segmentInfo?[Self.Constants.apiHost.rawValue] as? String
That'll make it such that whatever you supply will be used at all times.
from analytics-swift.
This currently works as intended. The idea was before you've received results from Segment's /settings endpoint, you may have a preference for EU vs US endpoints. Segment settings has the final say, but we acknowledge this is problematic when intending to use a proxy (which I assume you're wanting to do). We'll look at this soon and try and figure out a good path forward. In the meantime feel free to fork and comment out the following line in SegmentDestination.swift
apiHost = segmentInfo?[Self.Constants.apiHost.rawValue] as? String
That'll make it such that whatever you supply will be used at all times.
If this is "working as intended", can you please documented it clearly in the Analytics Swift documentation - https://segment.com/docs/connections/sources/catalog/libraries/mobile/swift-ios/
I just spent several hours last night trying to understand why our events aren't going through our proxy with the apiHost configuration set.
In fact, from my troubleshooting, it is unclear to me if what you are saying is accurate (that apiHost
is being used as a default). Browsing through the source code, I do not see the apiHost
value on the configuration object ever being read.
Anyway, I've opened this ticket https://segment.zendesk.com/hc/requests/488619
from analytics-swift.
Just to confirm, this is the workaround you are proposing, correct?
main...jackgene:analytics-swift:main
If so, it is not working for me. As I pointed out in my last comment, apiHost
on the Configuration object doesn't appear to be being read at all. Let me know if I've missed anything else.
Thank you.
from analytics-swift.
@jackgene It is being read, I assure you. See HTTPClient.swift. That workaround is no longer necessary once this PR is merged: #165. Documentation will be updated before a point release is made.
from analytics-swift.
from analytics-swift.
@jackgene There was no "tone". I'm just sharing facts. As an employee here trying to help you, I don't appreciate yours so lets take it down a notch. See the line below as to where it's being read.
analytics-swift/Sources/Segment/Utilities/HTTPClient.swift
Lines 30 to 52 in 93314b0
The fix has already been merged since we first spoke. A point release has yet to happen, pending documentation.
from analytics-swift.
@jackgene There was no "tone". I'm just sharing facts. As an employee here trying to help you, I don't appreciate yours so lets take it down a notch. See the line below as to where it's being read.
analytics-swift/Sources/Segment/Utilities/HTTPClient.swift
Lines 30 to 52 in 93314b0
The fix has already been merged since we first spoke. A point release has yet to happen, pending documentation.
The lines you highlighted is the initializer for HTTPClient (called "constructor" in other languages). It shows that the initializer accepts an apiHost
, and defaults it to nil
when no value is passed in - more on initializers here - https://docs.swift.org/swift-book/LanguageGuide/Initialization.html. But the key point is these lines of code do not show apiHost
being read from the Configuration object.
(Note that in Swift (and in most programming languages really), the fact that there's a constructor parameter named apiHost
, and that there's a corresponding property named apiHost
on the Configuration
object, does not automatically bind the two)
For Configuration
's apiHost
to be passed to the initializer, it has to be explicitly invoked with it, it would look something like this:
let configuration = Configuration("some write key").apiHost("myhost.com/v1")
let analytics = Analytics(configuration: configuration)
HTTPClient(
analytics: analytics,
apiHost: configuration.values.apiHost // THIS LINE
)
If you look through the analytics-swift source, you'll find that the HTTPClient
is being initialized from three different places (you can find this in Xcode by right clicking on the init
function -> Find -> Find Call Hierarchy):
- https://github.com/segmentio/analytics-swift/blob/main/Sources/Segment/Settings.swift#L127
- https://github.com/segmentio/analytics-swift/blob/main/Sources/Segment/Plugins/SegmentDestination.swift#L58
- https://github.com/segmentio/analytics-swift/blob/main/Sources/Segment/Plugins/SegmentDestination.swift#L78
You'll note that in none of these locations is apiHost
being set to a value read from Configuration
.
Another point worth noting, you "assured me" that Configuration.Values.apiHost
is being read. Here's a tip on how you can quickly see that that is not the case:
- Navigate to the
apiHost
property forConfiguration.Values
(https://github.com/segmentio/analytics-swift/blob/main/Sources/Segment/Configuration.swift#L34) in Xcode. - Right-click on
apiHost
, and then Find -> Find Call Hierarchy
You'll quickly see it's not referenced anywhere. Try the same thing with say writeKey
, and you'll see all the places where writeKey
is being read from.
from analytics-swift.
Thanks for all those super useful links.
Here, I'll paste the code for you since it seems difficult for you to see it on GitHub.
init(analytics: Analytics, apiKey: String? = nil, apiHost: String? = nil, cdnHost: String? = nil) {
self.analytics = analytics
if let apiKey = apiKey {
self.apiKey = apiKey
} else {
self.apiKey = analytics.configuration.values.writeKey
}
Low and behold, apiKey gets set from the configuration value that was specified if null was passed into the constructor. HTTPClient is a somewhat generic class that lost its way a little over time. But wait, there's more!
Just a few lines down ....
@discardableResult
func startBatchUpload(writeKey: String, batch: URL, completion: @escaping (_ result: Result<Bool, Error>) -> Void) -> URLSessionDataTask? {
guard let uploadURL = segmentURL(for: apiHost, path: "/b") else {
completion(.failure(HTTPClientErrors.failedToOpenBatch))
return nil
}
Enjoy.
from analytics-swift.
You may want to re-read this issue.
It is about apiHost
not applying to the HTTPClient
, NOT apiKey
or writeKey
.
from analytics-swift.
Ya got me. My apologies, apiKey has been front and center for me all week. I'll make a PR for the default setting of apiHost in the coming days, however that doesn't seem like what you needed in the first place. The linked PR has more along the lines of what you and the original poster of this bug were looking for. See Configuration.requestFactory which gives you full control over all the details of a given request (headers/url/path/etc).
from analytics-swift.
Actually, I'll reopen this as another issue that omits the confusion.
from analytics-swift.
Ya got me. My apologies, apiKey has been front and center for me all week. I'll make a PR for the default setting of apiHost in the coming days, however that doesn't seem like what you needed in the first place. The linked PR has more along the lines of what you and the original poster of this bug were looking for. See Configuration.requestFactory which gives you full control over all the details of a given request (headers/url/path/etc).
I think you are right, that the requestFactory
override is more what I need.
And apologies if my frustration was coming through, but my point was that I knew I was writing the apiHost
value on the Configuration
object, but I wasn't seeing it have any effect.
Going through the code manually, and having Xcode try and find all references to Configuration.Values.apiHost
, I find a couple of references where the value is written to, but no references where it is ever read from, hence I don't see how it could possibly be affecting any behavior of HTTPClient
or anything else.
Thanks for opening the new issue, and have a nice weekend!
from analytics-swift.
No worries at all! Glad requestFactory does the trick for you and you're back in business. Hope you have a good weekend as well. Ttys!
from analytics-swift.
Related Issues (20)
- Crash inside DestinationMetadataPlugin during Analytics.update call HOT 12
- JSON encoding: lots of Codable-conforming types that crash in JSON encoding HOT 3
- SEGIntegration and SEGIntegrationFactory HOT 2
- Build fails: `isUnitTesting` only available in DEBUG mode HOT 2
- Question: Is it supported multiple instance write key? HOT 1
- Infinite loop of network failures contacting https://api.segment.io/v1/b HOT 13
- Some logs are uploaded with corrupted JSON/inline garbage data HOT 7
- Vendored Framework: "... is not a member type of ..." error HOT 9
- Traits payload is not attached to "track" events HOT 1
- Loosing events after upgrading to 1.5.7 HOT 11
- Adding a plugin to Analytics causes a circular reference HOT 6
- Rename of `JSONSafeEncoder` -> `JSONSafeEncoding` has broken previous releases HOT 4
- Force closing the app or updating to a newer version, causes the Segment.Analytics.init(configuration:) to call fatalError() HOT 11
- What's happened to 1.5.10? HOT 1
- Segment package versioning HOT 1
- Library does not automatically collect IAP Order Completed events, despite what docs say HOT 4
- iOSLifecycleEvents.application(didFinishLaunchingWithOptions:) is Compiled for More than 400 ms HOT 3
- 'shared' is inaccessible due to 'internal' protection level HOT 5
- Modify some context from Plugin HOT 1
- Crash at "specialized iOSVendorSystem.deviceModel()" HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from analytics-swift.