(I know there is a Performance Counter for Windows (PCW) forum but I could not figure out its forum category when asking the question, so please forward to the correct forum for me if needed.)
My application is getting intermittent errors when trying to access some system counters throughPerformanceCounter class. The application runs on Windows Server 2008 R2 Standard as a service.
Error #1:
EXCEPTION
(LEVEL 1): System.ArgumentException
EXCEPTION OUTPUT: PerformanceCounter category Processor does not exist
Parameter name: counterPath
Error #2:
EXCEPTION
(LEVEL 1): System.InvalidOperationException
EXCEPTION OUTPUT: The Counter layout for the Category specified is invalid, a counter of the type: AverageCount64,
AverageTimer32, CounterMultiTimer, CounterMultiTimerInverse, CounterMultiTimer100Ns, CounterMultiTimer100NsInverse, RawFraction, or SampleFraction has to be immediately followed by any of the base counter types: AverageBase, CounterMultiBase, RawBase or SampleBase.
STACK TRACE:
at System.Diagnostics.CategorySample.GetCounterDefinitionSample(String counter)
at System.Diagnostics.PerformanceCounter.NextSample()
at System.Diagnostics.PerformanceCounter.NextValue()
at System.Collections.Generic.List`1.ForEach(Action`1 action)
The error occurs intermittently every day on various servers, but when I manually start the service it works just fine.
Below are the performance counters my application tries to access:
_processorUserPercent = new Counter(@"Processor(_Total)\% User Time");
_processorSystemPercent = new Counter(@"Processor(_Total)\% Privileged Time");
_memoryAvailableBytes = new Counter(@"Memory\Available Bytes");
_networkBytesReceived = new Counter(@"Network Interface(*)\Bytes Received/sec");
_networkBytesSent = new Counter(@"Network Interface(*)\Bytes Sent/sec");
_diskBytesRead = new Counter(@"PhysicalDisk(_Total)\Avg. Disk Bytes/Read");
_diskBytesWritten = new Counter(@"PhysicalDisk(_Total)\Avg. Disk Bytes/Write");
The Counter class:
class Counter
{
private readonly List<PerformanceCounter> _counters;
private readonly string _categoryName;
private readonly string _counterName;
public Counter(string counterPath)
{
var match = Regex.Match(counterPath, @"^([^()]*)(?:\((.*)\))?\\(.*)$");
if (!match.Success)
throw new ArgumentException("Invalid format", "counterPath");
_categoryName = match.Groups[1].Value;
_counterName = match.Groups[3].Value;
var instanceName = match.Groups[2].Value;
if (!PerformanceCounterCategory.Exists(_categoryName))
throw new ArgumentException("PerformanceCounter category {0} does not exist".FormatWith(_categoryName), "counterPath");
if (instanceName.IsNullOrEmpty())
{
_counters = new List<PerformanceCounter> { new PerformanceCounter(_categoryName, _counterName) };
}
else
{
var instanceNames = instanceName == "*"
? new PerformanceCounterCategory(_categoryName).GetInstanceNames()
: new[] { instanceName };
_counters = instanceNames
.Select(instance => new PerformanceCounter(_categoryName, _counterName, instance))
.ToList();
}
// prime NextValue to have non-zero value on first call to CollectValue
_counters.ForEach(x => x.NextValue());
}
public float GetValue()
{
var values = new List<float>();
foreach (var counter in _counters)
{
try
{
values.Add(counter.NextValue());
}
catch (Win32Exception)
{
}
catch (InvalidOperationException)
{
// Happens when coming out of stand-by on desktop. Shouldn't happen on a production machine.
}
}
return values.Sum();
}
}