public void QuickPulseServiceClientFillsInSampleWeightWhenSubmittingToService() { // ARRANGE var now = DateTimeOffset.UtcNow; var serviceClient = new QuickPulseServiceClient(this.serviceEndpoint, string.Empty, string.Empty, string.Empty, string.Empty, new Clock()); var sample1 = new QuickPulseDataSample( new QuickPulseDataAccumulator { AIRequestCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(3, 10000), StartTimestamp = now, EndTimestamp = now.AddSeconds(1) }, new Dictionary <string, Tuple <PerformanceCounterData, float> >()); var sample2 = new QuickPulseDataSample( new QuickPulseDataAccumulator { AIDependencyCallCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(4, 10000), StartTimestamp = now, EndTimestamp = now.AddSeconds(1) }, new Dictionary <string, Tuple <PerformanceCounterData, float> >()); // ACT serviceClient.SubmitSamples(new[] { sample1, sample2 }, string.Empty); // ASSERT this.listener.Stop(); Assert.AreEqual(3, this.samples[0].Item2.Metrics.Single(m => m.Name == @"\ApplicationInsights\Request Duration").Weight); Assert.AreEqual(4, this.samples[1].Item2.Metrics.Single(m => m.Name == @"\ApplicationInsights\Dependency Call Duration").Weight); }
public void QuickPulseDataAccumulatorCollectsTelemetryItemsInThreadSafeManner() { // ARRANGE CollectionConfigurationError[] errors; var accumulator = new QuickPulseDataAccumulator( new CollectionConfiguration( new CollectionConfigurationInfo() { ETag = string.Empty, Metrics = new CalculatedMetricInfo[0] }, out errors, new ClockMock())); // ACT var iterationCount = 1000; var concurrency = 12; Action addItemTask = () => Enumerable.Range(0, iterationCount) .ToList() .ForEach( i => accumulator.TelemetryDocuments.Push(new RequestTelemetryDocument() { Name = i.ToString(CultureInfo.InvariantCulture) })); var tasks = new List <Action>(); for (int i = 0; i < concurrency; i++) { tasks.Add(addItemTask); } Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = concurrency }, tasks.ToArray()); // ASSERT var dict = new Dictionary <int, int>(); foreach (var item in accumulator.TelemetryDocuments) { int requestNumber = int.Parse(((RequestTelemetryDocument)item).Name, CultureInfo.InvariantCulture); if (dict.ContainsKey(requestNumber)) { dict[requestNumber]++; } else { dict[requestNumber] = 1; } } Assert.AreEqual(iterationCount, dict.Count); Assert.IsTrue(dict.All(pair => pair.Value == concurrency)); }
private static QuickPulseDataSample CreateDataSample( QuickPulseDataAccumulator accumulator, IEnumerable <Tuple <PerformanceCounterData, double> > perfData, IEnumerable <Tuple <string, int> > topCpuData, bool topCpuDataAccessDenied) { return(new QuickPulseDataSample( accumulator, perfData.ToDictionary(tuple => tuple.Item1.ReportAs, tuple => tuple), topCpuData, topCpuDataAccessDenied)); }
private QuickPulseDataSample CollectSample() { // For AI data, all we have to do is lock the current accumulator in QuickPulseDataAccumulator completeAccumulator = this.dataAccumulatorManager.CompleteCurrentDataAccumulator(); // For performance collection, we have to read perf samples from Windows List <Tuple <PerformanceCounterData, float> > perfData = this.performanceCollector.Collect((counterName, e) => QuickPulseEventSource.Log.CounterReadingFailedEvent(e.ToString(), counterName)) .ToList(); return(this.CreateDataSample(completeAccumulator, perfData)); }
public void QuickPulseDataAccumulatorEncodesCountAndDurationOverflowDuration() { // ARRANGE // ACTt long encodedValue = QuickPulseDataAccumulator.EncodeCountAndDuration(MaxCount, MaxDuration + 1); Tuple <long, long> decodedValues = QuickPulseDataAccumulator.DecodeCountAndDuration(encodedValue); // ASSERT Assert.AreEqual(0, decodedValues.Item1); Assert.AreEqual(0, decodedValues.Item2); }
public void QuickPulseDataAccumulatorEncodesCountAndDuration() { // ARRANGE long count = 42; long duration = 102; // ACT long encodedValue = QuickPulseDataAccumulator.EncodeCountAndDuration(count, duration); Tuple <long, long> decodedValues = QuickPulseDataAccumulator.DecodeCountAndDuration(encodedValue); // ASSERT Assert.AreEqual(count, decodedValues.Item1); Assert.AreEqual(duration, decodedValues.Item2); }
public void QuickPulseDataSampleHandlesAbsentCounterInPerfData() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.IsFalse(dataSample.PerfCountersLookup.Any()); }
private void UpdateRequestAggregates(RequestTelemetry requestTelemetry) { long requestCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(1, requestTelemetry.Duration.Ticks); Interlocked.Add(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIRequestCountAndDurationInTicks, requestCountAndDurationInTicks); if (requestTelemetry.Success == true) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount); } else { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIRequestFailureCount); } }
public void QuickPulseDataSampleHandlesAbsentCounterInPerfData() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(0.0, dataSample.PerfIisQueueSize); }
public void QuickPulseDataSampleHandlesAbsentTopCpuData() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.IsFalse(dataSample.TopCpuData.Any()); }
public void QuickPulseDataSampleHandlesAbsentTopCpuData() { // ARRANGE var accumulator = new QuickPulseDataAccumulator(new CollectionConfiguration(EmptyCollectionConfigurationInfo, out this.errors, new ClockMock())) { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.IsFalse(dataSample.TopCpuData.Any()); }
public void QuickPulseDataSampleCalculatesAIDependencyCallsFailedPerSecondCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = this.now, EndTimestamp = this.now.AddSeconds(2), AIDependencyCallFailureCount = 10 }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.AreEqual(10.0 / 2, dataSample.AIDependencyCallsFailedPerSecond); }
public void QuickPulseDataSampleCalculatesAIRpsCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2), AIRequestCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(10, 0) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(10.0 / 2, dataSample.AIRequestsPerSecond); }
public void QuickPulseDataSampleCalculatesAIExceptionsPerSecondCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2), AIExceptionCount = 3 }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(3.0 / 2, dataSample.AIExceptionsPerSecond); }
public void QuickPulseDataSampleTimestampsItselfCorrectly() { // ARRANGE var timestampStart = DateTimeOffset.UtcNow; var timestampEnd = DateTimeOffset.UtcNow.AddSeconds(3); var accumulator = new QuickPulseDataAccumulator { StartTimestamp = timestampStart, EndTimestamp = timestampEnd }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(timestampStart, dataSample.StartTimestamp); Assert.AreEqual(timestampEnd, dataSample.EndTimestamp); }
public void QuickPulseDataSampleCalculatesAIDependencyCallsSucceededPerSecondCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2), AIDependencyCallSuccessCount = 10 }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(10.0 / 2, dataSample.AIDependencyCallsSucceededPerSecond); }
public void QuickPulseDataSampleCalculatesAIRequestDurationAveCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2), AIRequestCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(10, TimeSpan.FromSeconds(5).Ticks) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(TimeSpan.FromSeconds(5).TotalMilliseconds / 10.0, dataSample.AIRequestDurationAveInMs); }
public void QuickPulseDataSampleCalculatesAIDependencyCallDurationAveWhenDependencyCallCountIsZeroCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator(new CollectionConfiguration(EmptyCollectionConfigurationInfo, out this.errors, new ClockMock())) { StartTimestamp = this.now, EndTimestamp = this.now.AddSeconds(2), AIDependencyCallCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(0, TimeSpan.FromSeconds(5).Ticks) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.AreEqual(0.0, dataSample.AIDependencyCallDurationAveInMs); }
private void UpdateDependencyAggregates(DependencyTelemetry dependencyTelemetry) { long dependencyCallCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(1, dependencyTelemetry.Duration.Ticks); Interlocked.Add( ref this.dataAccumulatorManager.CurrentDataAccumulator.AIDependencyCallCountAndDurationInTicks, dependencyCallCountAndDurationInTicks); if (dependencyTelemetry.Success == true) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIDependencyCallSuccessCount); } else if (dependencyTelemetry.Success == false) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIDependencyCallFailureCount); } }
private QuickPulseDataSample CollectSample() { // For AI data, all we have to do is lock the current accumulator in QuickPulseDataAccumulator completeAccumulator = this.dataAccumulatorManager.CompleteCurrentDataAccumulator(); // For performance collection, we have to read perf samples from Windows List <Tuple <PerformanceCounterData, double> > perfData = this.performanceCollector.Collect((counterName, e) => QuickPulseEventSource.Log.CounterReadingFailedEvent(e.ToString(), counterName)) .ToList(); // For top N CPU, we have to get data from the provider IEnumerable <Tuple <string, int> > topCpuData = this.DisableTopCpuProcesses ? Enumerable.Empty <Tuple <string, int> >() : this.topCpuCollector.GetTopProcessesByCpu(TopCpuCount); return(this.CreateDataSample(completeAccumulator, perfData, topCpuData, this.topCpuCollector.AccessDenied)); }
public void QuickPulseDataSampleCalculatesAIExceptionsPerSecondCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator(new CollectionConfiguration(EmptyCollectionConfigurationInfo, out this.errors, new ClockMock())) { StartTimestamp = this.now, EndTimestamp = this.now.AddSeconds(2), AIExceptionCount = 3 }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.AreEqual(3.0 / 2, dataSample.AIExceptionsPerSecond); }
public void QuickPulseDataSampleCalculatesAIDependencyCallDurationAveWhenDependencyCallCountIsZeroCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2), AIDependencyCallCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(0, TimeSpan.FromSeconds(5).Ticks) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary); // ASSERT Assert.AreEqual(0.0, dataSample.AIDependencyCallDurationAveInMs); }
public void QuickPulseDataSampleCalculatesAIRequestDurationAveWhenRequestCountIsZeroCorrectly() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = this.now, EndTimestamp = this.now.AddSeconds(2), AIRequestCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(0, TimeSpan.FromSeconds(5).Ticks) }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.AreEqual(0.0, dataSample.AIRequestDurationAveInMs); }
public void QuickPulseDataSampleTimestampsItselfCorrectly() { // ARRANGE var timestampStart = this.now; var timestampEnd = this.now.AddSeconds(3); var accumulator = new QuickPulseDataAccumulator(new CollectionConfiguration(EmptyCollectionConfigurationInfo, out this.errors, new ClockMock())) { StartTimestamp = timestampStart, EndTimestamp = timestampEnd }; // ACT var dataSample = new QuickPulseDataSample(accumulator, this.dummyDictionary, this.dummyTopCpu, false); // ASSERT Assert.AreEqual(timestampStart, dataSample.StartTimestamp); Assert.AreEqual(timestampEnd, dataSample.EndTimestamp); }
public void QuickPulseDataSampleStoresTopCpuData() { // ARRANGE var accumulator = new QuickPulseDataAccumulator { StartTimestamp = DateTimeOffset.UtcNow, EndTimestamp = DateTimeOffset.UtcNow.AddSeconds(2) }; // ACT var dataSample = new QuickPulseDataSample( accumulator, this.dummyDictionary, new List <Tuple <string, int> >() { Tuple.Create("Process1", 25) }, false); // ASSERT Assert.AreEqual("Process1", dataSample.TopCpuData.Single().Item1); Assert.AreEqual(25, dataSample.TopCpuData.Single().Item2); }
/// <summary> /// Intercepts telemetry items and updates QuickPulse data when needed. /// </summary> /// <param name="telemetry">Telemetry item being tracked by AI.</param> /// <remarks>This method is performance critical since every AI telemetry item goes through it.</remarks> public void Process(ITelemetry telemetry) { bool letItemThrough = true; try { // filter out QPS requests from dependencies even when we're not collecting (for Pings) var dependencyCall = telemetry as DependencyTelemetry; if (this.serviceEndpoint != null && dependencyCall != null && !string.IsNullOrWhiteSpace(dependencyCall.Name)) { if (dependencyCall.Name.IndexOf(this.serviceEndpoint.Host, StringComparison.OrdinalIgnoreCase) >= 0) { // this is an HTTP request to QuickPulse service, we don't want to let it through letItemThrough = false; return; } } if (!this.isCollecting || this.dataAccumulatorManager == null) { return; } // only process items that are going to the instrumentation key that our module is initialized with if (this.config != null && !string.IsNullOrWhiteSpace(this.config.InstrumentationKey) && telemetry.Context != null && string.Equals(telemetry.Context.InstrumentationKey, this.config.InstrumentationKey, StringComparison.OrdinalIgnoreCase)) { var request = telemetry as RequestTelemetry; var exception = telemetry as ExceptionTelemetry; if (request != null) { bool success = IsRequestSuccessful(request); long requestCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(1, request.Duration.Ticks); Interlocked.Add(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIRequestCountAndDurationInTicks, requestCountAndDurationInTicks); if (success) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIRequestSuccessCount); } else { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIRequestFailureCount); } } else if (dependencyCall != null) { long dependencyCallCountAndDurationInTicks = QuickPulseDataAccumulator.EncodeCountAndDuration(1, dependencyCall.Duration.Ticks); Interlocked.Add(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIDependencyCallCountAndDurationInTicks, dependencyCallCountAndDurationInTicks); if (dependencyCall.Success == true) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIDependencyCallSuccessCount); } else if (dependencyCall.Success == false) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIDependencyCallFailureCount); } } else if (exception != null) { Interlocked.Increment(ref this.dataAccumulatorManager.CurrentDataAccumulator.AIExceptionCount); } } } catch (Exception e) { // whatever happened up there - we don't want to interrupt the chain of processors QuickPulseEventSource.Log.UnknownErrorEvent(e.ToInvariantString()); } finally { if (letItemThrough) { this.Next.Process(telemetry); } } }
private QuickPulseDataSample CreateDataSample( QuickPulseDataAccumulator accumulator, IEnumerable <Tuple <PerformanceCounterData, float> > perfData) { return(new QuickPulseDataSample(accumulator, perfData.ToDictionary(tuple => tuple.Item1.ReportAs, tuple => tuple))); }