/// <inheritdoc /> public IReservoirSnapshot GetSnapshot() { return(new WavefrontHistogramSnapshot( wavefrontHistogram.GetSnapshot(), WavefrontHistogramImpl.Serialize(wavefrontHistogram.FlushDistributions()) )); }
public void TestSnapshot() { var currentTime = DateTime.UtcNow; long clockMillis() => DateTimeUtils.UnixTimeMilliseconds(currentTime); var powHistogram = CreatePowHistogram(clockMillis); var rangeHistogram = CreateRangeHistogram(clockMillis); var multiThreadedHistogram = CreateMultiThreadedHistogram(clockMillis); var emptyHistogram = new WavefrontHistogramImpl(clockMillis); currentTime = currentTime.AddMinutes(1); var powSnapshot = powHistogram.GetSnapshot(); var rangeSnapshot = rangeHistogram.GetSnapshot(); var multiThreadedSnapshot = multiThreadedHistogram.GetSnapshot(); var emptySnapshot = emptyHistogram.GetSnapshot(); // Test snapshot for the pow histogram Assert.Equal(9, powSnapshot.Count); Assert.Equal(100000, powSnapshot.Max); Assert.Equal(13457.9, powSnapshot.Mean, 1); Assert.Equal(0.1, powSnapshot.Min); Assert.Equal(7, powSnapshot.Size); Assert.Equal(121121.1, powSnapshot.Sum); Assert.Equal( PowDict.SelectMany(entry => Enumerable.Repeat(entry.Key, entry.Value)), powSnapshot.Values ); Assert.Equal(100, powSnapshot.GetValue(0.5d)); // Test snapshot for the range histogram Assert.Equal(1000, rangeSnapshot.Count); Assert.Equal(1000, rangeSnapshot.Max); Assert.Equal(500.5, rangeSnapshot.Mean); Assert.Equal(1, rangeSnapshot.Min); Assert.Equal(288.6749902572095, rangeSnapshot.StdDev, 0); Assert.Equal(500500, rangeSnapshot.Sum); Assert.InRange(rangeSnapshot.GetValue(0.5d), 490.5, 510.5); Assert.InRange(rangeSnapshot.GetValue(0.75d), 745.5, 755.5); Assert.InRange(rangeSnapshot.GetValue(0.95d), 949, 952); Assert.InRange(rangeSnapshot.GetValue(0.98d), 980, 981); Assert.InRange(rangeSnapshot.GetValue(0.99d), 990, 991); Assert.InRange(rangeSnapshot.GetValue(0.999d), 999, 1000); // Test snapshot for multi-threaded histogram Assert.Equal(100, multiThreadedSnapshot.Count); Assert.Equal(28.86607004772212, multiThreadedSnapshot.StdDev, 0); Assert.Equal(5050, multiThreadedSnapshot.Sum); Assert.Equal(100, multiThreadedSnapshot.GetValue(0.999d), 1); // Test snapshot for empty histogram Assert.Equal(0, emptySnapshot.StdDev); }
private static WavefrontHistogramImpl CreateMultiThreadedHistogram(Func <long> clockMillis) { var wavefrontHistogram = new WavefrontHistogramImpl(clockMillis); // Update the histogram in parallel Parallel.For(1, 101, wavefrontHistogram.Update); return(wavefrontHistogram); }
private void WriteHistogram(string context, string name, IDictionary <string, object> data, MetricTags tags, DateTime timestamp) { // Report Wavefront Histograms using an API that is specific to Wavefront Histograms. if (WavefrontHistogramOptions.IsWavefrontHistogram(tags)) { name = Concat(context, name); // Wavefront Histograms are reported as a distribution, so we must extract the // distribution from a HistogramValue that is carrying it in a serialized format. string keyFieldName = fields.Histogram[HistogramFields.UserMaxValue]; string valueFieldName = fields.Histogram[HistogramFields.UserMinValue]; if (data.ContainsKey(keyFieldName) && data.ContainsKey(valueFieldName)) { string key = (string)data[keyFieldName]; string value = (string)data[valueFieldName]; // Deserialize the distributions into the right format for reporting. var distributions = WavefrontHistogramImpl.Deserialize( new KeyValuePair <string, string>(key, value)); foreach (var distribution in distributions) { wavefrontSender.SendDistribution( name, distribution.Centroids, histogramGranularities, distribution.Timestamp, source, FilterTags(tags) ); } } } else { foreach (var field in fields.Histogram) { // Do not report non-numerical metrics if (field.Key == HistogramFields.UserLastValue || field.Key == HistogramFields.UserMaxValue || field.Key == HistogramFields.UserMinValue) { continue; } if (data.ContainsKey(field.Value)) { WriteInternal(context, name, field.Value, data[field.Value], tags, timestamp); } } } }
private static WavefrontHistogramImpl CreateRangeHistogram(Func <long> clockMillis) { var wavefrontHistogram = new WavefrontHistogramImpl(clockMillis); for (int i = 1; i <= 1000; ++i) { wavefrontHistogram.Update(i); } return(wavefrontHistogram); }
private static WavefrontHistogramImpl CreatePowHistogram(Func <long> clockMillis) { var means = new List <double>(); var counts = new List <int>(); foreach (var entry in PowDict) { means.Add(entry.Key); counts.Add(entry.Value); } var wavefrontHistogram = new WavefrontHistogramImpl(clockMillis); wavefrontHistogram.BulkUpdate(means, counts); return(wavefrontHistogram); }
public void TestFlushDistributions() { var currentTime = DateTime.UtcNow; long clockMillis() => DateTimeUtils.UnixTimeMilliseconds(currentTime); var wavefrontHistogram = CreatePowHistogram(clockMillis); long minute0ClockMillis = clockMillis() / 60000 * 60000; // Test that nothing in the current minute bin gets flushed var distributions = wavefrontHistogram.FlushDistributions(); Assert.Equal(0, distributions.Count); // Test that prior minute bins get flushed currentTime = currentTime.AddMinutes(1); long minute1ClockMillis = clockMillis() / 60000 * 60000; wavefrontHistogram.Update(0.01); currentTime = currentTime.AddMinutes(1); distributions = wavefrontHistogram.FlushDistributions(); var actualDict = DistributionsToDictionary(distributions); var expectedDict = new Dictionary <long, Dictionary <double, int> > { { minute0ClockMillis, new Dictionary <double, int> { { 0.1, 1 }, { 1, 1 }, { 10, 2 }, { 100, 1 }, { 1000, 1 }, { 10000, 2 }, { 100000, 1 } } }, { minute1ClockMillis, new Dictionary <double, int> { { 0.01, 1 } } } }; Assert.Equal(expectedDict, actualDict); // Test serialization var serializedPair = WavefrontHistogramImpl.Serialize(distributions); string expectedTimestamps = distributions .Select(distribution => distribution.Timestamp.ToString()) .Aggregate((result, item) => result + ';' + item); string expectedCentroids = distributions .Select(distribution => distribution.Centroids .Select(centroid => centroid.Key.ToString() + ' ' + centroid.Value) .Aggregate((result, item) => result + ',' + item)) .Aggregate((result, item) => result + ';' + item); Assert.Equal(expectedTimestamps, serializedPair.Key); Assert.Equal(expectedCentroids, serializedPair.Value); // Test deserialization var deserializedDistributions = WavefrontHistogramImpl.Deserialize(serializedPair); Assert.Equal(actualDict, DistributionsToDictionary(deserializedDistributions)); // Test that prior minute bins get cleared distributions = wavefrontHistogram.FlushDistributions(); Assert.Equal(0, distributions.Count); }
/// <summary> /// Initializes a new instance of the <see cref="WavefrontHistogramReservoir"/> class. /// Backed by a <see cref="WavefrontHistogramImpl"/>. /// </summary> /// <param name="clockMillis"> /// A delegate function that simulates a clock for taking timestamps in milliseconds. /// </param> public WavefrontHistogramReservoir(Func <long> clockMillis) { wavefrontHistogram = new WavefrontHistogramImpl(clockMillis); }
/// <summary> /// Initializes a new instance of the <see cref="WavefrontHistogramReservoir"/> class. /// Backed by a <see cref="WavefrontHistogramImpl"/>. /// </summary> public WavefrontHistogramReservoir() { wavefrontHistogram = new WavefrontHistogramImpl(); }