docs
docs copied to clipboard
metrics-instrumentation missing discussion of RecordObservableInstruments for unit testing
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