Commit graph

130 commits

Author SHA1 Message Date
ketanmixpanel
5aa52257c1
Fix feature flags and track events race condition (#715)
* added fix for the race FF condition

* removed unused initilizers

* passed the distinctId to the recordFirstTimeEvent

* Update Sources/FeatureFlags.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update Sources/FeatureFlags.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: avoid trackingQueue.sync from main thread in async flag paths and fix doc comments

Agent-Logs-Url: https://github.com/mixpanel/mixpanel-swift/sessions/035f0c40-e3d9-4629-a0f5-e52a16a531a6

Co-authored-by: ketanmixpanel <188901560+ketanmixpanel@users.noreply.github.com>

* fix: align getAllVariantsSync doc comment to use 'may block' for consistency

Agent-Logs-Url: https://github.com/mixpanel/mixpanel-swift/sessions/035f0c40-e3d9-4629-a0f5-e52a16a531a6

Co-authored-by: ketanmixpanel <188901560+ketanmixpanel@users.noreply.github.com>

* fixed review feedback

* removed queue scheduling

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ketanmixpanel <188901560+ketanmixpanel@users.noreply.github.com>
2026-04-17 22:07:58 +05:30
Santi Gracia
22cdbed76e
Defer automatic events initialization - Fix SwiftUI global accent color override when initializing Mixpanel with automatic events (#712)
* Defer automatic events initialization

Delay automaticEvents.initializeEvents by dispatching to DispatchQueue.main.async to run on the next run loop iteration. This avoids interfering with SwiftUI's accent color setup when Mixpanel.initialize() is called from a SwiftUI App's init (see #522). Uses a weak self capture to avoid retain cycles.

* Drain main run loop before tracking queue

Call waitForAsyncTasks() at the start of waitForTrackingQueue to drain the main run loop so any deferred initialization (e.g. automatic events) is dispatched to the tracking queue before synchronizing. Adds a clarifying comment and prevents races in tests that rely on tracking/ network queue state.
- Fix for copilot review comment on pull/712

* Fix for tests in PR

drains the main run loop only once per test right after init, ensuring initializeEvents() has dispatched before the test proceeds
2026-04-17 00:09:18 +05:30
Tyler Roach
2fecbcc4be
feat: OSX Automatic Event Tracking (#706)
* OSX Automatic Event Tracking

* fix tests
2026-04-02 08:49:37 -04:00
Mark Siebert
84f5aa84d1
Add FlagOptions struct for granular feature flag configuration (#699)
* Add FlagOptions with loadOnFirstForeground to fix initialize/identify race

When calling Mixpanel.initialize immediately followed by identify, both
can trigger concurrent flag fetches causing inconsistent flag evaluation.

This adds a FlagOptions struct with a loadOnFirstForeground option that
lets customers disable the automatic flag load at init time, call
identify first, then manually trigger loadFlags(). The new flagsOptions
parameter on MixpanelOptions groups flag config together while keeping
full backward compatibility with existing featureFlagsEnabled and
featureFlagsContext parameters.

Usage:
  let options = MixpanelOptions(
      token: "TOKEN",
      flagsOptions: FlagOptions(enabled: true, loadOnFirstForeground: false)
  )
  let mp = Mixpanel.initialize(options: options)
  mp.identify(distinctId: "user123")
  mp.flags.loadFlags()

https://claude.ai/code/session_01234twgpsuvC2SP67zKDNru

* Clarify FlagOptions docs: identify() already triggers loadFlags()

identify() calls loadFlags() internally when the distinctId changes,
so an explicit loadFlags() call is only needed when re-identifying
with the same persisted distinctId.

https://claude.ai/code/session_01234twgpsuvC2SP67zKDNru

* deprecate old options

* test update

* Fix CI test failures: replace timer waits with predicate expectations

Timer-based waits (0.2-0.3s) expire before .utility QoS dispatches
complete on resource-constrained CI runners. Replace with
XCTNSPredicateExpectation that polls observable state and fulfills
immediately when ready, with 10s timeout for CI headroom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* rename fields

* rename to featureFlagOptions

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-04 11:22:47 -08:00
Jared McFarland
de73100ee3
Add deviceIdProvider closure for custom device ID generation (#692)
* Add deviceIdProvider closure for custom device ID generation

Adds a `deviceIdProvider: (() -> String)?` property to MixpanelOptions
that allows customers to supply their own device ID generation logic.

Key behaviors:
- Provider called on init (if no persisted identity) and after reset()/optOutTracking()
- Return same value = persistent device ID (never resets)
- Return different value = ephemeral device ID (resets each time)
- SDK logs warning when provider would replace existing persisted anonymousId
- Empty string from provider falls back to default UUID/IDFV behavior

This gives customers full control over device ID persistence and reset
semantics without needing separate parameters on reset() and optOutTracking().

Includes:
- 13 unit tests covering all behaviors
- Comprehensive documentation in docs/device-id-provider.md

* Address PR review feedback for deviceIdProvider

- Change log level from warn to error for identity mismatch
- Use defaultDeviceId() in unarchive to avoid calling provider twice
- Add whitespace trimming to provider result
- Update documentation table with "Value Used?" column
- Add testIdentifyWithDeviceIdProvider test case

* Add deviceIdProvider QA helpers to MixpanelDemo

- Add persistent and ephemeral device ID provider examples in AppDelegate
- Enhance Reset button with before/after console logging
- Default to no provider (standard SDK behavior) for production

* Make deviceIdProvider return optional String for graceful error handling

Change type from `(() -> String)?` to `(() -> String?)?` so customers can
return nil to signal "use SDK default" when their device ID source fails.

- Update MixpanelOptions type signature and documentation
- Handle optional return in defaultDeviceId() with nil-coalescing
- Update warning message to mention nil or empty string
- Add failingDeviceIdProvider test option in demo app
- Add testProviderReturningNilFallsBackToDefault test

* Add Original ID Merge compatibility note to deviceIdProvider docs

Document the footgun with persistent device IDs + Original ID Merge
on shared devices, where createAlias() can incorrectly merge
identities of different users.

* Add thread-safety warning to deviceIdProvider documentation

The provider closure is called while holding internal locks, so blocking
operations (Keychain, network, UserDefaults) can cause deadlocks. Update
docs and examples to recommend caching the device ID at app launch and
returning the cached value from the provider.

- Add Thread Safety note to MixpanelOptions.swift doc comment
- Update docs/device-id-provider.md with caching pattern
- Revise Best Practices to emphasize non-blocking providers
- Update MixpanelDemo to demonstrate caching pattern
2026-02-06 11:35:58 +05:30
Rahul Raveendran V P
79968d3f20
Refactor reachability handling to use server URL for network reachability checks (#694) 2026-01-23 23:49:18 +05:30
Copilot
8833248376
Add device_id as an automatic context value for Feature Flags (#675)
* Initial plan

* Add device_id as automatic context value for Feature Flags

Co-authored-by: msiebert <1504059+msiebert@users.noreply.github.com>

* Add timeLastFetched and fetchLatencyMs tracking properties to $experiment_started events

Co-authored-by: msiebert <1504059+msiebert@users.noreply.github.com>

* Fix type mismatch in timeLastFetched and fetchLatencyMs properties

Co-authored-by: msiebert <1504059+msiebert@users.noreply.github.com>

* Fix private access level for timeLastFetched and fetchLatencyMs properties

Co-authored-by: msiebert <1504059+msiebert@users.noreply.github.com>

* fix concurrency bug

* determine if sync is needed when tracking

* add more tests

* tweak test

* prevent potential deadlock, simplify tracking threading

* add timing properties sanity test

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: msiebert <1504059+msiebert@users.noreply.github.com>
Co-authored-by: Mark Siebert <mark.siebert@mixpanel.com>
Co-authored-by: Jared McFarland <jared@mixpanel.com>
2025-08-06 12:12:43 -07:00
Jared McFarland
e8c8783d94
swift-format (#672) 2025-05-29 17:45:08 -07:00
Jared McFarland
330b471fc5
Initial support for Feature Flags (#670)
* initial feature flag support

* tests and tweaks

* add new sources to podspec

* fix config init

* tests and cleanup

* pass to AnalyticsMessages and add to mixpaneldemo

* fix test

* rename APIs

* more renaming

* fix demo app delegate

* fix tests

* update podspec

* revert demo app changes

* one more config -> options rename

* nope... more config->options renaming

* modify enabled method names and load flags on identify

* Update Sources/MixpanelPersistence.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix response parser function test

* update README with DeepWiki badge

* tweak README

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-28 13:49:38 -07:00
Santi Gracia
a8dd5ffd88
Adding optional gzip compression for /track (#653)
* Adding optional gzip compression for /track

* Logger->MixpanelLogger

* safe unwrap in gzipCompressed

---------

Co-authored-by: Jared McFarland <jared@mixpanel.com>
2025-03-31 16:34:07 -07:00
Jared McFarland
dbdc3d1d6b check opt out inside tracking queue 2025-02-10 15:08:46 -08:00
Jared McFarland
a81bf89936
Merge pull request #663 from mixpanel/jared-unregister-replay-id
unregister session replay ID super prop upon backgrounding
2025-02-10 14:59:46 -08:00
Jared McFarland
0884678b1c unregister replay ID upon backgrounding 2025-02-10 09:59:08 -08:00
Jared McFarland
d11438b6a4
Merge pull request #626 from jduquennoy/InjectableLogger
Expose publicly some types and methods related to the logging system
2025-01-30 16:06:30 -08:00
Jared McFarland
028b5eee7b more renaming 2025-01-30 12:52:14 -08:00
Jared McFarland
af5f9753ae add Mixpanel prefix to avoid namespace clashes 2025-01-30 12:44:04 -08:00
Jared McFarland
4b58a6cb7f Revert "rename with MP prefix to avoid namespace clashes"
This reverts commit 348574216b.
2025-01-30 12:38:50 -08:00
Jared McFarland
348574216b rename with MP prefix to avoid namespace clashes 2025-01-30 12:19:36 -08:00
Mathijs Kadijk
37da5557e9
Avoid deadlock by moving saveIdentity to read lock
Since the UserDefaults calls made by saveIdentity cause blocking NSNotifications to be emitted to the main thread, calling saveIdentity under the write lock can cause deadlocks.

Since the saveIdentity call only reads state it’s now moved to only take a read lock instead of being under the write lock.
2024-12-06 10:13:35 +01:00
Zihe Jia
5d1e989094 Enable inter-SDK communication for setting super properties. 2024-07-19 15:11:47 -07:00
Zihe Jia
68dc046646 Remove all internal tracking 2024-05-03 16:39:42 -07:00
Zihe Jia
460e1a1dc2 fix the crash for FlushRequest.sendRequest 2024-04-19 15:16:15 -07:00
mohitanand-cred
68ea193376 Merge branch 'master' of https://github.com/mixpanel/mixpanel-swift into feat/proxy_server_header_capability 2024-04-08 01:23:43 +05:30
ay8s
5b375eac53 Automatic Props 2024-01-29 19:12:01 -08:00
Dale Swift
ec16672d91 Prevent crashes in unregisterSuperProperty
Fixes thread safety in currentSuperProperties, unregisterSuperProperty and updateSuperProperty.
2024-01-17 07:58:33 +11:00
mohitanand-cred
91c16b9cee added header capability to other network requests 2023-12-21 13:18:35 +05:30
mohitanand-cred
918d3ad6a3 headers and query item capability added to proxy server 2023-12-12 17:12:45 +05:30
Zihe Jia
a215e52f7c code review feedback 2023-11-09 16:55:05 -08:00
Zihe Jia
4f222e4541 add new property flushBatchSize for fine tuning the network request 2023-11-09 16:41:33 -08:00
Zihe Jia
442606e7b0 code review feedback 2023-03-22 15:48:53 -07:00
Zihe Jia
ef18690a85 add limit to number of events for each flush to 1000 to improve the performance 2023-03-22 10:01:12 -07:00
deepak neralla
0ee018219b identity v3 changes for swift sdk 2023-02-28 16:18:11 -08:00
deepak neralla
f5b6f9f933 identity v3 changes for swift sdk 2023-02-28 16:18:11 -08:00
Jared McFarland
fa699e5e63
Merge pull request #579 from museapphq/fix/dispatch-queue-autorelease
Setting explicit autorelease frequency
2023-02-28 16:06:37 -08:00
Jared McFarland
6f392a7c24
Merge pull request #588 from prydain007/fix-eventElapsedTime-crash
Access the timedEvents property inside of a readWriteLock.
2023-02-28 16:05:28 -08:00
J.R. Blackham
ea8ecb392b Access the timedEvents property inside of a readWriteLock. 2023-02-23 11:59:35 -07:00
deepak neralla
edd030174d identity v3 changes for swift sdk 2023-02-17 13:53:57 -08:00
deepak neralla
3928e1cb7a identity v3 changes for swift sdk 2023-02-14 16:45:18 -08:00
Adam Wulf
3b333518ce Setting explicit autorelease frequency 2023-02-01 14:56:05 -06:00
Jared McFarland
191dcacd86 fix Xcode 14 warnings 2022-11-02 10:34:28 -07:00
Jared McFarland
d8fd470f34 always use serverURL 2022-09-13 12:35:35 -07:00
Jared McFarland
db92974f8b dont initialize AutomaticEvents if trackAutomaticEvents is false 2022-09-09 10:27:36 -07:00
Jared McFarland
e5225512fc
Merge branch 'master' into jared-deprecate-decide 2022-07-06 12:01:39 -07:00
Zihe Jia
aa7c38efe6 add support for mulitple instances under the same token 2022-07-01 17:44:47 -07:00
Zihe Jia
71c4db0258 add tests 2022-06-27 13:11:13 -07:00
Zihe Jia
7c6d58e1cc add option for 'createAlias' for not calling identify 2022-06-24 17:05:15 -07:00
Jared McFarland
3961313053 replace build flag with os checks 2022-06-23 11:01:26 -07:00
Jared McFarland
cc18259319 remove trackAutomaticEvents from user defaults 2022-06-22 12:43:36 -07:00
Jared McFarland
ddebd2de7d fix tests 2022-06-22 12:09:05 -07:00
Jared McFarland
80bf687c8a change DECIDE build flag to AUTOMATIC_EVENTS 2022-06-22 11:33:51 -07:00