public IHttpActionResult Push(NewMetricMessage newMetric) { // If special guid, then don't store anything var ipAddress = GetIPAddress(); if (newMetric.SpecialId == ByPassSpecialGuid) //filter out SSKK by default { Trace.TraceInformation("/api/push-metric (origin: {0}) with SpecialGuid not saved {1}", ipAddress, JsonConvert.SerializeObject(newMetric)); return(Ok()); } // TODO: Disable pooling for now to make sure that we don't starve global ThreadPool as it is used also by ASP.net // Put this immediately in a worker thread //ThreadPool.QueueUserWorkItem(state => //{ var clock = Stopwatch.StartNew(); MetricEvent result; using (var db = new MetricDbContext()) { result = db.SaveNewMetric(newMetric, ipAddress); } Trace.TraceInformation("/api/push-metric New metric saved in {0}ms: {1}", clock.ElapsedMilliseconds, JsonConvert.SerializeObject(result)); //}); return(Ok()); }
public static void Fill(MetricDbContext db) { var fromTime = new DateTime(2015, 01, 3); var toTime = DateTime.Now; var installGenerators = new List <PseudoInstallGenerator>() { new PseudoInstallGenerator(new DateTime(2015, 01, 20), 1, 3, "1.0.0") { new PseudoMetricEventGenerator(0.7, 1, -1, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(3)), new PseudoMetricEventGenerator(0.9, 1, -0.2, TimeSpan.FromMinutes(50), TimeSpan.FromMinutes(20)), new PseudoMetricEventGenerator(1.0, 2, -0.05, TimeSpan.FromHours(2), TimeSpan.FromHours(1)), }, new PseudoInstallGenerator(new DateTime(2015, 03, 20), 1, 5, "1.1.0") { new PseudoMetricEventGenerator(0.5, 1, -1, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(3)), new PseudoMetricEventGenerator(0.7, 1, -0.2, TimeSpan.FromMinutes(50), TimeSpan.FromMinutes(20)), new PseudoMetricEventGenerator(0.9, 1, -0.01, TimeSpan.FromMinutes(50), TimeSpan.FromMinutes(20)), new PseudoMetricEventGenerator(1.0, 2, -0.005, TimeSpan.FromHours(3), TimeSpan.FromHours(1)), }, new PseudoInstallGenerator(toTime, 1, 10, "1.2.0") { new PseudoMetricEventGenerator(0.3, 1, -1, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(3)), new PseudoMetricEventGenerator(0.5, 1, -0.1, TimeSpan.FromMinutes(50), TimeSpan.FromMinutes(20)), new PseudoMetricEventGenerator(0.7, 1, -0.01, TimeSpan.FromMinutes(50), TimeSpan.FromMinutes(20)), new PseudoMetricEventGenerator(1.0, 2, -0.005, TimeSpan.FromHours(3), TimeSpan.FromHours(1)), }, }; var currentTime = fromTime; var random = new Random(0); var userInstalls = new List <PseudoInstall>(); while (currentTime < toTime) { var generator = installGenerators.FirstOrDefault(t => currentTime < t.Until); if (generator == null) { break; } var installCount = random.Next(generator.InstallCountMin, generator.InstallCountMax); for (int i = 0; i < installCount; i++) { var p = random.NextDouble(); foreach (var eventGenerators in generator.MetricEventGenerators) { if (p <= eventGenerators.Percentage) { eventGenerators.InstallGenerator = generator; var pseudoInstall = new PseudoInstall( new MetricInstall(Guid.NewGuid()) { Created = currentTime + TimeSpan.FromHours(6 + i * 10 / installCount) }, eventGenerators) { NumberPerDay = eventGenerators.NumberPerDay, }; // Save the install to the database db.Installs.Add(pseudoInstall.MetricInstall); // Add our new pseudo install userInstalls.Add(pseudoInstall); break; } } } db.SaveChanges(); int eventCount = 0; // Generate user events for (int i = 0; i < userInstalls.Count; i++) { var pseudoInstall = userInstalls[i]; // Saving and storing metrics per user install every day. This is not correct as we should ideally save them ordered by timestamp between all users // but for this test, we simplify this. for (int eventId = 0; eventId < pseudoInstall.NumberPerDay; eventId++) { var metricEvent = new NewMetricMessage() { ApplicationId = CommonApps.StrideEditorAppId.Guid, InstallId = pseudoInstall.MetricInstall.InstallGuid, SessionId = eventId, EventId = eventId, MetricId = CommonMetrics.OpenApplication.Guid, Value = pseudoInstall.EventGenerator.InstallGenerator.Version }; var time = currentTime + TimeSpan.FromHours(7 + eventId * 10 / pseudoInstall.NumberPerDay); db.SaveNewMetric(metricEvent, pseudoInstall.IPAddress, time, true); metricEvent = new NewMetricMessage() { ApplicationId = CommonApps.StrideEditorAppId.Guid, InstallId = pseudoInstall.MetricInstall.InstallGuid, SessionId = eventId, EventId = eventId, MetricId = CommonMetrics.CloseApplication.Guid, Value = string.Empty }; time += pseudoInstall.EventGenerator.Duration + TimeSpan.FromSeconds(random.NextDouble() * pseudoInstall.EventGenerator.DurationAddDelta.TotalSeconds); db.SaveNewMetric(metricEvent, pseudoInstall.IPAddress, time, true); eventCount += 2; } // Decrease the installs pseudoInstall.NumberPerDay += pseudoInstall.EventGenerator.DecreaseNumberPerDay; if (pseudoInstall.NumberPerDay <= 0.0) { userInstalls.RemoveAt(i); i--; } } db.SaveChanges(); Debug.WriteLine("{0}: Users: {1} Events {2}", currentTime, userInstalls.Count, eventCount); // Add one day currentTime += TimeSpan.FromDays(1); } }
internal MetricEvent SaveNewMetric(NewMetricMessage newMetric, string ipAddress, DateTime?overrideTime = null, bool disableSave = false) { var applicationId = this.GetApplicationId(newMetric.ApplicationId); if (applicationId == -1) { Trace.TraceError($"Invalid ApplicationId {newMetric.ApplicationId} from {ipAddress}"); throw new InvalidOperationException($"Invalid ApplicationId {newMetric.ApplicationId} from {ipAddress}"); } //Debug.WriteLine("Save - ApplicationId {0}ms", clock.ElapsedMilliseconds); //clock.Restart(); var installId = this.GetOrCreateInstallId(newMetric.InstallId); //Debug.WriteLine("Save - InstallId {0}ms", clock.ElapsedMilliseconds); //clock.Restart(); var metricId = this.GetMetricId(newMetric.MetricId); //Debug.WriteLine("Save - MetricId {0}ms", clock.ElapsedMilliseconds); //clock.Restart(); var metricEvent = new MetricEvent { AppId = applicationId, InstallId = installId, SessionId = newMetric.SessionId, MetricId = metricId, IPAddress = ipAddress, EventId = newMetric.EventId, MetricValue = newMetric.Value ?? string.Empty }; if (overrideTime.HasValue) { metricEvent.Timestamp = overrideTime.Value; } var metricAsJson = JsonConvert.SerializeObject(newMetric); if (!metricEvent.Validate()) { Trace.TraceError($"Invalid MetricEvent, cannot save: {metricAsJson}"); throw new InvalidOperationException($"Invalid MetricEvent {metricAsJson}"); } // If element valid, use the MetricEvent for loggin from here metricAsJson = JsonConvert.SerializeObject(metricEvent); var newMetricEvent = Metrics.Add(metricEvent); if (!disableSave) { try { SaveChanges(); return(newMetricEvent); } catch (Exception ex) { Trace.TraceError("Unable to save MetricEvent, cannot save: {0} {1}", ex, metricAsJson); throw; } } return(null); }