예제 #1
0
 private void Start()
 {
     MigrateFrom1To2();
     MixpanelTracking();
     CheckForMixpanelImplemented();
     Mixpanel.Log($"Mixpanel Component Started");
     StartCoroutine(WaitAndFlush());
 }
예제 #2
0
        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;
            }
        }
예제 #3
0
 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();
     }
 }
예제 #4
0
        private IEnumerator Start()
        {
            DontDestroyOnLoad(this);
            while (true)
            {
                yield return(new WaitForSecondsRealtime(MixpanelSettings.Instance.FlushInterval));

                Mixpanel.Flush();
            }
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
 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}");
 }
예제 #7
0
        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));
        }
예제 #8
0
        private IEnumerator Start()
        {
            MigrateFrom1To2();
            DontDestroyOnLoad(this);
            //Worker.StartWorkerThread();
            TrackIntegrationEvent();
            Mixpanel.Log($"Mixpanel Component Started");
            while (true)
            {
                yield return(new WaitForSecondsRealtime(Config.FlushInterval));

                DoFlush();
            }
        }
예제 #9
0
 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();
 }
예제 #10
0
 private static void RunBackgroundThread()
 {
     _isBgThreadRunning = true;
     while (!_stopThread)
     {
         try
         {
             DispatchOperations();
         }
         catch (Exception e)
         {
             Mixpanel.LogError(e.ToString());
         }
     }
     _isBgThreadRunning = false;
 }
예제 #11
0
 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();
 }
예제 #12
0
        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);
                    }
                }
            }
        }
예제 #13
0
        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));
        }
예제 #14
0
 private void OnApplicationQuit()
 {
     Mixpanel.Track("App Session");
     Mixpanel.Save();
     Mixpanel.Flush();
 }
예제 #15
0
        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;
                }
            }
        }
예제 #16
0
 private static void Initialize()
 {
     _instance = new GameObject("Mixpanel").AddComponent <MixpanelManager>();
     Mixpanel.Load();
 }
예제 #17
0
 private void OnApplicationPause(bool pauseStatus)
 {
     Mixpanel.Save();
 }
예제 #18
0
 void OnDestroy()
 {
     Mixpanel.Log($"Mixpanel Component Destroyed");
 }
예제 #19
0
        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;
            }
        }
예제 #20
0
 private static void InitializeBeforeSceneLoad()
 {
     GetInstance();
     Mixpanel.Log($"Track Queue Depth: {MixpanelStorage.TrackPersistentQueue.CurrentCountOfItemsInQueue}");
     Mixpanel.Log($"Engage Queue Depth: {MixpanelStorage.EngagePersistentQueue.CurrentCountOfItemsInQueue}");
 }
예제 #21
0
 void OnDestroy()
 {
     Mixpanel.Log($"Mixpanel Component Destroyed");
     //Worker.StopWorkerThread();
 }
예제 #22
0
 private static void InitializeAfterSceneLoad()
 {
     Mixpanel.CollectAutoProperties();
 }