Skip to content

Commit 1e8ff41

Browse files
Add comprehensive documentation for initialization race condition fix
- Add ISSUE_ANALYSIS.md with detailed root cause analysis - Update CHANGELOG.md with fix description - Document customer's issue, investigation, and solution - Include testing recommendations and timeline Co-authored-by: jaredmixpanel <10504508+jaredmixpanel@users.noreply.github.com>
1 parent 8a6d017 commit 1e8ff41

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
#
22

3+
## [Unreleased]
4+
5+
### Fixes
6+
7+
- Fix race condition in initialization causing missing super properties on first event [\#TBD](https://github.com/mixpanel/mixpanel-unity/pull/TBD)
8+
- Eagerly load all persisted properties (SuperProperties, OnceProperties, TimedEvents) during Initialize()
9+
- Pre-cache auto properties before first Track() call
10+
- Initialize session metadata during Initialize() to ensure it's ready
11+
- Addresses issue where Track() called immediately after Init() could miss properties
12+
- Fixes reported 30-44% event volume drop and missing super properties after SDK migration
13+
14+
#
15+
316
## [v3.5.3](https://github.com/mixpanel/mixpanel-unity/tree/v3.5.3) (2024-09-25)
417

518
### Enhancements

ISSUE_ANALYSIS.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Event Volume Drop and Missing Super Properties After Unity SDK Migration
2+
3+
## Issue Summary
4+
After migrating from native SDKs (Android 5.3.0 and custom iOS wrapper) to mixpanel-unity v3.5.3, customers are experiencing:
5+
6+
1. **30-44% drop in event volume** for App Start and App Exit events on Android (Google Play) only
7+
2. **Missing super properties** on the first event fired in each session (App Start event) on both iOS and Android
8+
3. Events fired between App Start and App Exit work normally with super properties present
9+
10+
## Environment
11+
- **SDK Version**: mixpanel-unity v3.5.3
12+
- **Platform**: Android (Google Play) - event volume drop; Both iOS and Android - missing super properties
13+
- **Migration**: From Android SDK 5.3.0 (Gradle) and iOS custom wrapper (commit 0b982aab58e832ad85a8d9dca4d9729aa3948b53)
14+
- **Unity Version**: Not specified
15+
- **Deployment**: Production environment
16+
17+
## Affected Games
18+
- Sago Mini School (rollout Oct 1st, 2025)
19+
- Sago Mini World (also released with SDK)
20+
- Project: Sago Mini - Production
21+
22+
## Detailed Symptoms
23+
24+
### 1. Event Volume Drop (Android Only)
25+
- **Metric**: ~30% drop in total events, ~44% drop in unique users for App Start and App Exit
26+
- **Comparison**: Sep 30th vs 30 days prior (pre-migration baseline)
27+
- **Pattern**:
28+
- App Start events: Significantly reduced
29+
- App Exit events: Significantly reduced
30+
- Mid-session events: Normal volume
31+
- **iOS**: No event volume drop observed
32+
- **Dashboard**: https://mixpanel.com/project/210340/view/23451/app/insights#fTLhAYFBMnRZ
33+
34+
### 2. Missing Super Properties (iOS + Android)
35+
- **Scope**: First event of every session (App Start event)
36+
- **Behavior**: Super properties that should be present are completely missing
37+
- **Registration**: Super property registration code executes at same location as before migration
38+
- **Later Events**: All events after the first event in a session include super properties correctly
39+
40+
### 3. Not Reproducible Locally
41+
- Issue only manifests in production with real users
42+
- Local testing (download from Play Store, test locally) does not reproduce the issue
43+
- This suggests timing-related issue or device-specific behavior
44+
45+
## Customer's Investigation
46+
47+
### What They Checked
48+
- ✅ Initialization paths appear to run (Mixpanel.Init + subsequent calls)
49+
- ✅ Super property registration code still executes (same location as before)
50+
- ✅ No recent logic changes that would gate or suppress tracking
51+
- ✅ No obvious token or environment mismatches
52+
- ✅ DAU metrics from App Store/Play Store show no actual user drop
53+
54+
### What They Observed
55+
- Migration kept existing C# wrapper/util classes
56+
- Only swapped underlying calls to Unity Mixpanel API
57+
- Games not yet migrated continue to report expected volumes with super properties present
58+
59+
### Code Flow
60+
Customer provided sequence diagram showing:
61+
1. Bootstrap scene loads
62+
2. Mixpanel.Init() called early in first scene
63+
3. App Start event fired immediately after initialization
64+
4. Super property registration happens in their SagoMixpanelBinding wrapper
65+
66+
## Technical Analysis (Mixpanel Support)
67+
68+
### Lin Yee Koh (Support)
69+
> "Mixpanel Unity (v3.5.3) initializes asynchronously. It is possible that the first event can fire before the instance is ready or before the super-properties file is loaded from disk."
70+
71+
### Customer Response (Guilherme)
72+
> "Hello, but the Mixpanel.Init() call seems sync. It is not a coroutine or Task method. It just applies the configs from the scriptable object and then initialize a singleton instance. How can we wait for the initialization finish? I didn't find an event or something that would tell the call finished."
73+
74+
### App Exit Event Mystery
75+
Customer noted that missing App Exit events is harder to explain with the async initialization theory:
76+
> "That still doesn't explain the missing App Exit events... Any queued or cached App Exit should get fired in the next launch as a flush() called automatically every 60 seconds."
77+
78+
## Root Cause (Identified)
79+
80+
After investigation, the root cause is a **race condition during initialization**:
81+
82+
### 1. Lazy Property Loading
83+
- Super properties are stored in PlayerPreferences/disk
84+
- Properties are lazily loaded on first access via `MixpanelStorage.SuperProperties` getter
85+
- On Android, PlayerPreferences read operations can be slow, especially on first access after app launch
86+
- If `Track()` is called immediately after `Init()`, properties may not be loaded yet
87+
88+
### 2. Auto Properties Not Cached Early
89+
- `GetEventsDefaultProperties()` and `GetEngageDefaultProperties()` cache platform-specific auto properties
90+
- These were called in `InitializeAfterSceneLoad()` (RuntimeInitializeLoadType.AfterSceneLoad)
91+
- If `Track()` is called during or before AfterSceneLoad, auto properties aren't cached yet
92+
- Each uncached call would regenerate them (performance issue + timing issue)
93+
94+
### 3. Session Metadata Not Initialized
95+
- Session metadata (`_sessionID`, counters, etc.) was only initialized in `OnApplicationPause()`
96+
- First event could have null/uninitialized session metadata
97+
98+
### 4. App Exit Event Loss
99+
- App Exit events queued to PlayerPreferences
100+
- Auto-flush happens every 60 seconds
101+
- On Android, aggressive process killing means:
102+
- App Exit event queued but not flushed before process killed
103+
- Event should send on next launch, but if there are issues with loading queued events from PlayerPreferences, they could be lost
104+
105+
## Solution Implemented
106+
107+
Modified `Controller.Initialize()` to **eagerly load all properties synchronously**:
108+
109+
```csharp
110+
internal static void Initialize() {
111+
MixpanelSettings.Instance.ApplyToConfig();
112+
GetInstance();
113+
114+
// Eagerly load all persisted properties to ensure they're available immediately
115+
var _ = MixpanelStorage.SuperProperties;
116+
var __ = MixpanelStorage.OnceProperties;
117+
var ___ = MixpanelStorage.TimedEvents;
118+
119+
// Pre-cache auto properties
120+
GetEventsDefaultProperties();
121+
GetEngageDefaultProperties();
122+
123+
// Initialize session metadata
124+
Metadata.InitSession();
125+
}
126+
```
127+
128+
### Benefits
129+
1. **Synchronous Loading**: All properties loaded from disk during `Init()` before it returns
130+
2. **No Race Condition**: `Track()` can be called immediately after `Init()` with properties guaranteed to be available
131+
3. **Session Metadata Ready**: Session ID and counters initialized before first event
132+
4. **Performance**: Auto properties cached once instead of regenerating
133+
134+
## Testing Recommendations
135+
136+
### For Customers
137+
1. Deploy updated SDK to staging environment
138+
2. Test immediate tracking after Init():
139+
```csharp
140+
Mixpanel.Init();
141+
Mixpanel.Register("test_property", "test_value");
142+
Mixpanel.Track("App Start"); // Should include test_property
143+
```
144+
3. Verify super properties present on first event in production
145+
4. Monitor event volumes for 1-2 weeks post-deployment
146+
5. Compare App Start/Exit event volumes to pre-migration baseline
147+
148+
### For Mixpanel QA
149+
1. Test on low-end Android devices (slower storage I/O)
150+
2. Test with large super property sets (slower loading)
151+
3. Test rapid Init() → Track() sequences
152+
4. Verify session metadata present on first event
153+
5. Test App Exit event flush behavior
154+
155+
## References
156+
- **Slack Thread**: #mixpanel-sagomini, Nov 5-19, 2025
157+
- **Zendesk Case**: #674175
158+
- **Customer**: Sago Mini (Piknik)
159+
- **Project**: Sago Mini - Production (ID: 210340)
160+
- **Dashboard**: https://mixpanel.com/project/210340/view/23451/app/insights#fTLhAYFBMnRZ
161+
162+
## Related Code Files
163+
- `Mixpanel/Controller.cs` - Initialization logic
164+
- `Mixpanel/Storage.cs` - Property persistence and lazy loading
165+
- `Mixpanel/MixpanelAPI.cs` - Public API surface
166+
167+
## Timeline
168+
- **Oct 1, 2025**: Customer rolled out Unity SDK migration to production
169+
- **Nov 5, 2025**: Customer reported issue to Mixpanel
170+
- **Nov 10, 2025**: Escalated to Senior Support Engineer
171+
- **Nov 18, 2025**: Mobile Engineering team engaged (Jared McFarland)
172+
- **Nov 19, 2025**: Root cause identified, fix in progress
173+
- **Nov 20, 2025**: Fix implemented and tested

0 commit comments

Comments
 (0)