private void Start() { MigrateFrom1To2(); MixpanelTracking(); CheckForMixpanelImplemented(); Mixpanel.Log($"Mixpanel Component Started"); StartCoroutine(WaitAndFlush()); }
private static void DispatchOperations() { ThreadOperation operation = _ops.Dequeue(); if (operation == null) { return; } Mixpanel.Log($"Dispatching new operation: {operation.GetAction()}"); Value data = operation.GetWhat(); switch (operation.GetAction()) { case ThreadOperation.ThreadOperationAction.ENQUEUE_EVENTS: MixpanelStorage.TrackPersistentQueue.Enqueue(data); break; case ThreadOperation.ThreadOperationAction.ENQUEUE_PEOPLE: MixpanelStorage.EngagePersistentQueue.Enqueue(data); break; case ThreadOperation.ThreadOperationAction.FLUSH: if (_isBgThreadRunning) { IEnumerator trackEnum = SendData(MixpanelStorage.TrackPersistentQueue, Config.TrackUrl); IEnumerator engageEnum = SendData(MixpanelStorage.EngagePersistentQueue, Config.EngageUrl); while (trackEnum.MoveNext()) { } ; while (engageEnum.MoveNext()) { } ; } else { Controller.GetInstance().StartCoroutine(SendData(MixpanelStorage.TrackPersistentQueue, Config.TrackUrl)); Controller.GetInstance().StartCoroutine(SendData(MixpanelStorage.EngagePersistentQueue, Config.EngageUrl)); } break; case ThreadOperation.ThreadOperationAction.CLEAR_QUEUE: MixpanelStorage.TrackPersistentQueue.Clear(); MixpanelStorage.EngagePersistentQueue.Clear(); break; case ThreadOperation.ThreadOperationAction.KILL_THREAD: _isBgThreadRunning = false; _bgThread.Abort(); // Will throw an exception break; default: break; } }
internal static void EnqueueMixpanelQueue(PersistentQueue persistentQueue, Value data) { using (PersistentQueueSession session = persistentQueue.OpenSession()) { session.Enqueue(Encoding.UTF8.GetBytes(JsonUtility.ToJson(data))); Mixpanel.Put(data); session.Flush(); } }
private IEnumerator Start() { DontDestroyOnLoad(this); while (true) { yield return(new WaitForSecondsRealtime(MixpanelSettings.Instance.FlushInterval)); Mixpanel.Flush(); } }
/// <summary> /// Checks whether Mixpanel is initialized or not. If it is not, every API will be no-op. /// </summary> public static bool IsInitialized() { bool initialized = Controller.IsInitialized(); if (!initialized) { Mixpanel.Log("Mixpanel is not initialized"); } return(initialized); }
private static void InitializeBeforeSceneLoad() { MixpanelSettings.LoadSettings(); if (Config.ManualInitialization) { return; } Initialize(); Mixpanel.Log($"Track Queue Depth: {MixpanelStorage.TrackPersistentQueue.CurrentCountOfItemsInQueue}"); Mixpanel.Log($"Engage Queue Depth: {MixpanelStorage.EngagePersistentQueue.CurrentCountOfItemsInQueue}"); }
private IEnumerator DoRequest(string url, PersistentQueue queue, int retryCount = 0) { int count = 0; Value batch = Mixpanel.ArrayPool.Get(); using (PersistentQueueSession session = queue.OpenSession()) { while (count < BatchSize) { byte[] data = session.Dequeue(); if (data == null) { break; } batch.Add(JsonUtility.FromJson <Value>(Encoding.UTF8.GetString(data))); ++count; } // If the batch is empty don't send the request if (count == 0) { yield break; } string payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(batch.ToString())); if (MixpanelSettings.Instance.ShowDebug) { Debug.Log($"[Mixpanel] Sending Request - '{url}' with payload '{payload}'"); } WWWForm form = new WWWForm(); form.AddField("data", payload); UnityWebRequest request = UnityWebRequest.Post(url, form); yield return(request.SendWebRequest()); while (!request.isDone) { yield return(new WaitForEndOfFrame()); } if (!request.isNetworkError && !request.isHttpError) { session.Flush(); Mixpanel.Put(batch); yield break; } if (retryCount > RetryMaxTries) { yield break; } } retryCount += 1; // 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 = 2046 seconds total yield return(new WaitForSecondsRealtime((float)Math.Pow(2, retryCount))); StartCoroutine(DoRequest(url, queue, retryCount)); }
private IEnumerator Start() { MigrateFrom1To2(); DontDestroyOnLoad(this); //Worker.StartWorkerThread(); TrackIntegrationEvent(); Mixpanel.Log($"Mixpanel Component Started"); while (true) { yield return(new WaitForSecondsRealtime(Config.FlushInterval)); DoFlush(); } }
public void OnRecycle() { _string = ""; _bool = false; _number = 0; foreach (Value item in _array) { Mixpanel.Put(item); } _array.Clear(); foreach (Value value in _container.Values) { Mixpanel.Put(value); } _container.Clear(); }
private static void RunBackgroundThread() { _isBgThreadRunning = true; while (!_stopThread) { try { DispatchOperations(); } catch (Exception e) { Mixpanel.LogError(e.ToString()); } } _isBgThreadRunning = false; }
private void LateUpdateEngageQueue() { if (EngageQueue.Count == 0) { return; } using (PersistentQueueSession session = Mixpanel.EngageQueue.OpenSession()) { foreach (Value item in EngageQueue) { session.Enqueue(Encoding.UTF8.GetBytes(JsonUtility.ToJson(item))); Mixpanel.Put(item); } session.Flush(); } EngageQueue.Clear(); }
private IEnumerator SendData(MixpanelStorage.FlushType flushType) { if (_retryTime > DateTime.Now && _retryCount > 0) { yield break; } string url = (flushType == MixpanelStorage.FlushType.EVENTS) ? Config.TrackUrl : Config.EngageUrl; Value batch = MixpanelStorage.DequeueBatchTrackingData(flushType, Config.BatchSize); while (batch.Count > 0) { WWWForm form = new WWWForm(); String payload = batch.ToString(); form.AddField("data", payload); Mixpanel.Log("Sending batch of data: " + payload); using (UnityWebRequest request = UnityWebRequest.Post(url, form)) { yield return(request.SendWebRequest()); #if UNITY_2020_1_OR_NEWER if (request.result != UnityWebRequest.Result.Success) #else if (request.isHttpError || request.isNetworkError) #endif { Mixpanel.Log("API request to " + url + "has failed with reason " + request.error); _retryCount += 1; double retryIn = Math.Pow(2, _retryCount - 1) * 60; retryIn = Math.Min(retryIn, 10 * 60); // limit 10 min _retryTime = DateTime.Now; _retryTime = _retryTime.AddSeconds(retryIn); Mixpanel.Log("Retrying request in " + retryIn + " seconds (retryCount=" + _retryCount + ")"); yield break; } else { _retryCount = 0; MixpanelStorage.DeleteBatchTrackingData(batch); batch = MixpanelStorage.DequeueBatchTrackingData(flushType, Config.BatchSize); Mixpanel.Log("Successfully posted to " + url); } } } }
private IEnumerator BuildRequest(string id, MixpanelBatch batch, int retryCount = 0) { string url = batch.Url; if (MixpanelSettings.Instance.ShowDebug) { Debug.Log($"[Mixpanel] Sending Request - '{url}'"); } UnityWebRequest request = UnityWebRequest.Get(url); yield return(request.SendWebRequest()); while (!request.isDone) { yield return(new WaitForEndOfFrame()); } // TODO: Be smarter about the errors coming back? if (!request.isNetworkError && !request.isHttpError) { Mixpanel.SuccessfulBatch(id); yield break; } if (request.responseCode == 413) // Payload Too Large { Mixpanel.ReBatch(id, batch); _needsFlush = true; yield break; } if (retryCount > RetryMaxTries) { Mixpanel.BisectBatch(id, batch); _needsFlush = true; yield break; } Debug.LogWarning($"[Mixpanel] Failed to sent batch because - '{request.error}'"); retryCount += 1; // 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 = 2046 seconds total yield return(new WaitForSecondsRealtime((float)Math.Pow(2, retryCount))); StartCoroutine(BuildRequest(id, batch, retryCount)); }
private void OnApplicationQuit() { Mixpanel.Track("App Session"); Mixpanel.Save(); Mixpanel.Flush(); }
internal static IEnumerator SendData(Queue <Value> queue, string url) { if (queue.Count == 0) { yield break; } int depth = queue.Count; int numBatches = (depth / Config.BatchSize) + (depth % Config.BatchSize != 0 ? 1 : 0); for (int i = 0; i < numBatches; i++) { if (_stopThread) { yield break; } Value batch = Value.Array; int count = 0; while (count < Config.BatchSize && queue.Count > 0) { Value data = queue.Dequeue(); if (data == null) { break; } try { batch.Add(data); } catch (Exception e) { Mixpanel.LogError($"There was an error processing event [{count}] from the internal object pool: " + e); } ++count; } if (count == 0) { yield break; } string payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(batch.ToString())); Mixpanel.Log($"Sending Request - '{url}' with payload '{payload}'"); bool successful = false; int responseCode = -1; string response = null; if (_isBgThreadRunning) { try { var content = new StringContent("data=" + payload, Encoding.UTF8, "application/json"); var responseRequest = _client.PostAsync(url, content).Result; responseCode = (int)responseRequest.StatusCode; response = responseRequest.Content.ReadAsStringAsync().Result; } catch (Exception e) { Mixpanel.LogError("There was an error sending the request: " + e); } } else { WWWForm form = new WWWForm(); form.AddField("data", payload); UnityWebRequest request = UnityWebRequest.Post(url, form); yield return(request.SendWebRequest()); while (!request.isDone) { yield return(new WaitForEndOfFrame()); } responseCode = (int)request.responseCode; response = request.downloadHandler.text; } Mixpanel.Log($"Response - '{url}' was '{response}'"); successful = responseCode == (int)HttpStatusCode.OK; if (successful) { _retryCount = 0; } else { _retryCount += 1; double retryIn = Math.Pow(2, _retryCount) * 60000; retryIn = Math.Min(retryIn, 10 * 60 * 1000); // limit 10 min Mixpanel.Log("Retrying request in " + retryIn / 1000 + " seconds (retryCount=" + _retryCount + ")"); _retryTimer = new System.Threading.Timer((obj) => { ForceFlushOp(); _retryTimer.Dispose(); }, null, (int)retryIn, System.Threading.Timeout.Infinite); yield break; } } }
private static void Initialize() { _instance = new GameObject("Mixpanel").AddComponent <MixpanelManager>(); Mixpanel.Load(); }
private void OnApplicationPause(bool pauseStatus) { Mixpanel.Save(); }
void OnDestroy() { Mixpanel.Log($"Mixpanel Component Destroyed"); }
private void MigrateFrom1To2() { if (!MixpanelStorage.HasMigratedFrom1To2) { string stateFile = Application.persistentDataPath + "/mp_state.json"; try { if (System.IO.File.Exists(stateFile)) { string state = System.IO.File.ReadAllText(stateFile); Value stateValue = Value.Deserialize(state); string distinctIdKey = "distinct_id"; if (stateValue.ContainsKey(distinctIdKey) && !stateValue[distinctIdKey].IsNull) { string distinctId = stateValue[distinctIdKey]; MixpanelStorage.DistinctId = distinctId; } string optedOutKey = "opted_out"; if (stateValue.ContainsKey(optedOutKey) && !stateValue[optedOutKey].IsNull) { bool optedOut = stateValue[optedOutKey]; MixpanelStorage.IsTracking = !optedOut; } string trackedIntegrationKey = "tracked_integration"; if (stateValue.ContainsKey(trackedIntegrationKey) && !stateValue[trackedIntegrationKey].IsNull) { bool trackedIntegration = stateValue[trackedIntegrationKey]; MixpanelStorage.HasIntegratedLibrary = trackedIntegration; } } } catch (Exception) { Mixpanel.LogError("Error migrating state from v1 to v2"); } finally { System.IO.File.Delete(stateFile); } string superPropertiesFile = Application.persistentDataPath + "/mp_super_properties.json"; try { if (System.IO.File.Exists(superPropertiesFile)) { string superProperties = System.IO.File.ReadAllText(superPropertiesFile); Value superPropertiesValue = Value.Deserialize(superProperties); foreach (KeyValuePair <string, Value> kvp in superPropertiesValue) { if (!kvp.Key.StartsWith("$")) { Mixpanel.Register(kvp.Key, kvp.Value); } } } } catch (Exception) { Mixpanel.LogError("Error migrating super properties from v1 to v2"); } finally { System.IO.File.Delete(superPropertiesFile); } MixpanelStorage.HasMigratedFrom1To2 = true; } }
private static void InitializeBeforeSceneLoad() { GetInstance(); Mixpanel.Log($"Track Queue Depth: {MixpanelStorage.TrackPersistentQueue.CurrentCountOfItemsInQueue}"); Mixpanel.Log($"Engage Queue Depth: {MixpanelStorage.EngagePersistentQueue.CurrentCountOfItemsInQueue}"); }
void OnDestroy() { Mixpanel.Log($"Mixpanel Component Destroyed"); //Worker.StopWorkerThread(); }
private static void InitializeAfterSceneLoad() { Mixpanel.CollectAutoProperties(); }