diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ITcpStateInfoProvider.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ITcpStateInfoProvider.cs
index 0c51e5fc45a..b62d8365d70 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ITcpStateInfoProvider.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ITcpStateInfoProvider.cs
@@ -12,11 +12,11 @@ internal interface ITcpStateInfoProvider
/// Gets the last known TCP/IP v4 state of the system.
///
/// An instance of .
- TcpStateInfo GetpIpV4TcpStateInfo();
+ TcpStateInfo GetIpV4TcpStateInfo();
///
/// Gets the last known TCP/IP v6 state of the system.
///
/// An instance of .
- TcpStateInfo GetpIpV6TcpStateInfo();
+ TcpStateInfo GetIpV6TcpStateInfo();
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs
index 11a6f72ccc8..660d5c4e7a1 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs
@@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
+using System.Linq;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Shared.Pools;
@@ -23,7 +24,7 @@ internal sealed class DiskStatsReader(IFileSystem fileSystem) : IDiskStatsReader
/// Reads and returns all disk statistics entries.
///
/// List of .
- public List ReadAll()
+ public DiskStats[] ReadAll(string[] skipDevicePrefixes)
{
var diskStatsList = new List();
@@ -41,7 +42,11 @@ public List ReadAll()
try
{
DiskStats stat = DiskStatsReader.ParseLine(line);
- diskStatsList.Add(stat);
+ if (!skipDevicePrefixes.Any(prefix =>
+ stat.DeviceName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+ {
+ diskStatsList.Add(stat);
+ }
}
#pragma warning disable CA1031
catch (Exception)
@@ -51,7 +56,7 @@ public List ReadAll()
}
}
- return diskStatsList;
+ return diskStatsList.ToArray();
}
///
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/IDiskStatsReader.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/IDiskStatsReader.cs
index df9d0d7c020..d4087731401 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/IDiskStatsReader.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/IDiskStatsReader.cs
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Collections.Generic;
-
namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Disk;
///
@@ -14,5 +12,5 @@ internal interface IDiskStatsReader
/// Gets all the disk statistics from the system.
///
/// List of instances.
- List ReadAll();
+ DiskStats[] ReadAll(string[] skipDevicePrefixes);
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/LinuxSystemDiskMetrics.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/LinuxSystemDiskMetrics.cs
index d70a65ed1b0..f967a1b7650 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/LinuxSystemDiskMetrics.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/LinuxSystemDiskMetrics.cs
@@ -2,10 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Frozen;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Metrics;
-using System.Linq;
+using System.IO;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
@@ -22,14 +23,22 @@ internal sealed class LinuxSystemDiskMetrics
private const string DeviceKey = "system.device";
private const string DirectionKey = "disk.io.direction";
+ // Exclude devices with these prefixes because they represent virtual, loopback, or device-mapper disks
+ // that do not correspond to real physical storage. Including them would distort system disk I/O metrics.
+ private static readonly string[] _skipDevicePrefixes = new[] { "ram", "loop", "dm-" };
private static readonly KeyValuePair _directionReadTag = new(DirectionKey, "read");
private static readonly KeyValuePair _directionWriteTag = new(DirectionKey, "write");
private readonly ILogger _logger;
private readonly TimeProvider _timeProvider;
private readonly IDiskStatsReader _diskStatsReader;
private readonly object _lock = new();
- private readonly Dictionary _baselineDiskStatsDict = [];
- private List _diskStatsSnapshot = [];
+ private readonly FrozenDictionary _baselineDiskStatsDict = FrozenDictionary.Empty;
+ private readonly TimeSpan _retryInterval = TimeSpan.FromMinutes(5);
+
+ private DateTimeOffset _lastDiskStatsFailure = DateTimeOffset.MinValue;
+ private bool _diskStatsUnavailable;
+
+ private DiskStats[] _diskStatsSnapshot = [];
private DateTimeOffset _lastRefreshTime = DateTimeOffset.MinValue;
public LinuxSystemDiskMetrics(
@@ -48,7 +57,7 @@ public LinuxSystemDiskMetrics(
}
// We need to read the disk stats once to get the baseline values
- _baselineDiskStatsDict = GetAllDiskStats().ToDictionary(d => d.DeviceName);
+ _baselineDiskStatsDict = GetAllDiskStats().ToFrozenDictionary(d => d.DeviceName);
#pragma warning disable CA2000 // Dispose objects before losing scope
// We don't dispose the meter because IMeterFactory handles that
@@ -85,7 +94,7 @@ public LinuxSystemDiskMetrics(
private IEnumerable> GetDiskIoMeasurements()
{
List> measurements = [];
- List diskStatsSnapshot = GetDiskStatsSnapshot();
+ DiskStats[] diskStatsSnapshot = GetDiskStatsSnapshot();
foreach (DiskStats diskStats in diskStatsSnapshot)
{
@@ -102,7 +111,7 @@ private IEnumerable> GetDiskIoMeasurements()
private IEnumerable> GetDiskOperationMeasurements()
{
List> measurements = [];
- List diskStatsSnapshot = GetDiskStatsSnapshot();
+ DiskStats[] diskStatsSnapshot = GetDiskStatsSnapshot();
foreach (DiskStats diskStats in diskStatsSnapshot)
{
@@ -119,7 +128,7 @@ private IEnumerable> GetDiskOperationMeasurements()
private IEnumerable> GetDiskIoTimeMeasurements()
{
List> measurements = [];
- List diskStatsSnapshot = GetDiskStatsSnapshot();
+ DiskStats[] diskStatsSnapshot = GetDiskStatsSnapshot();
foreach (DiskStats diskStats in diskStatsSnapshot)
{
@@ -131,12 +140,12 @@ private IEnumerable> GetDiskIoTimeMeasurements()
return measurements;
}
- private List GetDiskStatsSnapshot()
+ private DiskStats[] GetDiskStatsSnapshot()
{
lock (_lock)
{
DateTimeOffset now = _timeProvider.GetUtcNow();
- if (_diskStatsSnapshot.Count == 0 || (now - _lastRefreshTime).TotalSeconds > MinimumDiskStatsRefreshIntervalInSeconds)
+ if (_diskStatsSnapshot.Length == 0 || (now - _lastRefreshTime).TotalSeconds > MinimumDiskStatsRefreshIntervalInSeconds)
{
_diskStatsSnapshot = GetAllDiskStats();
_lastRefreshTime = now;
@@ -146,27 +155,37 @@ private List GetDiskStatsSnapshot()
return _diskStatsSnapshot;
}
- private List GetAllDiskStats()
+ private DiskStats[] GetAllDiskStats()
{
+ if (_diskStatsUnavailable &&
+ _timeProvider.GetUtcNow() - _lastDiskStatsFailure < _retryInterval)
+ {
+ return Array.Empty();
+ }
+
try
{
- List diskStatsList = _diskStatsReader.ReadAll();
-
- // We should not include ram, loop, or dm(device-mapper) devices in the disk stats, should we?
- diskStatsList = diskStatsList
- .Where(d => !d.DeviceName.StartsWith("ram", StringComparison.OrdinalIgnoreCase)
- && !d.DeviceName.StartsWith("loop", StringComparison.OrdinalIgnoreCase)
- && !d.DeviceName.StartsWith("dm-", StringComparison.OrdinalIgnoreCase))
- .ToList();
+ DiskStats[] diskStatsList = _diskStatsReader.ReadAll(_skipDevicePrefixes);
+ _diskStatsUnavailable = false;
+
return diskStatsList;
}
+ catch (Exception ex) when (
+ ex is FileNotFoundException ||
+ ex is DirectoryNotFoundException ||
+ ex is UnauthorizedAccessException)
+ {
+ _logger.HandleDiskStatsException(ex.Message);
+ _lastDiskStatsFailure = _timeProvider.GetUtcNow();
+ _diskStatsUnavailable = true;
+ }
#pragma warning disable CA1031
catch (Exception ex)
#pragma warning restore CA1031
{
- Log.HandleDiskStatsException(_logger, ex.Message);
+ _logger.HandleDiskStatsException(ex.Message);
}
- return [];
+ return Array.Empty();
}
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationProvider.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationProvider.cs
index c6dde5c0da1..4090bbb5619 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationProvider.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationProvider.cs
@@ -112,7 +112,7 @@ public LinuxUtilizationProvider(IOptions options, ILi
// _memoryLimit - Resource Memory Limit (in k8s terms)
// _memoryLimit - To keep the contract, this parameter will get the Host available memory
Resources = new SystemResources(cpuRequest, cpuLimit, _memoryLimit, _memoryLimit);
- Log.SystemResourcesInfo(_logger, cpuLimit, cpuRequest, _memoryLimit, _memoryLimit);
+ _logger.SystemResourcesInfo(cpuLimit, cpuRequest, _memoryLimit, _memoryLimit);
}
public double CpuUtilizationWithoutHostDelta()
@@ -144,7 +144,7 @@ public double CpuUtilizationWithoutHostDelta()
{
coresUsed = deltaCgroup / (double)deltaCpuPeriodInNanoseconds;
- Log.CpuUsageDataV2(_logger, cpuUsageTime, _previousCgroupCpuTime, deltaCpuPeriodInNanoseconds, coresUsed);
+ _logger.CpuUsageDataV2(cpuUsageTime, _previousCgroupCpuTime, deltaCpuPeriodInNanoseconds, coresUsed);
_lastCpuCoresUsed = coresUsed;
_refreshAfterCpu = now.Add(_cpuRefreshInterval);
@@ -158,7 +158,7 @@ public double CpuUtilizationWithoutHostDelta()
{
coresUsed = deltaCgroup / actualElapsedNanoseconds;
- Log.CpuUsageDataV2(_logger, cpuUsageTime, _previousCgroupCpuTime, actualElapsedNanoseconds, coresUsed);
+ _logger.CpuUsageDataV2(cpuUsageTime, _previousCgroupCpuTime, actualElapsedNanoseconds, coresUsed);
_lastCpuCoresUsed = coresUsed;
_refreshAfterCpu = now.Add(_cpuRefreshInterval);
@@ -188,7 +188,7 @@ public double CpuUtilizationLimit(float cpuLimit)
{
_cpuUtilizationLimit100PercentExceededCounter?.Add(1);
_cpuUtilizationLimit100PercentExceeded++;
- Log.CounterMessage100(_logger, _cpuUtilizationLimit100PercentExceeded);
+ _logger.CounterMessage100(_cpuUtilizationLimit100PercentExceeded);
}
// Increment counter if utilization exceeds 110%
@@ -196,7 +196,7 @@ public double CpuUtilizationLimit(float cpuLimit)
{
_cpuUtilizationLimit110PercentExceededCounter?.Add(1);
_cpuUtilizationLimit110PercentExceeded++;
- Log.CounterMessage110(_logger, _cpuUtilizationLimit110PercentExceeded);
+ _logger.CounterMessage110(_cpuUtilizationLimit110PercentExceeded);
}
return utilization;
@@ -228,7 +228,7 @@ public double CpuUtilization()
{
double percentage = Math.Min(One, (double)deltaCgroup / deltaHost);
- Log.CpuUsageData(_logger, cgroupCpuTime, hostCpuTime, _previousCgroupCpuTime, _previousHostCpuTime, percentage);
+ _logger.CpuUsageData(cgroupCpuTime, hostCpuTime, _previousCgroupCpuTime, _previousHostCpuTime, percentage);
_cpuPercentage = percentage;
_refreshAfterCpu = now.Add(_cpuRefreshInterval);
@@ -266,7 +266,7 @@ public double MemoryUtilization()
}
}
- Log.MemoryUsageData(_logger, memoryUsed, _memoryLimit, _memoryPercentage);
+ _logger.MemoryUsageData(memoryUsed, _memoryLimit, _memoryPercentage);
return _memoryPercentage;
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Log.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Log.cs
index d2f9c8f5070..b78f64ddfe0 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Log.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Log.cs
@@ -15,7 +15,7 @@ internal static partial class Log
"Computed CPU usage with CgroupCpuTime = {cgroupCpuTime}, HostCpuTime = {hostCpuTime}, PreviousCgroupCpuTime = {previousCgroupCpuTime}, PreviousHostCpuTime = {previousHostCpuTime}, CpuPercentage = {cpuPercentage}.")]
#pragma warning restore S103 // Lines should not be too long
public static partial void CpuUsageData(
- ILogger logger,
+ this ILogger logger,
long cgroupCpuTime,
long hostCpuTime,
long previousCgroupCpuTime,
@@ -25,21 +25,26 @@ public static partial void CpuUsageData(
[LoggerMessage(2, LogLevel.Debug,
"Computed memory usage with MemoryUsedInBytes = {memoryUsed}, MemoryLimit = {memoryLimit}, MemoryPercentage = {memoryPercentage}.")]
public static partial void MemoryUsageData(
- ILogger logger,
+ this ILogger logger,
ulong memoryUsed,
double memoryLimit,
double memoryPercentage);
[LoggerMessage(3, LogLevel.Debug,
"System resources information: CpuLimit = {cpuLimit}, CpuRequest = {cpuRequest}, MemoryLimit = {memoryLimit}, MemoryRequest = {memoryRequest}.")]
- public static partial void SystemResourcesInfo(ILogger logger, double cpuLimit, double cpuRequest, ulong memoryLimit, ulong memoryRequest);
+ public static partial void SystemResourcesInfo(
+ this ILogger logger,
+ double cpuLimit,
+ double cpuRequest,
+ ulong memoryLimit,
+ ulong memoryRequest);
[LoggerMessage(4, LogLevel.Debug,
#pragma warning disable S103 // Lines should not be too long
"For CgroupV2, Computed CPU usage with CgroupCpuTime = {cgroupCpuTime}, PreviousCgroupCpuTime = {previousCgroupCpuTime}, ActualElapsedNanoseconds = {actualElapsedNanoseconds}, CpuCores = {cpuCores}.")]
#pragma warning restore S103 // Lines should not be too long
public static partial void CpuUsageDataV2(
- ILogger logger,
+ this ILogger logger,
long cgroupCpuTime,
long previousCgroupCpuTime,
double actualElapsedNanoseconds,
@@ -48,16 +53,18 @@ public static partial void CpuUsageDataV2(
[LoggerMessage(5, LogLevel.Debug,
"CPU utilization exceeded 100%: Counter = {counterValue}")]
public static partial void CounterMessage100(
- ILogger logger,
+ this ILogger logger,
long counterValue);
[LoggerMessage(6, LogLevel.Debug,
"CPU utilization exceeded 110%: Counter = {counterValue}")]
public static partial void CounterMessage110(
- ILogger logger,
+ this ILogger logger,
long counterValue);
[LoggerMessage(7, LogLevel.Warning,
"Error while getting disk stats: Error={errorMessage}")]
- public static partial void HandleDiskStatsException(ILogger logger, string errorMessage);
+ public static partial void HandleDiskStatsException(
+ this ILogger logger,
+ string errorMessage);
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxNetworkMetrics.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxNetworkMetrics.cs
index a7e0c6b2303..5add8ccfe75 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxNetworkMetrics.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxNetworkMetrics.cs
@@ -1,9 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Metrics;
+using System.IO;
+using System.Threading;
using Microsoft.Shared.Instruments;
namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Network;
@@ -11,10 +14,18 @@ namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Network;
internal sealed class LinuxNetworkMetrics
{
private readonly ITcpStateInfoProvider _tcpStateInfoProvider;
+ private readonly TimeProvider _timeProvider;
- public LinuxNetworkMetrics(IMeterFactory meterFactory, ITcpStateInfoProvider tcpStateInfoProvider)
+ private readonly TimeSpan _retryInterval = TimeSpan.FromMinutes(5);
+ private DateTimeOffset _lastV4Failure = DateTimeOffset.MinValue;
+ private DateTimeOffset _lastV6Failure = DateTimeOffset.MinValue;
+ private int _v4Unavailable;
+ private int _v6Unavailable;
+
+ public LinuxNetworkMetrics(IMeterFactory meterFactory, ITcpStateInfoProvider tcpStateInfoProvider, TimeProvider timeProvider)
{
_tcpStateInfoProvider = tcpStateInfoProvider;
+ _timeProvider = timeProvider;
#pragma warning disable CA2000 // Dispose objects before losing scope
// We don't dispose the meter because IMeterFactory handles that
@@ -36,10 +47,9 @@ public LinuxNetworkMetrics(IMeterFactory meterFactory, ITcpStateInfoProvider tcp
tags: commonTags);
}
- private IEnumerable> GetMeasurements()
+ public IEnumerable> GetMeasurements()
{
const string NetworkTypeKey = "network.type";
- const string NetworkStateKey = "system.network.state";
// These are covered in https://github.com/open-telemetry/semantic-conventions/blob/main/docs/rpc/rpc-metrics.md#attributes:
KeyValuePair tcpVersionFourTag = new(NetworkTypeKey, "ipv4");
@@ -48,33 +58,59 @@ private IEnumerable> GetMeasurements()
List> measurements = new(24);
// IPv4:
- TcpStateInfo stateV4 = _tcpStateInfoProvider.GetpIpV4TcpStateInfo();
- measurements.Add(new Measurement(stateV4.ClosedCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "close") }));
- measurements.Add(new Measurement(stateV4.ListenCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "listen") }));
- measurements.Add(new Measurement(stateV4.SynSentCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "syn_sent") }));
- measurements.Add(new Measurement(stateV4.SynRcvdCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "syn_recv") }));
- measurements.Add(new Measurement(stateV4.EstabCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "established") }));
- measurements.Add(new Measurement(stateV4.FinWait1Count, new TagList { tcpVersionFourTag, new(NetworkStateKey, "fin_wait_1") }));
- measurements.Add(new Measurement(stateV4.FinWait2Count, new TagList { tcpVersionFourTag, new(NetworkStateKey, "fin_wait_2") }));
- measurements.Add(new Measurement(stateV4.CloseWaitCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "close_wait") }));
- measurements.Add(new Measurement(stateV4.ClosingCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "closing") }));
- measurements.Add(new Measurement(stateV4.LastAckCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "last_ack") }));
- measurements.Add(new Measurement(stateV4.TimeWaitCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "time_wait") }));
+ TcpStateInfo stateV4 = GetTcpStateInfoWithRetry(_tcpStateInfoProvider.GetIpV4TcpStateInfo, ref _v4Unavailable, ref _lastV4Failure);
+ CreateMeasurements(tcpVersionFourTag, measurements, stateV4);
// IPv6:
- TcpStateInfo stateV6 = _tcpStateInfoProvider.GetpIpV6TcpStateInfo();
- measurements.Add(new Measurement(stateV6.ClosedCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "close") }));
- measurements.Add(new Measurement(stateV6.ListenCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "listen") }));
- measurements.Add(new Measurement(stateV6.SynSentCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "syn_sent") }));
- measurements.Add(new Measurement(stateV6.SynRcvdCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "syn_recv") }));
- measurements.Add(new Measurement(stateV6.EstabCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "established") }));
- measurements.Add(new Measurement(stateV6.FinWait1Count, new TagList { tcpVersionSixTag, new(NetworkStateKey, "fin_wait_1") }));
- measurements.Add(new Measurement(stateV6.FinWait2Count, new TagList { tcpVersionSixTag, new(NetworkStateKey, "fin_wait_2") }));
- measurements.Add(new Measurement(stateV6.CloseWaitCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "close_wait") }));
- measurements.Add(new Measurement(stateV6.ClosingCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "closing") }));
- measurements.Add(new Measurement(stateV6.LastAckCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "last_ack") }));
- measurements.Add(new Measurement(stateV6.TimeWaitCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "time_wait") }));
+ TcpStateInfo stateV6 = GetTcpStateInfoWithRetry(_tcpStateInfoProvider.GetIpV6TcpStateInfo, ref _v6Unavailable, ref _lastV6Failure);
+ CreateMeasurements(tcpVersionSixTag, measurements, stateV6);
return measurements;
}
+
+ private static void CreateMeasurements(KeyValuePair tcpVersionTag, List> measurements, TcpStateInfo state)
+ {
+ const string NetworkStateKey = "system.network.state";
+
+ measurements.Add(new Measurement(state.ClosedCount, new TagList { tcpVersionTag, new(NetworkStateKey, "close") }));
+ measurements.Add(new Measurement(state.ListenCount, new TagList { tcpVersionTag, new(NetworkStateKey, "listen") }));
+ measurements.Add(new Measurement(state.SynSentCount, new TagList { tcpVersionTag, new(NetworkStateKey, "syn_sent") }));
+ measurements.Add(new Measurement(state.SynRcvdCount, new TagList { tcpVersionTag, new(NetworkStateKey, "syn_recv") }));
+ measurements.Add(new Measurement(state.EstabCount, new TagList { tcpVersionTag, new(NetworkStateKey, "established") }));
+ measurements.Add(new Measurement(state.FinWait1Count, new TagList { tcpVersionTag, new(NetworkStateKey, "fin_wait_1") }));
+ measurements.Add(new Measurement(state.FinWait2Count, new TagList { tcpVersionTag, new(NetworkStateKey, "fin_wait_2") }));
+ measurements.Add(new Measurement(state.CloseWaitCount, new TagList { tcpVersionTag, new(NetworkStateKey, "close_wait") }));
+ measurements.Add(new Measurement(state.ClosingCount, new TagList { tcpVersionTag, new(NetworkStateKey, "closing") }));
+ measurements.Add(new Measurement(state.LastAckCount, new TagList { tcpVersionTag, new(NetworkStateKey, "last_ack") }));
+ measurements.Add(new Measurement(state.TimeWaitCount, new TagList { tcpVersionTag, new(NetworkStateKey, "time_wait") }));
+ }
+
+ private TcpStateInfo GetTcpStateInfoWithRetry(
+ Func getStateInfoFunc,
+ ref int unavailableFlag,
+ ref DateTimeOffset lastFailureTime)
+ {
+ if (Volatile.Read(ref unavailableFlag) == 0 || _timeProvider.GetUtcNow() - lastFailureTime > _retryInterval)
+ {
+ try
+ {
+ TcpStateInfo state = getStateInfoFunc();
+ _ = Interlocked.Exchange(ref unavailableFlag, 0);
+ return state;
+ }
+ catch (Exception ex) when (
+ ex is FileNotFoundException ||
+ ex is DirectoryNotFoundException ||
+ ex is UnauthorizedAccessException)
+ {
+ lastFailureTime = _timeProvider.GetUtcNow();
+ _ = Interlocked.Exchange(ref unavailableFlag, 1);
+ return new TcpStateInfo();
+ }
+ }
+ else
+ {
+ return new TcpStateInfo();
+ }
+ }
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxTcpStateInfo.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxTcpStateInfo.cs
index 390bcda64ea..66bc3e1501e 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxTcpStateInfo.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Network/LinuxTcpStateInfo.cs
@@ -23,13 +23,13 @@ public LinuxTcpStateInfo(IOptions options, LinuxNetwo
_parser = parser;
}
- public TcpStateInfo GetpIpV4TcpStateInfo()
+ public TcpStateInfo GetIpV4TcpStateInfo()
{
RefreshSnapshotIfNeeded();
return _iPv4Snapshot;
}
- public TcpStateInfo GetpIpV6TcpStateInfo()
+ public TcpStateInfo GetIpV6TcpStateInfo()
{
RefreshSnapshotIfNeeded();
return _iPv6Snapshot;
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Log.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Log.cs
index a300450a37d..f1d2b620a71 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Log.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Log.cs
@@ -12,15 +12,20 @@ namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring;
internal static partial class Log
{
[LoggerMessage(1, LogLevel.Error, "Unable to gather utilization statistics.")]
- public static partial void HandledGatherStatisticsException(ILogger logger, Exception e);
+ public static partial void HandledGatherStatisticsException(
+ this ILogger logger,
+ Exception e);
[LoggerMessage(2, LogLevel.Error, "Publisher `{Publisher}` was unable to publish utilization statistics.")]
- public static partial void HandlePublishUtilizationException(ILogger logger, Exception e, string publisher);
+ public static partial void HandlePublishUtilizationException(
+ this ILogger logger,
+ Exception e,
+ string publisher);
[LoggerMessage(3, LogLevel.Debug,
"Snapshot received: TotalTimeSinceStart={totalTimeSinceStart}, KernelTimeSinceStart={kernelTimeSinceStart}, UserTimeSinceStart={userTimeSinceStart}, MemoryUsageInBytes={memoryUsageInBytes}.")]
public static partial void SnapshotReceived(
- ILogger logger,
+ this ILogger logger,
TimeSpan totalTimeSinceStart,
TimeSpan kernelTimeSinceStart,
TimeSpan userTimeSinceStart,
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitorService.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitorService.cs
index d856cedb5ec..ab77a5dfed9 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitorService.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/ResourceMonitorService.cs
@@ -115,7 +115,7 @@ internal async Task PublishUtilizationAsync(CancellationToken cancellationToken)
{
// By Design: Swallow the exception, as they're non-actionable in this code path.
// Prioritize app reliability over error visibility
- Log.HandlePublishUtilizationException(_logger, e, publisher.GetType().FullName!);
+ _logger.HandlePublishUtilizationException(e, publisher.GetType().FullName!);
}
}
}
@@ -133,13 +133,13 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken)
var snapshot = _provider.GetSnapshot();
_snapshotsStore.Add(snapshot);
- Log.SnapshotReceived(_logger, snapshot.TotalTimeSinceStart, snapshot.KernelTimeSinceStart, snapshot.UserTimeSinceStart, snapshot.MemoryUsageInBytes);
+ _logger.SnapshotReceived(snapshot.TotalTimeSinceStart, snapshot.KernelTimeSinceStart, snapshot.UserTimeSinceStart, snapshot.MemoryUsageInBytes);
}
catch (Exception e)
{
// By Design: Swallow the exception, as they're non-actionable in this code path.
// Prioritize app reliability over error visibility
- Log.HandledGatherStatisticsException(_logger, e);
+ _logger.HandledGatherStatisticsException(e);
}
await PublishUtilizationAsync(cancellationToken).ConfigureAwait(false);
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Disk/WindowsDiskMetrics.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Disk/WindowsDiskMetrics.cs
index 2927fa657e3..fc6250e80ba 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Disk/WindowsDiskMetrics.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Disk/WindowsDiskMetrics.cs
@@ -99,7 +99,7 @@ private void InitializeDiskCounters(IPerformanceCounterFactory performanceCounte
}
catch (Exception ex)
{
- Log.DiskIoPerfCounterException(_logger, WindowsDiskPerfCounterNames.DiskIdleTimeCounter, ex.Message);
+ _logger.DiskIoPerfCounterException(WindowsDiskPerfCounterNames.DiskIdleTimeCounter, ex.Message);
}
// Initialize disk performance counters for "system.disk.io" and "system.disk.operations" metrics
@@ -125,7 +125,7 @@ private void InitializeDiskCounters(IPerformanceCounterFactory performanceCounte
}
catch (Exception ex)
{
- Log.DiskIoPerfCounterException(_logger, counterName, ex.Message);
+ _logger.DiskIoPerfCounterException(counterName, ex.Message);
}
}
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Log.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Log.cs
index 3d23f87dff9..fdc0d17fe44 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Log.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Log.cs
@@ -10,14 +10,15 @@ namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Windows;
internal static partial class Log
{
[LoggerMessage(1, LogLevel.Information, "Resource Monitoring is running inside a Job Object. For more information about Job Objects see https://aka.ms/job-objects")]
- public static partial void RunningInsideJobObject(ILogger logger);
+ public static partial void RunningInsideJobObject(this ILogger logger);
[LoggerMessage(2, LogLevel.Information, "Resource Monitoring is running outside of Job Object. For more information about Job Objects see https://aka.ms/job-objects")]
- public static partial void RunningOutsideJobObject(ILogger logger);
+ public static partial void RunningOutsideJobObject(this ILogger logger);
[LoggerMessage(3, LogLevel.Debug,
"Computed CPU usage with CpuUsageTicks = {cpuUsageTicks}, OldCpuUsageTicks = {oldCpuUsageTicks}, TimeTickDelta = {timeTickDelta}, CpuUnits = {cpuUnits}, CpuPercentage = {cpuPercentage}.")]
- public static partial void CpuUsageData(ILogger logger,
+ public static partial void CpuUsageData(
+ this ILogger logger,
long cpuUsageTicks,
long oldCpuUsageTicks,
double timeTickDelta,
@@ -26,7 +27,8 @@ public static partial void CpuUsageData(ILogger logger,
[LoggerMessage(4, LogLevel.Debug,
"Computed memory usage with CurrentMemoryUsage = {currentMemoryUsage}, TotalMemory = {totalMemory}, MemoryPercentage = {memoryPercentage}.")]
- public static partial void MemoryUsageData(ILogger logger,
+ public static partial void MemoryUsageData(
+ this ILogger logger,
ulong currentMemoryUsage,
double totalMemory,
double memoryPercentage);
@@ -34,7 +36,8 @@ public static partial void MemoryUsageData(ILogger logger,
#pragma warning disable S103 // Lines should not be too long
[LoggerMessage(5, LogLevel.Debug, "Computed CPU usage with CpuUsageKernelTicks = {cpuUsageKernelTicks}, CpuUsageUserTicks = {cpuUsageUserTicks}, OldCpuUsageTicks = {oldCpuUsageTicks}, TimeTickDelta = {timeTickDelta}, CpuUnits = {cpuUnits}, CpuPercentage = {cpuPercentage}.")]
#pragma warning restore S103 // Lines should not be too long
- public static partial void CpuContainerUsageData(ILogger logger,
+ public static partial void CpuContainerUsageData(
+ this ILogger logger,
long cpuUsageKernelTicks,
long cpuUsageUserTicks,
long oldCpuUsageTicks,
@@ -44,9 +47,17 @@ public static partial void CpuContainerUsageData(ILogger logger,
[LoggerMessage(6, LogLevel.Debug,
"System resources information: CpuLimit = {cpuLimit}, CpuRequest = {cpuRequest}, MemoryLimit = {memoryLimit}, MemoryRequest = {memoryRequest}.")]
- public static partial void SystemResourcesInfo(ILogger logger, double cpuLimit, double cpuRequest, ulong memoryLimit, ulong memoryRequest);
+ public static partial void SystemResourcesInfo(
+ this ILogger logger,
+ double cpuLimit,
+ double cpuRequest,
+ ulong memoryLimit,
+ ulong memoryRequest);
[LoggerMessage(7, LogLevel.Warning,
"Error initializing disk io perf counter: PerfCounter={counterName}, Error={errorMessage}")]
- public static partial void DiskIoPerfCounterException(ILogger logger, string counterName, string errorMessage);
+ public static partial void DiskIoPerfCounterException(
+ this ILogger logger,
+ string counterName,
+ string errorMessage);
}
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsNetworkMetrics.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsNetworkMetrics.cs
index 1acc8d02edd..be3b4e6983f 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsNetworkMetrics.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsNetworkMetrics.cs
@@ -48,7 +48,7 @@ private IEnumerable> GetMeasurements()
List> measurements = new(24);
// IPv4:
- TcpStateInfo stateV4 = _tcpStateInfoProvider.GetpIpV4TcpStateInfo();
+ TcpStateInfo stateV4 = _tcpStateInfoProvider.GetIpV4TcpStateInfo();
measurements.Add(new Measurement(stateV4.ClosedCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "close") }));
measurements.Add(new Measurement(stateV4.ListenCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "listen") }));
measurements.Add(new Measurement(stateV4.SynSentCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "syn_sent") }));
@@ -63,7 +63,7 @@ private IEnumerable> GetMeasurements()
measurements.Add(new Measurement(stateV4.DeleteTcbCount, new TagList { tcpVersionFourTag, new(NetworkStateKey, "delete") }));
// IPv6:
- TcpStateInfo stateV6 = _tcpStateInfoProvider.GetpIpV6TcpStateInfo();
+ TcpStateInfo stateV6 = _tcpStateInfoProvider.GetIpV6TcpStateInfo();
measurements.Add(new Measurement(stateV6.ClosedCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "close") }));
measurements.Add(new Measurement(stateV6.ListenCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "listen") }));
measurements.Add(new Measurement(stateV6.SynSentCount, new TagList { tcpVersionSixTag, new(NetworkStateKey, "syn_sent") }));
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsTcpStateInfo.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsTcpStateInfo.cs
index 732c522cda5..cc0310fd4c8 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsTcpStateInfo.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/Network/WindowsTcpStateInfo.cs
@@ -42,13 +42,13 @@ public WindowsTcpStateInfo(IOptions options)
_refreshAfter = default;
}
- public TcpStateInfo GetpIpV4TcpStateInfo()
+ public TcpStateInfo GetIpV4TcpStateInfo()
{
RefreshSnapshotIfNeeded();
return _iPv4Snapshot;
}
- public TcpStateInfo GetpIpV6TcpStateInfo()
+ public TcpStateInfo GetIpV6TcpStateInfo()
{
RefreshSnapshotIfNeeded();
return _iPv6Snapshot;
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsContainerSnapshotProvider.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsContainerSnapshotProvider.cs
index 56d8bc2e578..27156ea874e 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsContainerSnapshotProvider.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsContainerSnapshotProvider.cs
@@ -73,7 +73,7 @@ internal WindowsContainerSnapshotProvider(
ResourceMonitoringOptions options)
{
_logger = logger ?? NullLogger.Instance;
- Log.RunningInsideJobObject(_logger);
+ _logger.RunningInsideJobObject();
_metricValueMultiplier = options.UseZeroToOneRangeForMetrics ? One : Hundred;
@@ -96,7 +96,7 @@ internal WindowsContainerSnapshotProvider(
var cpuRequest = _cpuLimit;
var memoryRequest = memoryLimitLong;
Resources = new SystemResources(cpuRequest, _cpuLimit, memoryRequest, memoryLimitLong);
- Log.SystemResourcesInfo(_logger, _cpuLimit, cpuRequest, memoryLimitLong, memoryRequest);
+ _logger.SystemResourcesInfo(_cpuLimit, cpuRequest, memoryLimitLong, memoryRequest);
var basicAccountingInfo = jobHandle.GetBasicAccountingInfo();
_oldCpuUsageTicks = basicAccountingInfo.TotalKernelTime + basicAccountingInfo.TotalUserTime;
@@ -205,7 +205,7 @@ private double MemoryPercentage(Func getMemoryUsage)
_refreshAfterMemory = now.Add(_memoryRefreshInterval);
}
- Log.MemoryUsageData(_logger, memoryUsage, _memoryLimit, _memoryPercentage);
+ _logger.MemoryUsageData(memoryUsage, _memoryLimit, _memoryPercentage);
return _memoryPercentage;
}
@@ -238,8 +238,8 @@ private double CpuPercentage()
// Don't change calculation order, otherwise precision is lost:
_cpuPercentage = Math.Min(_metricValueMultiplier, usageTickDelta / timeTickDelta * _metricValueMultiplier);
- Log.CpuContainerUsageData(
- _logger, basicAccountingInfo.TotalKernelTime, basicAccountingInfo.TotalUserTime, _oldCpuUsageTicks, timeTickDelta, _cpuLimit, _cpuPercentage);
+ _logger.CpuContainerUsageData(
+ basicAccountingInfo.TotalKernelTime, basicAccountingInfo.TotalUserTime, _oldCpuUsageTicks, timeTickDelta, _cpuLimit, _cpuPercentage);
_oldCpuUsageTicks = currentCpuTicks;
_oldCpuTimeTicks = now.Ticks;
diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsSnapshotProvider.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsSnapshotProvider.cs
index 3a20412424c..837cd0f9a06 100644
--- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsSnapshotProvider.cs
+++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Windows/WindowsSnapshotProvider.cs
@@ -57,7 +57,7 @@ internal WindowsSnapshotProvider(
{
_logger = logger ?? NullLogger.Instance;
- Log.RunningOutsideJobObject(_logger);
+ _logger.RunningOutsideJobObject();
_metricValueMultiplier = options.UseZeroToOneRangeForMetrics ? One : Hundred;
@@ -68,7 +68,7 @@ internal WindowsSnapshotProvider(
// any resource requests or resource limits, therefore using physical values
// such as number of CPUs and physical memory and using it for both requests and limits (aka 'guaranteed' and 'max'):
Resources = new SystemResources(_cpuUnits, _cpuUnits, totalMemory, totalMemory);
- Log.SystemResourcesInfo(_logger, _cpuUnits, _cpuUnits, totalMemory, totalMemory);
+ _logger.SystemResourcesInfo(_cpuUnits, _cpuUnits, totalMemory, totalMemory);
_timeProvider = timeProvider;
_getCpuTicksFunc = getCpuTicksFunc;
@@ -144,7 +144,7 @@ private double MemoryPercentage()
_refreshAfterMemory = now.Add(_memoryRefreshInterval);
}
- Log.MemoryUsageData(_logger, (ulong)currentMemoryUsage, _totalMemory, _memoryPercentage);
+ _logger.MemoryUsageData((ulong)currentMemoryUsage, _totalMemory, _memoryPercentage);
return _memoryPercentage;
}
@@ -175,7 +175,7 @@ private double CpuPercentage()
// Don't change calculation order, otherwise we loose some precision:
_cpuPercentage = Math.Min(_metricValueMultiplier, usageTickDelta / (double)timeTickDelta * _metricValueMultiplier);
- Log.CpuUsageData(_logger, currentCpuTicks, _oldCpuUsageTicks, timeTickDelta, _cpuUnits, _cpuPercentage);
+ _logger.CpuUsageData(currentCpuTicks, _oldCpuUsageTicks, timeTickDelta, _cpuUnits, _cpuPercentage);
_oldCpuUsageTicks = currentCpuTicks;
_oldCpuTimeTicks = now.Ticks;
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/DiskStatsReaderTests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/DiskStatsReaderTests.cs
index c5098b2d284..1f7738bb030 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/DiskStatsReaderTests.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/DiskStatsReaderTests.cs
@@ -13,6 +13,8 @@ namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Disk.Test;
[OSSkipCondition(OperatingSystems.Windows | OperatingSystems.MacOSX, SkipReason = "Linux specific tests")]
public class DiskStatsReaderTests
{
+ private static readonly string[] _skipDevicePrefixes = new[] { "ram", "loop", "dm-" };
+
[Fact]
public void Test_ReadAll_Valid_DiskStats()
{
@@ -39,8 +41,17 @@ public void Test_ReadAll_Valid_DiskStats()
});
var reader = new DiskStatsReader(fileSystem);
- var dictionary = reader.ReadAll().ToDictionary(x => x.DeviceName);
- Assert.Equal(15, dictionary.Count);
+ var dictionary = reader.ReadAll(_skipDevicePrefixes).ToDictionary(x => x.DeviceName);
+
+ var expectedDevices = new[]
+ {
+ "nvme1n1", "nvme1n1p1", "nvme0n1", "nvme0n1p1", "nvme0n1p2", "nvme0n1p3", "sda"
+ };
+ Assert.Equal(expectedDevices.Length, dictionary.Count);
+ foreach (var device in expectedDevices)
+ {
+ Assert.True(dictionary.ContainsKey(device), $"Expected device {device} to be present.");
+ }
var disk1 = dictionary["nvme0n1"];
Assert.Equal(6_090_587u, disk1.ReadsCompleted);
@@ -61,31 +72,18 @@ public void Test_ReadAll_Valid_DiskStats()
Assert.Equal(1_659_742u, disk1.FlushRequestsCompleted);
Assert.Equal(515_787u, disk1.TimeFlushingMs);
- var disk2 = dictionary["dm-8"];
- Assert.Equal(100_601u, disk2.ReadsCompleted);
+ var disk2 = dictionary["sda"];
+ Assert.Equal(0u, disk2.ReadsCompleted);
Assert.Equal(0u, disk2.ReadsMerged);
- Assert.Equal(2_990_980u, disk2.SectorsRead);
- Assert.Equal(23_940u, disk2.TimeReadingMs);
- Assert.Equal(3_097_278u, disk2.WritesCompleted);
+ Assert.Equal(0u, disk2.SectorsRead);
+ Assert.Equal(0u, disk2.TimeReadingMs);
+ Assert.Equal(0u, disk2.WritesCompleted);
Assert.Equal(0u, disk2.WritesMerged);
- Assert.Equal(32_037_680u, disk2.SectorsWritten);
- Assert.Equal(1_410_540u, disk2.TimeWritingMs);
+ Assert.Equal(0u, disk2.SectorsWritten);
+ Assert.Equal(0u, disk2.TimeWritingMs);
Assert.Equal(0u, disk2.IoInProgress);
- Assert.Equal(5_488_608u, disk2.TimeIoMs);
- Assert.Equal(1_434_496u, disk2.WeightedTimeIoMs);
-
- var disk3 = dictionary["sda"];
- Assert.Equal(0u, disk3.ReadsCompleted);
- Assert.Equal(0u, disk3.ReadsMerged);
- Assert.Equal(0u, disk3.SectorsRead);
- Assert.Equal(0u, disk3.TimeReadingMs);
- Assert.Equal(0u, disk3.WritesCompleted);
- Assert.Equal(0u, disk3.WritesMerged);
- Assert.Equal(0u, disk3.SectorsWritten);
- Assert.Equal(0u, disk3.TimeWritingMs);
- Assert.Equal(0u, disk3.IoInProgress);
- Assert.Equal(0u, disk3.TimeIoMs);
- Assert.Equal(0u, disk3.WeightedTimeIoMs);
+ Assert.Equal(0u, disk2.TimeIoMs);
+ Assert.Equal(0u, disk2.WeightedTimeIoMs);
}
[Fact]
@@ -104,7 +102,7 @@ public void Test_ReadAll_With_Invalid_Lines()
});
var reader = new DiskStatsReader(fileSystem);
- var dictionary = reader.ReadAll().ToDictionary(x => x.DeviceName);
+ var dictionary = reader.ReadAll(_skipDevicePrefixes).ToDictionary(x => x.DeviceName);
Assert.Equal(3, dictionary.Count);
var disk1 = dictionary["nvme1n1"];
@@ -132,4 +130,29 @@ public void Test_ReadAll_With_Invalid_Lines()
var disk3 = dictionary["nvme0n1"];
Assert.NotNull(disk3);
}
+
+ [Fact]
+ public void Test_ReadAll_Skips_Prefixes()
+ {
+ string diskStatsFileContent =
+ " 7 0 loop0 100 0 1000 10 1000 0 10000 100 0 1000 100 0 0 0 0 100 100\n" +
+ " 1 0 ram0 200 0 2000 20 2000 0 20000 200 0 2000 200 0 0 0 0 200 200\n" +
+ " 259 0 nvme0n1 300 0 3000 30 3000 0 30000 300 0 3000 300 0 0 0 0 300 300\n" +
+ " 252 0 dm-0 400 0 4000 40 4000 0 40000 400 0 4000 400 0 0 0 0 400 400\n" +
+ " 8 0 sda 500 0 5000 50 5000 0 50000 500 0 5000 500 0 0 0 0 500 500\n";
+
+ var fileSystem = new HardcodedValueFileSystem(new Dictionary
+ {
+ { new FileInfo("/proc/diskstats"), diskStatsFileContent }
+ });
+
+ var reader = new DiskStatsReader(fileSystem);
+ var dictionary = reader.ReadAll(_skipDevicePrefixes).ToDictionary(x => x.DeviceName);
+
+ Assert.DoesNotContain("loop0", dictionary.Keys);
+ Assert.DoesNotContain("ram0", dictionary.Keys);
+ Assert.DoesNotContain("dm-0", dictionary.Keys);
+ Assert.Contains("nvme0n1", dictionary.Keys);
+ Assert.Contains("sda", dictionary.Keys);
+ }
}
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/FakeDiskStatsReader.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/FakeDiskStatsReader.cs
index 1c69be74709..4b8186c8fb7 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/FakeDiskStatsReader.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/FakeDiskStatsReader.cs
@@ -11,15 +11,15 @@ internal class FakeDiskStatsReader(Dictionary> stats) :
{
private int _index;
- public List ReadAll()
+ public DiskStats[] ReadAll(string[] skipDevicePrefixes)
{
if (_index >= stats.Values.First().Count)
{
throw new InvalidOperationException("No more values available.");
}
- List list = stats.Values.Select(x => x[_index]).ToList();
+ DiskStats[] result = stats.Values.Select(x => x[_index]).ToArray();
_index++;
- return list;
+ return result;
}
}
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/LinuxSystemDiskMetricsTests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/LinuxSystemDiskMetricsTests.cs
index c6aba8e0b53..80ebc818894 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/LinuxSystemDiskMetricsTests.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/Disk/LinuxSystemDiskMetricsTests.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
+using System.IO;
using System.Linq;
using Microsoft.Extensions.Diagnostics.Metrics.Testing;
using Microsoft.Extensions.Diagnostics.ResourceMonitoring.Test.Helpers;
@@ -19,6 +20,7 @@ namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Disk.Test;
[OSSkipCondition(OperatingSystems.Windows | OperatingSystems.MacOSX, SkipReason = "Linux specific tests")]
public class LinuxSystemDiskMetricsTests
{
+ private static readonly string[] _skipDevicePrefixes = new[] { "ram", "loop", "dm-" };
private readonly FakeLogger _fakeLogger = new();
[Fact]
@@ -213,4 +215,100 @@ public void Test_MetricValues()
Assert.Equal(4.444, ioTimeMeasurement.Last(x => x.MatchesTags(deviceTagSda)).Value, 0.01); // (4444 - 0) / 1000 = 4.444
Assert.Equal(3.5, ioTimeMeasurement.Last(x => x.MatchesTags(deviceTagSdb)).Value, 0.01); // (9500 - 6000) / 1000 = 3.5
}
+
+ [Fact]
+ public void GetAllDiskStats_RetriesAfterFailureInterval()
+ {
+ using var meterFactory = new TestMeterFactory();
+ var fakeTimeProvider = new FakeTimeProvider();
+ var options = new ResourceMonitoringOptions { EnableSystemDiskIoMetrics = true };
+
+ var diskStats = new DiskStats
+ {
+ DeviceName = "sda",
+ SectorsRead = 100,
+ SectorsWritten = 200,
+ ReadsCompleted = 10,
+ WritesCompleted = 20,
+ TimeIoMs = 1000
+ };
+
+ var diskStatsReaderMock = new Mock();
+ diskStatsReaderMock.Setup(r => r.ReadAll(_skipDevicePrefixes)).Throws();
+
+ var metrics = new LinuxSystemDiskMetrics(
+ _fakeLogger,
+ meterFactory,
+ Options.Options.Create(options),
+ fakeTimeProvider,
+ diskStatsReaderMock.Object);
+
+ using var ioCollector = new MetricCollector(meterFactory.Meters.Single(), ResourceUtilizationInstruments.SystemDiskIo);
+
+ ioCollector.RecordObservableInstruments();
+ Assert.Empty(ioCollector.GetMeasurementSnapshot());
+ diskStatsReaderMock.Verify(r => r.ReadAll(_skipDevicePrefixes), Times.Once);
+
+ ioCollector.RecordObservableInstruments();
+ Assert.Empty(ioCollector.GetMeasurementSnapshot());
+ diskStatsReaderMock.Verify(r => r.ReadAll(_skipDevicePrefixes), Times.Once);
+
+ fakeTimeProvider.Advance(TimeSpan.FromMinutes(5).Add(TimeSpan.FromSeconds(1)));
+
+ ioCollector.RecordObservableInstruments();
+ Assert.Empty(ioCollector.GetMeasurementSnapshot());
+ diskStatsReaderMock.Verify(r => r.ReadAll(_skipDevicePrefixes), Times.Exactly(2));
+
+ diskStatsReaderMock.Reset();
+ diskStatsReaderMock.Setup(r => r.ReadAll(_skipDevicePrefixes)).Returns(new DiskStats[] { diskStats });
+
+ fakeTimeProvider.Advance(TimeSpan.FromMinutes(5).Add(TimeSpan.FromSeconds(1)));
+
+ ioCollector.RecordObservableInstruments();
+ var measurements = ioCollector.GetMeasurementSnapshot();
+ Assert.NotEmpty(measurements);
+ Assert.Contains(measurements, m => m.Tags.Any(t => t.Value?.ToString() == "sda"));
+ diskStatsReaderMock.Verify(r => r.ReadAll(_skipDevicePrefixes), Times.Once);
+
+ fakeTimeProvider.Advance(TimeSpan.FromMinutes(5).Add(TimeSpan.FromSeconds(1)));
+
+ ioCollector.RecordObservableInstruments();
+ measurements = ioCollector.GetMeasurementSnapshot();
+ Assert.NotEmpty(measurements);
+ Assert.Contains(measurements, m => m.Tags.Any(t => t.Value?.ToString() == "sda"));
+ diskStatsReaderMock.Verify(r => r.ReadAll(_skipDevicePrefixes), Times.Exactly(2));
+ }
+
+ [Fact]
+ public void Metrics_Are_Not_Created_When_ReadAll_Throws_FileNotFoundException()
+ {
+ using var meterFactory = new TestMeterFactory();
+ var options = new ResourceMonitoringOptions { EnableSystemDiskIoMetrics = true };
+ var diskStatsReaderMock = new Mock();
+ diskStatsReaderMock.Setup(r => r.ReadAll(_skipDevicePrefixes)).Throws();
+
+ var fakeTimeProvider = new FakeTimeProvider();
+
+ _ = new LinuxSystemDiskMetrics(
+ _fakeLogger,
+ meterFactory,
+ Options.Options.Create(options),
+ fakeTimeProvider,
+ diskStatsReaderMock.Object);
+
+ Meter meter = meterFactory.Meters.Single();
+
+ using var diskIoCollector = new MetricCollector(meter, ResourceUtilizationInstruments.SystemDiskIo);
+ using var operationCollector = new MetricCollector(meter, ResourceUtilizationInstruments.SystemDiskOperations);
+ using var ioTimeCollector = new MetricCollector(meter, ResourceUtilizationInstruments.SystemDiskIoTime);
+
+ diskIoCollector.RecordObservableInstruments();
+ operationCollector.RecordObservableInstruments();
+ ioTimeCollector.RecordObservableInstruments();
+
+ Assert.Empty(diskIoCollector.GetMeasurementSnapshot());
+ Assert.Empty(operationCollector.GetMeasurementSnapshot());
+ Assert.Empty(ioTimeCollector.GetMeasurementSnapshot());
+ diskStatsReaderMock.Verify(r => r.ReadAll(_skipDevicePrefixes), Times.Once);
+ }
}
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxCountersTests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxCountersTests.cs
index e0ff3880075..4f8dbf9547f 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxCountersTests.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxCountersTests.cs
@@ -1,12 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.IO;
using System.Threading;
using FluentAssertions;
using Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Network;
+using Microsoft.Extensions.Time.Testing;
using Microsoft.Shared.Instruments;
using Moq;
using Xunit;
@@ -85,7 +87,7 @@ public void LinuxNetworkCounters_Registers_Instruments()
.Returns(meter);
var tcpStateInfo = new LinuxTcpStateInfo(options, parser);
- var lnm = new LinuxNetworkMetrics(meterFactoryMock.Object, tcpStateInfo);
+ var lnm = new LinuxNetworkMetrics(meterFactoryMock.Object, tcpStateInfo, new FakeTimeProvider(DateTimeOffset.UtcNow));
using var listener = new MeterListener
{
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxNetworkMetricsTests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxNetworkMetricsTests.cs
index 6668ebe811c..40536a3245c 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxNetworkMetricsTests.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Linux/LinuxNetworkMetricsTests.cs
@@ -1,10 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+using System.Collections.Generic;
using System.Diagnostics.Metrics;
+using System.IO;
using System.Linq;
using Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Network;
using Microsoft.Extensions.Diagnostics.ResourceMonitoring.Test.Helpers;
+using Microsoft.Extensions.Time.Testing;
using Microsoft.Shared.Instruments;
using Microsoft.TestUtilities;
using Moq;
@@ -15,14 +19,120 @@ namespace Microsoft.Extensions.Diagnostics.ResourceMonitoring.Linux.Test;
[OSSkipCondition(OperatingSystems.Windows | OperatingSystems.MacOSX, SkipReason = "Linux specific tests")]
public class LinuxNetworkMetricsTests
{
+ private readonly Mock _tcpStateInfoProvider = new();
+ private readonly DateTimeOffset _startTime = DateTimeOffset.UtcNow;
+ private FakeTimeProvider _timeProvider;
+
+ public LinuxNetworkMetricsTests()
+ {
+ _timeProvider = new FakeTimeProvider(_startTime);
+
+ _tcpStateInfoProvider.Setup(p => p.GetIpV4TcpStateInfo()).Returns(new TcpStateInfo());
+ _tcpStateInfoProvider.Setup(p => p.GetIpV6TcpStateInfo()).Returns(new TcpStateInfo());
+ }
+
[Fact]
- public void Creates_Meter_With_Correct_Name()
+ public void CreatesMeter_WithCorrectName()
{
using var meterFactory = new TestMeterFactory();
- var tcpStateInfoProviderMock = new Mock();
- _ = new LinuxNetworkMetrics(meterFactory, tcpStateInfoProviderMock.Object);
+ _ = new LinuxNetworkMetrics(
+ meterFactory,
+ _tcpStateInfoProvider.Object,
+ _timeProvider);
Meter meter = meterFactory.Meters.Single();
Assert.Equal(ResourceUtilizationInstruments.MeterName, meter.Name);
}
+
+ [Fact]
+ public void GetTcpStateInfoWithRetry_SuccessfulCall_ReturnsState()
+ {
+ var expectedV4 = new TcpStateInfo { ClosedCount = 42 };
+ var expectedV6 = new TcpStateInfo { EstabCount = 24 };
+ _tcpStateInfoProvider.Setup(p => p.GetIpV4TcpStateInfo()).Returns(expectedV4);
+ _tcpStateInfoProvider.Setup(p => p.GetIpV6TcpStateInfo()).Returns(expectedV6);
+
+ LinuxNetworkMetrics metrics = CreateMetrics();
+ List> measurements = metrics.GetMeasurements().ToList();
+
+ Assert.Contains(measurements, m => HasTagWithValue(m, "network.type", "ipv4", 42));
+ Assert.Contains(measurements, m => HasTagWithValue(m, "system.network.state", "close", 42));
+ Assert.Contains(measurements, m => HasTagWithValue(m, "network.type", "ipv6", 24));
+ Assert.Contains(measurements, m => HasTagWithValue(m, "system.network.state", "established", 24));
+ }
+
+ [Theory]
+ [InlineData(typeof(FileNotFoundException))]
+ [InlineData(typeof(DirectoryNotFoundException))]
+ [InlineData(typeof(UnauthorizedAccessException))]
+ public void GetTcpStateInfoWithRetry_Failure_SetsUnavailableAndReturnsDefault(Type exceptionType)
+ {
+ _tcpStateInfoProvider.Setup(p => p.GetIpV4TcpStateInfo()).Throws((Exception)Activator.CreateInstance(exceptionType)!);
+
+ LinuxNetworkMetrics metrics = CreateMetrics();
+ List> measurements = metrics.GetMeasurements().ToList();
+
+ Assert.All(measurements.Take(11), m => Assert.Equal(0, m.Value));
+ }
+
+ [Fact]
+ public void GetTcpStateInfoWithRetry_DuringRetryInterval_ReturnsDefault()
+ {
+ _tcpStateInfoProvider.SetupSequence(p => p.GetIpV4TcpStateInfo())
+ .Throws(new FileNotFoundException())
+ .Returns(new TcpStateInfo { ClosedCount = 123 });
+
+ LinuxNetworkMetrics metrics = CreateMetrics();
+ List> first = metrics.GetMeasurements().ToList();
+
+ _timeProvider.Advance(TimeSpan.FromMinutes(2));
+ List> second = metrics.GetMeasurements().ToList();
+
+ Assert.All(first.Take(11), m => Assert.Equal(0, m.Value));
+ Assert.All(second.Take(11), m => Assert.Equal(0, m.Value));
+ _tcpStateInfoProvider.Verify(p => p.GetIpV4TcpStateInfo(), Times.Once);
+ }
+
+ [Fact]
+ public void GetTcpStateInfoWithRetry_AfterRetryInterval_ResetsUnavailableOnSuccess()
+ {
+ _tcpStateInfoProvider.SetupSequence(p => p.GetIpV4TcpStateInfo())
+ .Throws(new FileNotFoundException())
+ .Returns(new TcpStateInfo { ClosedCount = 99 });
+
+ LinuxNetworkMetrics metrics = CreateMetrics();
+ List> first = metrics.GetMeasurements().ToList();
+
+ _timeProvider.Advance(TimeSpan.FromMinutes(6));
+ List> second = metrics.GetMeasurements().ToList();
+
+ Assert.All(first.Take(11), m => Assert.Equal(0, m.Value));
+ Assert.Equal(99, second[0].Value);
+ Assert.Contains(second, m => HasTagWithValue(m, "network.type", "ipv4", 99));
+ Assert.Contains(second, m => HasTagWithValue(m, "system.network.state", "close", 99));
+
+ _tcpStateInfoProvider.Verify(p => p.GetIpV4TcpStateInfo(), Times.Exactly(2));
+ }
+
+ private static bool HasTagWithValue(Measurement measurement, string tagKey, string tagValue, long expectedValue)
+ {
+ foreach (KeyValuePair tag in measurement.Tags)
+ {
+ if (tag.Key == tagKey && string.Equals(tag.Value as string, tagValue, StringComparison.Ordinal))
+ {
+ return measurement.Value == expectedValue;
+ }
+ }
+
+ return false;
+ }
+
+ private LinuxNetworkMetrics CreateMetrics()
+ {
+ using var meterFactory = new TestMeterFactory();
+ return new LinuxNetworkMetrics(
+ meterFactory,
+ _tcpStateInfoProvider.Object,
+ _timeProvider);
+ }
}
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/Tcp6TableInfoTests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/Tcp6TableInfoTests.cs
index 3ef240e1274..a5dfdb5c170 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/Tcp6TableInfoTests.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/Tcp6TableInfoTests.cs
@@ -234,11 +234,12 @@ public void Test_Tcp6TableInfo_Get_UnsuccessfulStatus_All_The_Time()
SourceIpAddresses = new HashSet { "[::1]" },
SamplingInterval = DefaultTimeSpan
};
- WindowsTcpStateInfo tcp6TableInfo = new WindowsTcpStateInfo(Options.Options.Create(options));
+
+ var tcp6TableInfo = new WindowsTcpStateInfo(Options.Options.Create(options));
tcp6TableInfo.SetGetTcp6TableDelegate(FakeGetTcp6TableWithUnsuccessfulStatusAllTheTime);
Assert.Throws(() =>
{
- var tcpStateInfo = tcp6TableInfo.GetpIpV6TcpStateInfo();
+ TcpStateInfo tcpStateInfo = tcp6TableInfo.GetIpV6TcpStateInfo();
});
}
@@ -254,7 +255,7 @@ public void Test_Tcp6TableInfo_Get_InsufficientBuffer_Then_Get_InvalidParameter(
tcp6TableInfo.SetGetTcp6TableDelegate(FakeGetTcp6TableWithInsufficientBufferAndInvalidParameter);
Assert.Throws(() =>
{
- var tcpStateInfo = tcp6TableInfo.GetpIpV6TcpStateInfo();
+ TcpStateInfo tcpStateInfo = tcp6TableInfo.GetIpV6TcpStateInfo();
});
}
@@ -270,7 +271,7 @@ public void Test_Tcp6TableInfo_Get_Correct_Information()
};
WindowsTcpStateInfo tcp6TableInfo = new WindowsTcpStateInfo(Options.Options.Create(options));
tcp6TableInfo.SetGetTcp6TableDelegate(FakeGetTcp6TableWithFakeInformation);
- var tcpStateInfo = tcp6TableInfo.GetpIpV6TcpStateInfo();
+ TcpStateInfo tcpStateInfo = tcp6TableInfo.GetIpV6TcpStateInfo();
Assert.NotNull(tcpStateInfo);
Assert.Equal(1, tcpStateInfo.ClosedCount);
Assert.Equal(1, tcpStateInfo.ListenCount);
@@ -286,7 +287,7 @@ public void Test_Tcp6TableInfo_Get_Correct_Information()
Assert.Equal(1, tcpStateInfo.DeleteTcbCount);
// Second calling in a small interval.
- tcpStateInfo = tcp6TableInfo.GetpIpV6TcpStateInfo();
+ tcpStateInfo = tcp6TableInfo.GetIpV6TcpStateInfo();
Assert.NotNull(tcpStateInfo);
Assert.Equal(1, tcpStateInfo.ClosedCount);
Assert.Equal(1, tcpStateInfo.ListenCount);
@@ -303,7 +304,7 @@ public void Test_Tcp6TableInfo_Get_Correct_Information()
// Third calling in a long interval.
Thread.Sleep(6000);
- tcpStateInfo = tcp6TableInfo.GetpIpV6TcpStateInfo();
+ tcpStateInfo = tcp6TableInfo.GetIpV6TcpStateInfo();
Assert.NotNull(tcpStateInfo);
Assert.Equal(2, tcpStateInfo.ClosedCount);
Assert.Equal(2, tcpStateInfo.ListenCount);
diff --git a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/TcpTableInfoTests.cs b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/TcpTableInfoTests.cs
index fb79d0cb839..8c88fc123dd 100644
--- a/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/TcpTableInfoTests.cs
+++ b/test/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring.Tests/Windows/TcpTableInfoTests.cs
@@ -181,7 +181,7 @@ public void Test_TcpTableInfo_Get_UnsuccessfulStatus_All_The_Time()
tcpTableInfo.SetGetTcpTableDelegate(FakeGetTcpTableWithUnsuccessfulStatusAllTheTime);
Assert.Throws(() =>
{
- var tcpStateInfo = tcpTableInfo.GetpIpV4TcpStateInfo();
+ var tcpStateInfo = tcpTableInfo.GetIpV4TcpStateInfo();
});
}
@@ -197,7 +197,7 @@ public void Test_TcpTableInfo_Get_InsufficientBuffer_Then_Get_InvalidParameter()
tcpTableInfo.SetGetTcpTableDelegate(FakeGetTcpTableWithInsufficientBufferAndInvalidParameter);
Assert.Throws(() =>
{
- var tcpStateInfo = tcpTableInfo.GetpIpV4TcpStateInfo();
+ var tcpStateInfo = tcpTableInfo.GetIpV4TcpStateInfo();
});
}
@@ -213,7 +213,7 @@ public void Test_TcpTableInfo_Get_Correct_Information()
};
WindowsTcpStateInfo tcpTableInfo = new WindowsTcpStateInfo(Options.Options.Create(options));
tcpTableInfo.SetGetTcpTableDelegate(FakeGetTcpTableWithFakeInformation);
- var tcpStateInfo = tcpTableInfo.GetpIpV4TcpStateInfo();
+ var tcpStateInfo = tcpTableInfo.GetIpV4TcpStateInfo();
Assert.NotNull(tcpStateInfo);
Assert.Equal(1, tcpStateInfo.ClosedCount);
Assert.Equal(1, tcpStateInfo.ListenCount);
@@ -229,7 +229,7 @@ public void Test_TcpTableInfo_Get_Correct_Information()
Assert.Equal(1, tcpStateInfo.DeleteTcbCount);
// Second calling in a small interval.
- tcpStateInfo = tcpTableInfo.GetpIpV4TcpStateInfo();
+ tcpStateInfo = tcpTableInfo.GetIpV4TcpStateInfo();
Assert.NotNull(tcpStateInfo);
Assert.Equal(1, tcpStateInfo.ClosedCount);
Assert.Equal(1, tcpStateInfo.ListenCount);
@@ -246,7 +246,7 @@ public void Test_TcpTableInfo_Get_Correct_Information()
// Third calling in a long interval.
Thread.Sleep(6000);
- tcpStateInfo = tcpTableInfo.GetpIpV4TcpStateInfo();
+ tcpStateInfo = tcpTableInfo.GetIpV4TcpStateInfo();
Assert.NotNull(tcpStateInfo);
Assert.Equal(2, tcpStateInfo.ClosedCount);
Assert.Equal(2, tcpStateInfo.ListenCount);