Streamline stat registration code in ServerStats. Remove most of the

usage of ProcessCounters which tend to fail oddly and are not supported
everywhere.
0.7.4-extended
Robert Adams 2013-02-24 07:43:01 -08:00 committed by Justin Clark-Casey (justincc)
parent 663809479d
commit 5d187b9b28
1 changed files with 50 additions and 160 deletions

View File

@ -63,6 +63,7 @@ public class ServerStats : ISharedRegionModule
public readonly string ContainerNetwork = "network"; public readonly string ContainerNetwork = "network";
public readonly string ContainerProcess = "process"; public readonly string ContainerProcess = "process";
public string NetworkInterfaceTypes = "Ethernet";
readonly int performanceCounterSampleInterval = 500; readonly int performanceCounterSampleInterval = 500;
int lastperformanceCounterSampleTime = 0; int lastperformanceCounterSampleTime = 0;
@ -86,20 +87,6 @@ public class ServerStats : ISharedRegionModule
PerfCounterControl processorPercentPerfCounter = null; PerfCounterControl processorPercentPerfCounter = null;
PerfCounterControl processThreadCountPerfCounter = null;
PerfCounterControl processVirtualBytesPerfCounter = null;
PerfCounterControl processWorkingSetPerfCounter = null;
PerfCounterControl dotNETCLRMemoryAllocatedBytesPerSecPerfCounter = null;
PerfCounterControl dotNETCLRMemoryGen0HeapSizePerfCounter = null;
PerfCounterControl dotNETCLRMemoryGen1HeapSizePerfCounter = null;
PerfCounterControl dotNETCLRMemoryGen2HeapSizePerfCounter = null;
PerfCounterControl dotNETCLRLaTTotalContentionsPerfCounter = null;
PerfCounterControl dotNETCLRLaTContentionsPerSecPerfCounter = null;
PerfCounterControl dotNETCLRLaTLogicalThreadsPerfCounter = null;
PerfCounterControl dotNETCLRLaTPhysicalThreadsPerfCounter = null;
#region ISharedRegionModule #region ISharedRegionModule
// IRegionModuleBase.Name // IRegionModuleBase.Name
public string Name { get { return "Server Stats"; } } public string Name { get { return "Server Stats"; } }
@ -108,10 +95,15 @@ public class ServerStats : ISharedRegionModule
// IRegionModuleBase.Initialize // IRegionModuleBase.Initialize
public void Initialise(IConfigSource source) public void Initialise(IConfigSource source)
{ {
IConfig cnfg = source.Configs["Statistics"]; IConfig cfg = source.Configs["Monitoring"];
if (cnfg != null) if (cfg != null)
Enabled = cnfg.GetBoolean("Enabled", true); Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
if (Enabled)
{
NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
}
} }
// IRegionModuleBase.Close // IRegionModuleBase.Close
public void Close() public void Close()
@ -148,6 +140,13 @@ public class ServerStats : ISharedRegionModule
} }
#endregion ISharedRegionModule #endregion ISharedRegionModule
private void MakeStat(string pName, string pUnit, string pContainer, Action<Stat> act)
{
Stat stat = new Stat(pName, pName, "", pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
StatsManager.RegisterStat(stat);
RegisteredStats.Add(pName, stat);
}
public void RegisterServerStats() public void RegisterServerStats()
{ {
lastperformanceCounterSampleTime = Util.EnvironmentTickCount(); lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
@ -157,7 +156,7 @@ public class ServerStats : ISharedRegionModule
try try
{ {
tempName = "CPU_Percent"; tempName = "CPUPercent";
tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total"); tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
processorPercentPerfCounter = new PerfCounterControl(tempPC); processorPercentPerfCounter = new PerfCounterControl(tempPC);
// A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy. // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
@ -167,31 +166,17 @@ public class ServerStats : ISharedRegionModule
StatsManager.RegisterStat(tempStat); StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat); RegisteredStats.Add(tempName, tempStat);
/* Performance counters are not the way to go. Ick. Find another way. MakeStat("TotalProcessorTime", "sec", ContainerProcessor,
tempName = "Thread_Count"; (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
tempPC = new PerformanceCounter("Process", "Thread Count", AppDomain.CurrentDomain.FriendlyName);
processThreadCountPerfCounter = new PerfCounterControl(tempPC);
tempStat = new Stat("Thread_Count", "Thread_Count", "", "threads", CategoryServer, ContainerProcess,
StatType.Pull, (s) => { GetNextValue(s, processThreadCountPerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Virtual_Bytes"; MakeStat("UserProcessorTime", "sec", ContainerProcessor,
tempPC = new PerformanceCounter("Process", "Virtual Bytes", AppDomain.CurrentDomain.FriendlyName); (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
processVirtualBytesPerfCounter = new PerfCounterControl(tempPC);
tempStat = new Stat("Virtual_Bytes", "Virtual_Bytes", "", "MB", CategoryServer, ContainerProcess,
StatType.Pull, (s) => { GetNextValue(s, processVirtualBytesPerfCounter, 1024.0*1024.0); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Working_Set"; MakeStat("PrivilegedProcessorTime", "sec", ContainerProcessor,
tempPC = new PerformanceCounter("Process", "Working Set", AppDomain.CurrentDomain.FriendlyName); (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
processWorkingSetPerfCounter = new PerfCounterControl(tempPC);
tempStat = new Stat("Working_Set", "Working_Set", "", "MB", CategoryServer, ContainerProcess, MakeStat("Threads", "threads", ContainerProcessor,
StatType.Pull, (s) => { GetNextValue(s, processWorkingSetPerfCounter, 1024.0*1024.0); }, StatVerbosity.Info); (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
*/
} }
catch (Exception e) catch (Exception e)
{ {
@ -200,112 +185,33 @@ public class ServerStats : ISharedRegionModule
try try
{ {
/* The ".NET CLR *" categories aren't working for me. List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
tempName = ""Bytes_Allocated_Per_Sec";
tempPC = new PerformanceCounter(".NET CLR Memory", "Allocated Bytes/sec", AppDomain.CurrentDomain.FriendlyName);
dotNETCLRMemoryAllocatedBytesPerSecPerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat(tempName, tempName, "", "bytes/sec", ServerCategory, MemoryContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRMemoryAllocatedBytesPerSecPerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Gen_0_Heap_Size";
tempPC = new PerformanceCounter(".NET CLR Memory", "Gen 0 heap size", AppDomain.CurrentDomain.FriendlyName);
dotNETCLRMemoryGen0HeapSizePerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Gen_0_Heap_Size", "Gen_0_Heap_Size", "", "bytes", ServerCategory, MemoryContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRMemoryGen0HeapSizePerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Gen_1_Heap_Size";
tempPC = new PerformanceCounter(".NET CLR Memory", "Gen 1 heap size", AppDomain.CurrentDomain.FriendlyName);
dotNETCLRMemoryGen1HeapSizePerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Gen_1_Heap_Size", "Gen_1_Heap_Size", "", "bytes", ServerCategory, MemoryContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRMemoryGen1HeapSizePerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Gen_2_Heap_Size";
tempPC = new PerformanceCounter(".NET CLR Memory", "Gen 2 heap size", AppDomain.CurrentDomain.FriendlyName);
dotNETCLRMemoryGen2HeapSizePerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Gen_2_Heap_Size", "Gen_2_Heap_Size", "", "bytes", ServerCategory, MemoryContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRMemoryGen2HeapSizePerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Total_Lock_Contentions";
tempPC = new PerformanceCounter(".NET CLR LocksAndThreads", "Total # of Contentions");
dotNETCLRLaTTotalContentionsPerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Total_Lock_Contentions", "Total_Lock_Contentions", "", "contentions", ServerCategory, ProcessContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRLaTTotalContentionsPerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Lock_Contentions";
tempPC = new PerformanceCounter(".NET CLR LocksAndThreads", "Contention Rate / sec");
dotNETCLRLaTContentionsPerSecPerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Lock_Contentions", "Lock_Contentions", "", "contentions/sec", ServerCategory, ProcessContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRLaTContentionsPerSecPerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Logical_Threads";
tempPC = new PerformanceCounter(".NET CLR LocksAndThreads", "# of current logical Threads");
dotNETCLRLaTLogicalThreadsPerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Logicial_Threads", "Logicial_Threads", "", "threads", ServerCategory, ProcessContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRLaTLogicalThreadsPerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Physical_Threads";
tempPC = new PerformanceCounter(".NET CLR LocksAndThreads", "# of current physical Threads");
dotNETCLRLaTPhysicalThreadsPerfCounter = new PerfCounterControl(tempPC, tempStat);
tempStat = new Stat("Physical_Threads", "Physical_Threads", "", "threads", ServerCategory, ProcessContainer,
StatType.Pull, (s) => { GetNextValue(s, dotNETCLRLaTPhysicalThreadsPerfCounter); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
*/
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating '.NET CLR Memory': {1}", LogHeader, e);
}
try
{
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces(); IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
// IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
// (network) => network.NetworkInterfaceType == NetworkInterfaceType.Ethernet);
// IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
// (network) => network.OperationalStatus == OperationalStatus.Up);
foreach (NetworkInterface nic in nics) foreach (NetworkInterface nic in nics)
{ {
if (nic.OperationalStatus != OperationalStatus.Up || nic.NetworkInterfaceType != NetworkInterfaceType.Ethernet) if (nic.OperationalStatus != OperationalStatus.Up)
continue; continue;
string nicInterfaceType = nic.NetworkInterfaceType.ToString();
if (!okInterfaceTypes.Contains(nicInterfaceType))
{
m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'. To include, add to [Monitoring]NetworkInterfaceTypes='Ethernet,Loopback'",
LogHeader, nic.Name, nicInterfaceType);
continue;
}
if (nic.Supports(NetworkInterfaceComponent.IPv4)) if (nic.Supports(NetworkInterfaceComponent.IPv4))
{ {
IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
if (nicStats != null) if (nicStats != null)
{ {
tempName = "Bytes_Rcvd/" + nic.Name; MakeStat("BytesRcvd/" + nic.Name, "KB", ContainerNetwork,
tempStat = new Stat(tempName, tempName, nic.Name, "KB", CategoryServer, ContainerNetwork, (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
StatType.Pull, (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }, StatVerbosity.Info); MakeStat("BytesSent/" + nic.Name, "KB", ContainerNetwork,
StatsManager.RegisterStat(tempStat); (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
RegisteredStats.Add(tempName, tempStat); MakeStat("TotalBytes/" + nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
tempName = "Bytes_Sent/" + nic.Name;
tempStat = new Stat(tempName, tempName, nic.Name, "KB", CategoryServer, ContainerNetwork,
StatType.Pull, (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Total_Bytes/" + nic.Name;
tempStat = new Stat(tempName, tempName, nic.Name, "KB", CategoryServer, ContainerNetwork,
StatType.Pull, (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
} }
} }
} }
@ -315,30 +221,14 @@ public class ServerStats : ISharedRegionModule
m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
} }
tempName = "Process_Memory"; MakeStat("ProcessMemory", "MB", ContainerMemory,
tempStat = new Stat(tempName, tempName, "", "MB", CategoryServer, ContainerMemory, (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
StatType.Pull, (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }, StatVerbosity.Info); MakeStat("ObjectMemory", "MB", ContainerMemory,
StatsManager.RegisterStat(tempStat); (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
RegisteredStats.Add(tempName, tempStat); MakeStat("LastMemoryChurn", "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
tempName = "Object_Memory"; MakeStat("AverageMemoryChurn", "MB/sec", ContainerMemory,
tempStat = new Stat(tempName, tempName, "", "MB", CategoryServer, ContainerMemory, (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
StatType.Pull, (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Last_Memory_Churn";
tempStat = new Stat(tempName, tempName, "", "MB/sec", CategoryServer, ContainerMemory,
StatType.Pull, (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
tempName = "Average_Memory_Churn";
tempStat = new Stat(tempName, tempName, "", "MB/sec", CategoryServer, ContainerMemory,
StatType.Pull, (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }, StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
} }
// Notes on performance counters: // Notes on performance counters: