Skip to content

Commit

Permalink
AppMetrics#637 add unit tests
Browse files Browse the repository at this point in the history
Add unit tests that check that desciption field is appeared in text formatted output
  • Loading branch information
aivanov-oneinc committed Feb 23, 2022
1 parent 2499c57 commit 254a748
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/Reporting/Reporting.sln
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetricsInfluxDB2SandboxMvc"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.InfluxDB2.Facts", "test\App.Metrics.Reporting.InfluxDB2.Facts\App.Metrics.Reporting.InfluxDB2.Facts.csproj", "{C4B12D2E-75D3-4800-B116-77851E4D1A2E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App.Metrics.Formatters.Prometheus.Facts", "test\App.Metrics.Formatters.Prometheus.Facts\App.Metrics.Formatters.Prometheus.Facts.csproj", "{5E6D167B-E6D1-4853-A54C-DD53CB3416EF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -316,6 +318,10 @@ Global
{C4B12D2E-75D3-4800-B116-77851E4D1A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4B12D2E-75D3-4800-B116-77851E4D1A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4B12D2E-75D3-4800-B116-77851E4D1A2E}.Release|Any CPU.Build.0 = Release|Any CPU
{5E6D167B-E6D1-4853-A54C-DD53CB3416EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E6D167B-E6D1-4853-A54C-DD53CB3416EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E6D167B-E6D1-4853-A54C-DD53CB3416EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E6D167B-E6D1-4853-A54C-DD53CB3416EF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -382,6 +388,7 @@ Global
{8B32FBD8-2F3F-40EF-A672-8E1E9E16148F} = {9D00C681-A88C-450E-B83E-E3BFF942F82A}
{74C314BC-394A-4A09-B739-03D4BE86DBB0} = {9D00C681-A88C-450E-B83E-E3BFF942F82A}
{C4B12D2E-75D3-4800-B116-77851E4D1A2E} = {3B064A0E-B6B6-41A3-BFC1-F4734E16EBA3}
{5E6D167B-E6D1-4853-A54C-DD53CB3416EF} = {DC95E9C9-286C-45D6-BE58-83E3F42DB96D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {492C97B1-706A-4357-B3F7-EFB6AFB1F6C6}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\App.Metrics.Formatters.Prometheus\App.Metrics.Formatters.Prometheus.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Globalization;

namespace App.Metrics.Formatters.Prometheus.Facts
{
sealed class TestClock : IClock
{
public event EventHandler Advanced;

public long Nanoseconds { get; private set; }

public long Seconds => TimeUnit.Nanoseconds.ToSeconds(Nanoseconds);

public DateTime UtcDateTime => new DateTime(Nanoseconds / 100L, DateTimeKind.Utc);

public void Advance(TimeUnit unit, long value)
{
Nanoseconds += unit.ToNanoseconds(value);
Advanced?.Invoke(this, EventArgs.Empty);
}

public string FormatTimestamp(DateTime timestamp) { return timestamp.ToString("yyyy-MM-ddTHH:mm:ss.ffffK", CultureInfo.InvariantCulture); }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using App.Metrics.Apdex;
using App.Metrics.BucketHistogram;
using App.Metrics.BucketTimer;
using App.Metrics.Counter;
using App.Metrics.Gauge;
using App.Metrics.Histogram;
using App.Metrics.Meter;
using App.Metrics.ReservoirSampling;
using App.Metrics.ReservoirSampling.ExponentialDecay;
using App.Metrics.Timer;
using FluentAssertions;
using Xunit;

namespace App.Metrics.Formatters.Prometheus.Facts
{
public class TestMetricsPrometheusTextOutputFormatter
{
private readonly IClock _clock = new TestClock();
private readonly IReservoir _defaultReservoir = new DefaultForwardDecayingReservoir();

private readonly MetricsPrometheusTextOutputFormatter _metricsPrometheusTextOutputFormatter =
new MetricsPrometheusTextOutputFormatter();

private readonly DateTime _timestamp = new DateTime(2017, 1, 1, 1, 1, 1, DateTimeKind.Utc);

[Fact]
public async Task Apdex_output_contains_description()
{
const string expected =
"# HELP test_apdex apdex description\n# TYPE test_apdex gauge\ntest_apdex 0\n\n";

var apdex = new DefaultApdexMetric(_defaultReservoir, _clock, false);
var apdexValueSource = new ApdexValueSource(
"apdex",
ConstantValue.Provider(apdex.Value),
MetricTags.Empty,
description: "apdex description");

var output = await GetFormatterOutput(CreateValueSource(apdexScores: apdexValueSource));
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Counter_output_contains_description()
{
const string expected =
"# HELP test_counter counter_description\n# TYPE test_counter gauge\ntest_counter 0\n\n";

var counter = new DefaultCounterMetric();
var counterValueSource = new CounterValueSource("counter", ConstantValue.Provider(counter.Value),
Unit.Calls,
MetricTags.Empty,
description: "counter_description");

var output = await GetFormatterOutput(CreateValueSource(counters: counterValueSource));
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Bucket_histogram_output_contains_description()
{
const string expected =
"# HELP test_bucket_histogram bucket histogram description\n# TYPE test_bucket_histogram histogram\ntest_bucket_histogram_sum 0\ntest_bucket_histogram_count 0\ntest_bucket_histogram_bucket{le=\"0.5\"} 0\ntest_bucket_histogram_bucket{le=\"+Inf\"} 0\n\n";
var bucketHistogram = new DefaultBucketHistogramMetric(new[] {0.5});
var bucketHistogramValueSource = new BucketHistogramValueSource("bucket_histogram",
ConstantValue.Provider(bucketHistogram.Value),
Unit.Calls,
MetricTags.Empty,
"bucket histogram description");
var metricsContextValueSource = CreateValueSource(bucketHistograms: bucketHistogramValueSource);

var output = await GetFormatterOutput(metricsContextValueSource);
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Bucket_timer_output_contains_description()
{
const string expected =
"# HELP test_bucket_timer bucket timer description\n# TYPE test_bucket_timer histogram\ntest_bucket_timer_sum 0\ntest_bucket_timer_count 0\ntest_bucket_timer_bucket{le=\"0.5\"} 0\ntest_bucket_timer_bucket{le=\"+Inf\"} 0\n\n";
var bucketHistogram = new DefaultBucketHistogramMetric(new[] {0.5});
var bucketTimer = new DefaultBucketTimerMetric(bucketHistogram,_clock,TimeUnit.Milliseconds);
var bucketTimerValueSource = new BucketTimerValueSource(
"bucket_timer",
ConstantValue.Provider(bucketTimer.Value),
Unit.Calls,
TimeUnit.Milliseconds,
TimeUnit.Milliseconds,
MetricTags.Empty,
"bucket timer description");
var metricsContextValueSource = CreateValueSource(bucketTimers: bucketTimerValueSource);

var output = await GetFormatterOutput(metricsContextValueSource);
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Gauge_output_contains_description()
{
const string expected =
"# HELP test_gauge gauge description\n# TYPE test_gauge gauge\ntest_gauge 1\n\n";
var gauge = new FunctionGauge(() => 1);
var gaugeValueSource = new GaugeValueSource(
"gauge",
ConstantValue.Provider(gauge.Value),
Unit.None,
MetricTags.Empty,
description: "gauge description");
var metricsContextValueSource = CreateValueSource(gauges: gaugeValueSource);

var output = await GetFormatterOutput(metricsContextValueSource);
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Histogram_output_contains_description()
{
const string expected =
"# HELP test_histogram histogram description\n# TYPE test_histogram summary\ntest_histogram_sum 0\ntest_histogram_count 0\ntest_histogram{quantile=\"0.5\"} 0\ntest_histogram{quantile=\"0.75\"} 0\ntest_histogram{quantile=\"0.95\"} 0\ntest_histogram{quantile=\"0.99\"} 0\n\n";
var histogram = new DefaultHistogramMetric(_defaultReservoir);
var histogramValueSource = new HistogramValueSource(
"histogram",
ConstantValue.Provider(histogram.Value),
Unit.None,
MetricTags.Empty,
description: "histogram description");

var metricsContextValueSource = CreateValueSource(histograms: histogramValueSource);

var output = await GetFormatterOutput(metricsContextValueSource);
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Meter_output_contains_description()
{
const string expected =
"# HELP test_meter_total meter description\n# TYPE test_meter_total counter\ntest_meter_total 0\n\n";
var clock = new TestClock();
var meter = new DefaultMeterMetric(clock);

var meterValueSource = new MeterValueSource(
"meter",
ConstantValue.Provider(meter.Value),
Unit.None,
TimeUnit.Milliseconds,
MetricTags.Empty,
description: "meter description");

var metricsContextValueSource = CreateValueSource(meters: meterValueSource);

var output = await GetFormatterOutput(metricsContextValueSource);
output.Should().BeEquivalentTo(expected);
}

[Fact]
public async Task Timer_output_contains_description()
{
const string expected =
"# HELP test_timer timer description\n# TYPE test_timer summary\ntest_timer_sum 0\ntest_timer_count 0\ntest_timer{quantile=\"0.5\"} 0\ntest_timer{quantile=\"0.75\"} 0\ntest_timer{quantile=\"0.95\"} 0\ntest_timer{quantile=\"0.99\"} 0\n\n";
var clock = new TestClock();
var timer = new DefaultTimerMetric(_defaultReservoir, clock);
var timerValueSource = new TimerValueSource(
"timer",
ConstantValue.Provider(timer.Value),
Unit.None,
TimeUnit.Milliseconds,
TimeUnit.Milliseconds,
MetricTags.Empty,
description: "timer description");

// Act
var metricsContextValueSource = CreateValueSource(timers: timerValueSource);

var output = await GetFormatterOutput(metricsContextValueSource);
output.Should().BeEquivalentTo(expected);
}

private async Task<string> GetFormatterOutput(MetricsContextValueSource metricsContextValueSource)
{
await using var stream = new MemoryStream();
await _metricsPrometheusTextOutputFormatter.WriteAsync(stream,
new MetricsDataValueSource(_timestamp,
new[] {metricsContextValueSource}));

var output = Encoding.UTF8.GetString(stream.ToArray());
return output;
}

private static MetricsContextValueSource CreateValueSource(
string context="test",
GaugeValueSource gauges = null,
CounterValueSource counters = null,
MeterValueSource meters = null,
HistogramValueSource histograms = null,
BucketHistogramValueSource bucketHistograms = null,
TimerValueSource timers = null,
BucketTimerValueSource bucketTimers = null,
ApdexValueSource apdexScores = null)
{
var gaugeValues = gauges != null ? new[] {gauges} : Enumerable.Empty<GaugeValueSource>();
var counterValues = counters != null ? new[] {counters} : Enumerable.Empty<CounterValueSource>();
var meterValues = meters != null ? new[] {meters} : Enumerable.Empty<MeterValueSource>();
var histogramValues = histograms != null ? new[] {histograms} : Enumerable.Empty<HistogramValueSource>();
var bucketHistogramValues = bucketHistograms != null
? new[] {bucketHistograms}
: Enumerable.Empty<BucketHistogramValueSource>();
var timerValues = timers != null ? new[] {timers} : Enumerable.Empty<TimerValueSource>();
var bucketTimerValues =
bucketTimers != null ? new[] {bucketTimers} : Enumerable.Empty<BucketTimerValueSource>();
var apdexScoreValues = apdexScores != null ? new[] {apdexScores} : Enumerable.Empty<ApdexValueSource>();

return new MetricsContextValueSource(
context,
gaugeValues,
counterValues,
meterValues,
histogramValues,
bucketHistogramValues,
timerValues,
bucketTimerValues,
apdexScoreValues);
}
}
}

0 comments on commit 254a748

Please sign in to comment.