/// <summary> /// Enqueues the events for delivery. The event is stored in an <see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.Internal.IEventStore"/>. /// </summary> /// <param name="eventObject">Event object. <see cref="Amazon.MobileAnalytics.Model.Event"/></param> public void EnqueueEventsForDelivery(Amazon.MobileAnalytics.Model.Event eventObject) { ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { string eventString = eventObject.MarshallToJson(); bool eventStored = false; try { eventStored = _eventStore.PutEvent(eventString, _appId); } catch (Exception e) { _logger.Error(e, "Event {0} is unable to be stored.", eventObject.EventType); } if (eventStored) { _logger.DebugFormat("Event {0} is queued for delivery", eventObject.EventType); } else { EventStoreException e = new EventStoreException("Event cannot be stored."); _logger.Error(e, "Event {0} is unable to be queued for delivery.", eventObject.EventType); } })); }
private void EnqueueEventsHelper(Amazon.MobileAnalytics.Model.Event eventObject) { string eventString = null; try { eventString = JsonMapper.ToJson(eventObject); } catch (Exception e) { _logger.Error(e, "An exception occurred when converting low level client event to json string."); List <Amazon.MobileAnalytics.Model.Event> eventList = new List <Amazon.MobileAnalytics.Model.Event>(); eventList.Add(eventObject); MobileAnalyticsErrorEventArgs eventArgs = new MobileAnalyticsErrorEventArgs(this.GetType().Name, "An exception occurred when converting low level client event to json string.", e, eventList); _maManager.OnRaiseErrorEvent(eventArgs); } if (null != eventString) { try { _eventStore.PutEvent(eventString, _appID); } catch (Exception e) { _logger.Error(e, "Event {0} was not stored.", eventObject.EventType); MobileAnalyticsErrorEventArgs eventArgs = new MobileAnalyticsErrorEventArgs(this.GetType().Name, "An exception occurred when storing event into event store.", e, new List <Amazon.MobileAnalytics.Model.Event>()); _maManager.OnRaiseErrorEvent(eventArgs); } _logger.DebugFormat("Event {0} is queued for delivery", eventObject.EventType); } }
/// <summary> /// Enqueues the events for delivery. The event is stored in an instance of <see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.Internal.IEventStore"/>. /// </summary> /// <param name="eventObject">Event object.<see cref="Amazon.MobileAnalytics.Model.Event"/></param> public void EnqueueEventsForDelivery(Amazon.MobileAnalytics.Model.Event eventObject) { ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { EnqueueEventsHelper(eventObject); })); }
private Amazon.MobileAnalytics.Model.Event BuildSessionEndEvent(string sessionID) { Amazon.MobileAnalytics.Model.Event sessionEndEvent = new Amazon.MobileAnalytics.Model.Event(); sessionEndEvent.EventType = "_session.stop"; //CultureInfo provider = CultureInfo.InvariantCulture; Amazon.MobileAnalytics.Model.Session session = new Amazon.MobileAnalytics.Model.Session(); session.Id = sessionID; session.StartTimestamp = DateTime.UtcNow; session.StopTimestamp = DateTime.UtcNow; session.Duration = (long)TimeSpan.FromSeconds(20).TotalMilliseconds; sessionEndEvent.Session = session; Dictionary <string, string> attributes = new Dictionary <string, string>(); sessionEndEvent.Attributes = attributes; Dictionary <string, double> metrics = new Dictionary <string, double>(); sessionEndEvent.Metrics = metrics; sessionEndEvent.Version = "v2.0"; sessionEndEvent.Timestamp = DateTime.UtcNow; return(sessionEndEvent); }
/// <summary> /// Enqueues the events for delivery. The event is stored in an instance of <see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.Internal.IEventStore"/>. /// </summary> /// <param name="eventObject">Event object.<see cref="Amazon.MobileAnalytics.Model.Event"/></param> public void EnqueueEventsForDelivery(Amazon.MobileAnalytics.Model.Event eventObject) { Task.Run(() => { EnqueueEventsHelper(eventObject); }); }
private Amazon.MobileAnalytics.Model.Event BuildMonetizationEvent() { Amazon.MobileAnalytics.Model.Event monetizationEvent = new Amazon.MobileAnalytics.Model.Event(); monetizationEvent.EventType = "_monetization.purchase"; Amazon.MobileAnalytics.Model.Session session = new Amazon.MobileAnalytics.Model.Session(); session.Id = Guid.NewGuid().ToString(); session.StartTimestamp = DateTime.UtcNow; monetizationEvent.Session = session; Dictionary <string, string> attributes = new Dictionary <string, string>(); attributes.Add("_currency_", "USD"); attributes.Add("_product_id", "Kindle"); monetizationEvent.Attributes = attributes; Dictionary <string, double> metrics = new Dictionary <string, double>(); metrics.Add("_quantity", 2); metrics.Add("_item_price", 110.0); monetizationEvent.Metrics = metrics; monetizationEvent.Version = "v2.0"; monetizationEvent.Timestamp = DateTime.Now.ToUniversalTime(); return(monetizationEvent); }
private Amazon.MobileAnalytics.Model.Event BuildSessionStartEvent(string sessionID) { Amazon.MobileAnalytics.Model.Event sessionStartEvent = new Amazon.MobileAnalytics.Model.Event(); sessionStartEvent.EventType = "_session.start"; //CultureInfo provider = CultureInfo.InvariantCulture; Amazon.MobileAnalytics.Model.Session session = new Amazon.MobileAnalytics.Model.Session(); session.Id = sessionID; session.StartTimestamp = DateTime.UtcNow; sessionStartEvent.Session = session; Dictionary <string, string> attributes = new Dictionary <string, string>(); sessionStartEvent.Attributes = attributes; Dictionary <string, double> metrics = new Dictionary <string, double>(); sessionStartEvent.Metrics = metrics; sessionStartEvent.Version = "v2.0"; sessionStartEvent.Timestamp = DateTime.UtcNow; return(sessionStartEvent); }
private Amazon.MobileAnalytics.Model.Event BuildCustomEvent() { Amazon.MobileAnalytics.Model.Event customEvent = new Amazon.MobileAnalytics.Model.Event(); customEvent.EventType = "LevelComplete"; Amazon.MobileAnalytics.Model.Session session = new Amazon.MobileAnalytics.Model.Session(); session.Id = Guid.NewGuid().ToString(); session.StartTimestamp = DateTime.UtcNow; session.StopTimestamp = DateTime.UtcNow; session.Duration = (long)TimeSpan.FromMinutes(30).TotalMilliseconds; customEvent.Session = session; Dictionary <string, string> attributes = new Dictionary <string, string>(); attributes.Add("LevelName", "Level1"); attributes.Add("CharacterClass", "Warrior"); attributes.Add("Successful", "True"); customEvent.Attributes = attributes; Dictionary <string, double> metrics = new Dictionary <string, double>(); metrics.Add("Score", 12345); metrics.Add("TimeInLevel", 64); customEvent.Metrics = metrics; customEvent.Version = "v2.0"; customEvent.Timestamp = DateTime.UtcNow; return(customEvent); }
/// <summary> /// Enqueues the events for delivery. The event is stored in an instance of <see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.Internal.IEventStore"/>. /// </summary> /// <param name="eventObject">Event object.<see cref="Amazon.MobileAnalytics.Model.Event"/></param> public void EnqueueEventsForDelivery(Amazon.MobileAnalytics.Model.Event eventObject) { #if BCL35 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { #elif PCL || BCL45 Task.Run(() => { #endif string eventString = JsonMapper.ToJson(eventObject); try { _eventStore.PutEvent(eventString, _appID); } catch (Exception e) { _logger.Error(e, "Event {0} is unable to be stored.", eventObject.EventType); } _logger.DebugFormat("Event {0} is queued for delivery", eventObject.EventType); #if BCL35 })); #elif PCL || BCL45 });
/// <summary> /// Attempts the delivery. /// It will fail delivery if any of the policies.isAllowed() returns false. /// The policies are attmpted in batches of fixed size. To increase or decrease the size of bytes /// transfered per batch you can awsconfig.xml and configure the maxRequestSize property. /// </summary> /// <param name="policies">list of <see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.IDeliveryPolicy"/></param> private void AttemptDelivery(List <IDeliveryPolicy> policies) { //validate all the policies before attempting the delivery foreach (IDeliveryPolicy policy in policies) { if (!policy.IsAllowed()) { _logger.InfoFormat("Policy restriction: {0}", policy.GetType().Name); lock (_deliveryLock) { _deliveryInProgress = false; } return; } } List <string> rowIds = new List <string>(); long maxRequestSize = AWSConfigsMobileAnalytics.MaxRequestSize; List <JsonData> eventList = _eventStore.GetAllEvents(_appId); if (eventList.Count == 0) { _logger.InfoFormat("No Events to deliver"); lock (_deliveryLock) { _deliveryInProgress = false; } return; } long eventsLength = 0L; List <Amazon.MobileAnalytics.Model.Event> eventArray = new List <Amazon.MobileAnalytics.Model.Event>(); foreach (JsonData eventData in eventList) { eventsLength += ((string)eventData["event"]).Length; if (eventsLength < maxRequestSize) { string eventString = (string)eventData["event"]; _logger.InfoFormat("Event string is {0}", eventString); Amazon.MobileAnalytics.Model.Event _analyticsEvent = Amazon.MobileAnalytics.Model.Event.UnmarshallFromJson(eventString); eventArray.Add(_analyticsEvent); rowIds.Add(eventData["id"].ToString()); } else { SubmitEvents(rowIds, eventArray, HandleResponse); rowIds = new List <string>(); eventArray = new List <Amazon.MobileAnalytics.Model.Event>(); eventsLength = 0L; } } SubmitEvents(rowIds, eventArray, HandleResponse); }
/// <summary> /// Enqueues the events for delivery. The event is stored in an instance of <see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.Internal.IEventStore"/>. /// </summary> /// <param name="eventObject">Event object.<see cref="Amazon.MobileAnalytics.Model.Event"/></param> public void EnqueueEventsForDelivery(Amazon.MobileAnalytics.Model.Event eventObject) { #if BCL35 ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { #elif PCL || BCL45 Task.Run(() => { #endif string eventString = null; try { eventString = JsonMapper.ToJson(eventObject); } catch (Exception e) { _logger.Error(e, "An exception occurred when converting low level client event to json string."); List <Amazon.MobileAnalytics.Model.Event> eventList = new List <Amazon.MobileAnalytics.Model.Event>(); eventList.Add(eventObject); MobileAnalyticsErrorEventArgs eventArgs = new MobileAnalyticsErrorEventArgs(this.GetType().Name, "An exception occurred when converting low level client event to json string.", e, eventList); _maManager.OnRaiseErrorEvent(eventArgs); } if (null != eventString) { try { _eventStore.PutEvent(eventString, _appID); } catch (Exception e) { _logger.Error(e, "Event {0} was not stored.", eventObject.EventType); MobileAnalyticsErrorEventArgs eventArgs = new MobileAnalyticsErrorEventArgs(this.GetType().Name, "An exception occurred when storing event into event store.", e, new List <Amazon.MobileAnalytics.Model.Event>()); _maManager.OnRaiseErrorEvent(eventArgs); } _logger.DebugFormat("Event {0} is queued for delivery", eventObject.EventType); } #if BCL35 })); #elif PCL || BCL45 });
/// <summary> /// Attempts the delivery. /// Delivery will fail if any of the policies IsAllowed() returns false. /// The delivery are attmpted in batches of fixed size. To increase or decrease the size, /// you can override MaxRequestSize in MobileAnalyticsManagerConfig.<see cref="Amazon.MobileAnalytics.MobileAnalyticsManager.MobileAnalyticsManagerConfig"/> /// </summary> public void AttemptDelivery() { lock (_deliveryLock) { if (_deliveryInProgress) { _logger.InfoFormat("Delivery already in progress, failing new delivery"); return; } _deliveryInProgress = true; } //validate all the policies before attempting the delivery foreach (IDeliveryPolicy policy in _deliveryPolicies) { if (!policy.IsAllowed()) { _logger.InfoFormat("Policy restriction: {0}", policy.GetType().Name); lock (_deliveryLock) { _deliveryInProgress = false; } return; } } List <JsonData> allEventList = _eventStore.GetEvents(_appID, MAX_ALLOWED_SELECTS); if (allEventList.Count == 0) { _logger.InfoFormat("No Events to deliver."); lock (_deliveryLock) { _deliveryInProgress = false; } return; } List <string> submitEventsIdList = new List <string>(); List <Amazon.MobileAnalytics.Model.Event> submitEventsList = new List <Amazon.MobileAnalytics.Model.Event>(); long submitEventsLength = 0L; foreach (JsonData eventData in allEventList) { string eventString = (string)eventData["event"]; submitEventsLength += eventString.Length; if (submitEventsLength < _maConfig.MaxRequestSize) { try { Amazon.MobileAnalytics.Model.Event _analyticsEvent = JsonMapper.ToObject <Amazon.MobileAnalytics.Model.Event>(eventString); submitEventsList.Add(_analyticsEvent); } catch (JsonException e) { _logger.Error(e, "Could not load event from event store, discarding."); } submitEventsIdList.Add(eventData["id"].ToString()); } else { SubmitEvents(submitEventsIdList, submitEventsList); submitEventsIdList = new List <string>(); submitEventsList = new List <Amazon.MobileAnalytics.Model.Event>(); submitEventsLength = 0L; } } if (submitEventsLength > 0) { SubmitEvents(submitEventsIdList, submitEventsList); } }
public void TestMonetizationEventConcurrency() { // event type const string EVENT_TYPE = "_monetization.purchase"; const double QUANTITY = 321321; const double ITEM_PRICE = 854584; const string PRODUCT_ID = "PRODUCT_ID123"; const string ITEM_PRICE_FORMATTED = "$1.99"; const string STORE = "STORE"; const string TRANSACTION_ID = "TRANSACTION_ID123"; const string CURRENCY = "2.22"; // attribute config const string ATTR1 = "ATTR1"; string ATTR1_VAL_T0 = Guid.NewGuid().ToString(); string ATTR1_VAL_T1 = Guid.NewGuid().ToString(); string ATTR1_VAL_T2 = Guid.NewGuid().ToString(); const string ATTR2 = "ATTR2"; string ATTR2_VAL_T0 = Guid.NewGuid().ToString(); string ATTR2_VAL_T1 = Guid.NewGuid().ToString(); string ATTR2_VAL_T2 = Guid.NewGuid().ToString(); const string ATTR3 = "ATTR3"; string ATTR3_VAL_T0 = Guid.NewGuid().ToString(); string ATTR3_VAL_T1 = Guid.NewGuid().ToString(); string ATTR3_VAL_T2 = Guid.NewGuid().ToString(); // metric config System.Random randObj = new System.Random(); const string METRIC1 = "METRIC1"; double METRIC1_VAL_T0 = randObj.Next(); double METRIC1_VAL_T1 = randObj.Next(); double METRIC1_VAL_T2 = randObj.Next(); const string METRIC2 = "METRIC2"; double METRIC2_VAL_T0 = randObj.Next(); double METRIC2_VAL_T1 = randObj.Next(); double METRIC2_VAL_T2 = randObj.Next(); const string METRIC3 = "METRIC3"; double METRIC3_VAL_T0 = randObj.Next(); double METRIC3_VAL_T1 = randObj.Next(); double METRIC3_VAL_T2 = randObj.Next(); MonetizationEvent monetizationEvent = new MonetizationEvent(); const int LOOP_COUNT = 1; Task task0 = new Task(() => { int i = 0; for (i = 0; i < LOOP_COUNT; i++) { monetizationEvent.AddAttribute(ATTR1, ATTR1_VAL_T0); monetizationEvent.AddGlobalAttribute(ATTR2, ATTR2_VAL_T0); monetizationEvent.AddGlobalAttribute(EVENT_TYPE, ATTR3, ATTR3_VAL_T0); monetizationEvent.AddMetric(METRIC1, METRIC1_VAL_T0); monetizationEvent.AddGlobalMetric(METRIC2, METRIC2_VAL_T0); monetizationEvent.AddGlobalMetric(EVENT_TYPE, METRIC3, METRIC3_VAL_T0); } monetizationEvent.Quantity = QUANTITY; monetizationEvent.ItemPrice = ITEM_PRICE; }); Task task1 = new Task(() => { int i = 0; for (i = 0; i < LOOP_COUNT; i++) { monetizationEvent.AddAttribute(ATTR1, ATTR1_VAL_T1); monetizationEvent.AddGlobalAttribute(ATTR2, ATTR2_VAL_T1); monetizationEvent.AddGlobalAttribute(EVENT_TYPE, ATTR3, ATTR3_VAL_T1); monetizationEvent.AddMetric(METRIC1, METRIC1_VAL_T1); monetizationEvent.AddGlobalMetric(METRIC2, METRIC2_VAL_T1); monetizationEvent.AddGlobalMetric(EVENT_TYPE, METRIC3, METRIC3_VAL_T1); } monetizationEvent.ProductId = PRODUCT_ID; monetizationEvent.ItemPriceFormatted = ITEM_PRICE_FORMATTED; monetizationEvent.Store = STORE; monetizationEvent.TransactionId = TRANSACTION_ID; monetizationEvent.Currency = CURRENCY; }); Task task2 = new Task(() => { int i = 0; for (i = 0; i < LOOP_COUNT; i++) { monetizationEvent.AddAttribute(ATTR1, ATTR1_VAL_T2); monetizationEvent.AddGlobalAttribute(ATTR2, ATTR2_VAL_T2); monetizationEvent.AddGlobalAttribute(EVENT_TYPE, ATTR3, ATTR3_VAL_T2); monetizationEvent.AddMetric(METRIC1, METRIC1_VAL_T2); monetizationEvent.AddGlobalMetric(METRIC2, METRIC2_VAL_T2); monetizationEvent.AddGlobalMetric(EVENT_TYPE, METRIC3, METRIC3_VAL_T2); } }); task0.Start(); task1.Start(); task2.Start(); // wait all task complete Task.WaitAll(new[] { task0, task1, task2 }); // Get model event. Amazon.MobileAnalytics.Model.Event modelEvent = monetizationEvent.ConvertToMobileAnalyticsModelEvent(GetMobileAnalyticsManager("TestMonetizationEventConcurrency").Session); // Check attribute value. if (!modelEvent.Attributes.ContainsKey(ATTR1) || !modelEvent.Attributes.ContainsKey(ATTR2) || !modelEvent.Attributes.ContainsKey(ATTR3)) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR1] != ATTR1_VAL_T0 && modelEvent.Attributes[ATTR1] != ATTR1_VAL_T1 && modelEvent.Attributes[ATTR1] != ATTR1_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR2] != ATTR2_VAL_T0 && modelEvent.Attributes[ATTR2] != ATTR2_VAL_T1 && modelEvent.Attributes[ATTR2] != ATTR2_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR3] != ATTR3_VAL_T0 && modelEvent.Attributes[ATTR3] != ATTR3_VAL_T1 && modelEvent.Attributes[ATTR3] != ATTR3_VAL_T2) { Assert.Fail(); return; } // check metric value if (!modelEvent.Metrics.ContainsKey(METRIC1) || !modelEvent.Metrics.ContainsKey(METRIC2) || !modelEvent.Metrics.ContainsKey(METRIC3)) { Assert.Fail(); return; } if (modelEvent.Metrics[METRIC1] != METRIC1_VAL_T0 && modelEvent.Metrics[METRIC1] != METRIC1_VAL_T1 && modelEvent.Metrics[METRIC1] != METRIC1_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Metrics[METRIC2] != METRIC2_VAL_T0 && modelEvent.Metrics[METRIC2] != METRIC2_VAL_T1 && modelEvent.Metrics[METRIC2] != METRIC2_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Metrics[METRIC3] != METRIC3_VAL_T0 && modelEvent.Metrics[METRIC3] != METRIC3_VAL_T1 && modelEvent.Metrics[METRIC3] != METRIC3_VAL_T2) { Assert.Fail(); return; } // metric name const string PURCHASE_EVENT_QUANTITY_METRIC = "_quantity"; const string PURCHASE_EVENT_ITEM_PRICE_METRIC = "_item_price"; // attribute name const string PURCHASE_EVENT_PRODUCT_ID_ATTR = "_product_id"; const string PURCHASE_EVENT_ITEM_PRICE_FORMATTED_ATTR = "_item_price_formatted"; const string PURCHASE_EVENT_STORE_ATTR = "_store"; const string PURCHASE_EVENT_TRANSACTION_ID_ATTR = "_transaction_id"; const string PURCHASE_EVENT_CURRENCY_ATTR = "_currency"; if (modelEvent.Metrics[PURCHASE_EVENT_QUANTITY_METRIC] != QUANTITY || modelEvent.Metrics[PURCHASE_EVENT_ITEM_PRICE_METRIC] != ITEM_PRICE) { Assert.Fail(); return; } if (modelEvent.Attributes[PURCHASE_EVENT_PRODUCT_ID_ATTR] != PRODUCT_ID || modelEvent.Attributes[PURCHASE_EVENT_ITEM_PRICE_FORMATTED_ATTR] != ITEM_PRICE_FORMATTED || modelEvent.Attributes[PURCHASE_EVENT_STORE_ATTR] != STORE || modelEvent.Attributes[PURCHASE_EVENT_TRANSACTION_ID_ATTR] != TRANSACTION_ID || modelEvent.Attributes[PURCHASE_EVENT_CURRENCY_ATTR] != CURRENCY) { Assert.Fail(); return; } }
public void TestCustomEventConcurrency() { // event type const string EVENT_TYPE = "MyEventType"; // attribute config string ATTR1 = "ATTR1"; string ATTR1_VAL_T0 = "dshjadfhjdfa132`23jj`23jh1k2h3h21hg3h21j2gh"; string ATTR1_VAL_T1 = "gfhfdhgvkfdkgljfdgjfdsj;l34t43jj4erjerb"; string ATTR1_VAL_T2 = "7t32674tgdfjehkjdksjs;akfdshfjdsafkadsfdsljfa"; string ATTR2 = "ATTR2"; string ATTR2_VAL_T0 = "343hjfdshdfjklsafj0913432jh4"; string ATTR2_VAL_T1 = "378t43y21ggdhsgdahshfdjsfafd"; string ATTR2_VAL_T2 = "48ry42378tfhsfkds;kfl;dsdfk;ldslks"; string ATTR3 = "ATTR3"; string ATTR3_VAL_T0 = "321432g4ghjfjshdggfjhsdgfdskgfjdsjgfsd"; string ATTR3_VAL_T1 = "76432tgrsgerhjkfgshdfdssfgjdssaf"; string ATTR3_VAL_T2 = "87549353hjtkgdk;sfgfdgf;kfl;dshfjdsjkhfjs"; string ATTR_EMPTY1 = "ATTR_EMPTY1"; string ATTR_EMPTY2 = "ATTR_EMPTY2"; string ATTR_EMPTY3 = "ATTR_EMPTY3"; // metric config System.Random randObj = new System.Random(); const string METRIC1 = "METRIC1"; double METRIC1_VAL_T0 = randObj.Next(); double METRIC1_VAL_T1 = randObj.Next(); double METRIC1_VAL_T2 = randObj.Next(); const string METRIC2 = "METRIC2"; double METRIC2_VAL_T0 = randObj.Next(); double METRIC2_VAL_T1 = randObj.Next(); double METRIC2_VAL_T2 = randObj.Next(); const string METRIC3 = "METRIC3"; double METRIC3_VAL_T0 = randObj.Next(); double METRIC3_VAL_T1 = randObj.Next(); double METRIC3_VAL_T2 = randObj.Next(); CustomEvent customEvent = new CustomEvent(EVENT_TYPE); const int LOOP_COUNT = 999; Task task0 = new Task(() => { for (int i = 0; i < LOOP_COUNT; i++) { customEvent.AddAttribute(ATTR1, ATTR1_VAL_T0); customEvent.AddGlobalAttribute(ATTR2, ATTR2_VAL_T0); customEvent.AddGlobalAttribute(EVENT_TYPE, ATTR3, ATTR3_VAL_T0); customEvent.AddMetric(METRIC1, METRIC1_VAL_T0); customEvent.AddGlobalMetric(METRIC2, METRIC2_VAL_T0); customEvent.AddGlobalMetric(EVENT_TYPE, METRIC3, METRIC3_VAL_T0); customEvent.AddAttribute(ATTR_EMPTY1, ""); customEvent.AddGlobalAttribute(ATTR_EMPTY2, ""); customEvent.AddGlobalAttribute(EVENT_TYPE, ATTR_EMPTY3, ""); } }); Task task1 = new Task(() => { for (int i = 0; i < LOOP_COUNT; i++) { customEvent.AddAttribute(ATTR1, ATTR1_VAL_T1); customEvent.AddGlobalAttribute(ATTR2, ATTR2_VAL_T1); customEvent.AddGlobalAttribute(EVENT_TYPE, ATTR3, ATTR3_VAL_T1); customEvent.AddMetric(METRIC1, METRIC1_VAL_T1); customEvent.AddGlobalMetric(METRIC2, METRIC2_VAL_T1); customEvent.AddGlobalMetric(EVENT_TYPE, METRIC3, METRIC3_VAL_T1); } }); Task task2 = new Task(() => { for (int i = 0; i < LOOP_COUNT; i++) { customEvent.AddAttribute(ATTR1, ATTR1_VAL_T1); customEvent.AddGlobalAttribute(ATTR2, ATTR2_VAL_T1); customEvent.AddGlobalAttribute(EVENT_TYPE, ATTR3, ATTR3_VAL_T1); customEvent.AddMetric(METRIC1, METRIC1_VAL_T1); customEvent.AddGlobalMetric(METRIC2, METRIC2_VAL_T1); customEvent.AddGlobalMetric(EVENT_TYPE, METRIC3, METRIC3_VAL_T1); } }); task0.Start(); task1.Start(); task2.Start(); // wait all task complete Task.WaitAll(new[] { task0, task1, task2 }); // Get Model event. Amazon.MobileAnalytics.Model.Event modelEvent = customEvent.ConvertToMobileAnalyticsModelEvent(GetMobileAnalyticsManager("TestCustomEventConcurrency").Session); // check attribute value if (!modelEvent.Attributes.ContainsKey(ATTR1) || !modelEvent.Attributes.ContainsKey(ATTR2) || !modelEvent.Attributes.ContainsKey(ATTR3)) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR1] != ATTR1_VAL_T0 && modelEvent.Attributes[ATTR1] != ATTR1_VAL_T1 && modelEvent.Attributes[ATTR1] != ATTR1_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR2] != ATTR2_VAL_T0 && modelEvent.Attributes[ATTR2] != ATTR2_VAL_T1 && modelEvent.Attributes[ATTR2] != ATTR2_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR3] != ATTR3_VAL_T0 && modelEvent.Attributes[ATTR3] != ATTR3_VAL_T1 && modelEvent.Attributes[ATTR3] != ATTR3_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Attributes[ATTR_EMPTY1] != "" || modelEvent.Attributes[ATTR_EMPTY2] != "" || modelEvent.Attributes[ATTR_EMPTY3] != "") { Assert.Fail(); return; } // check metric value if (!modelEvent.Metrics.ContainsKey(METRIC1) || !modelEvent.Metrics.ContainsKey(METRIC2) || !modelEvent.Metrics.ContainsKey(METRIC3)) { Assert.Fail(); return; } if (modelEvent.Metrics[METRIC1] != METRIC1_VAL_T0 && modelEvent.Metrics[METRIC1] != METRIC1_VAL_T1 && modelEvent.Metrics[METRIC1] != METRIC1_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Metrics[METRIC2] != METRIC2_VAL_T0 && modelEvent.Metrics[METRIC2] != METRIC2_VAL_T1 && modelEvent.Metrics[METRIC2] != METRIC2_VAL_T2) { Assert.Fail(); return; } if (modelEvent.Metrics[METRIC3] != METRIC3_VAL_T0 && modelEvent.Metrics[METRIC3] != METRIC3_VAL_T1 && modelEvent.Metrics[METRIC3] != METRIC3_VAL_T2) { Assert.Fail(); return; } }