docs icon indicating copy to clipboard operation
docs copied to clipboard

metrics-instrumentation missing discussion of RecordObservableInstruments for unit testing

Open rcollette opened this issue 1 year ago • 0 comments

Type of issue

Missing information

Description

This documentation makes no mention of the need to call MetricCollector.RecordObservableInstruments when unit testing something like an ObservableGauge. The documentation on this method is effectively missing as well. It took me most of the day to figure out how to test an ObservableGauge.

For those currently struggling, the following tests may offer a little more insight

public class DistributedLockTests
{
    private const string _lockId = "lockId";
    private readonly MetricCollector<double> _averageLockDurationGaugeCollector;
    private readonly DistributedLock _distributedLock;
    private readonly MetricCollector<double> _lockDurationHistogramCollector;
    private readonly FakeTimeProvider _timeProvider = new();

    public DistributedLockTests()
    {
        ServiceCollection serviceCollection = [];
        serviceCollection.AddMetrics();
        ServiceProvider provider = serviceCollection.BuildServiceProvider();
        IMeterFactory meterFactory = provider.GetService<IMeterFactory>() ??
                                     throw new InvalidOperationException("Could not provide meter factory.");
        _distributedLock = new DistributedLock(_lockId, meterFactory, _timeProvider);
        _lockDurationHistogramCollector = new MetricCollector<double>(
            _distributedLock.LockDurationMillisecondsHistogram,
            _timeProvider);
        _averageLockDurationGaugeCollector = new MetricCollector<double>(
            _distributedLock.AverageLockDurationMillisecondsGauge,
            _timeProvider);
    }

    [Fact]
    public async Task Release_WhenALockWasPreviouslyObtained_ComputesAverageLockTime()
    {
        // Arrange

        // Act
        await AcquireWaitAndReleaseLock(TimeSpan.FromMilliseconds(100));
        await AcquireWaitAndReleaseLock(TimeSpan.FromMilliseconds(200));

        // Assert
        _distributedLock.AverageLockDurationMilliseconds.Should().Be(150);
        IReadOnlyList<CollectedMeasurement<double>> lockDurations =
            _lockDurationHistogramCollector.GetMeasurementSnapshot();

        // There is no public constructor for CollectedMeasurement, so we can only test individual properties.
        ExpectMeasurement(lockDurations[0], 100.0, "2000-01-01T00:00:00.100Z");
        ExpectMeasurement(lockDurations[1], 200.0, "2000-01-01T00:00:00.300Z");
        _averageLockDurationGaugeCollector.RecordObservableInstruments();
        IReadOnlyList<CollectedMeasurement<double>> averageLockDurations =
            _averageLockDurationGaugeCollector.GetMeasurementSnapshot();
        averageLockDurations.Count.Should().Be(1);
        averageLockDurations[0].Value.Should().Be(150.0);
        averageLockDurations[0].Timestamp.Should().BeExactly(
            DateTimeOffset.Parse("2000-01-01T00:00:00.300Z", CultureInfo.InvariantCulture));
    }

    private async Task AcquireWaitAndReleaseLock(TimeSpan timeSpan)
    {
        await _distributedLock.WaitAsync();
        _distributedLock.RecordSharedLockAcquisitionTime();
        _timeProvider.Advance(timeSpan);
        _distributedLock.Release();
    }

    private static void ExpectMeasurement<T>(CollectedMeasurement<T> measurement, T value, string timestamp) where T : struct
    {
        measurement.Value.Should().Be(value);
        measurement.Timestamp.Should().BeExactly(DateTimeOffset.Parse(timestamp, CultureInfo.InvariantCulture));
    }
}

Page URL

https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-instrumentation

Content source URL

https://github.com/dotnet/docs/blob/main/docs/core/diagnostics/metrics-instrumentation.md

Document Version Independent Id

02ec1bf2-d0fe-dac5-b2c1-45d607430b06

Article author

@tommcdon

Metadata

  • ID: 61024acd-c2e8-291a-3007-7f09a1857690
  • Service: dotnet-fundamentals

rcollette avatar Jan 31 '24 20:01 rcollette