29 using System.Collections.Generic;
 
   30 using System.Diagnostics;
 
   32 using System.Net.NetworkInformation;
 
   34 using System.Threading;
 
   37 using OpenMetaverse.StructuredData;
 
   38 using OpenSim.Framework;
 
   40 namespace OpenSim.Framework.Monitoring
 
   44         private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
   45         private readonly 
string LogHeader = 
"[SERVER STATS]";
 
   47         public bool Enabled = 
false;
 
   48         private static Dictionary<string, Stat> RegisteredStats = 
new Dictionary<string, Stat>();
 
   50         public readonly 
string CategoryServer = 
"server";
 
   52         public readonly 
string ContainerThreadpool = 
"threadpool";
 
   53         public readonly 
string ContainerProcessor = 
"processor";
 
   54         public readonly 
string ContainerMemory = 
"memory";
 
   55         public readonly 
string ContainerNetwork = 
"network";
 
   56         public readonly 
string ContainerProcess = 
"process";
 
   58         public string NetworkInterfaceTypes = 
"Ethernet";
 
   60         readonly 
int performanceCounterSampleInterval = 500;
 
   63         private class PerfCounterControl
 
   65             public PerformanceCounter perfCounter;
 
   68             public PerfCounterControl(PerformanceCounter pPc)
 
   69                 : 
this(pPc, String.Empty)
 
   72             public PerfCounterControl(PerformanceCounter pPc, 
string pName)
 
   80         PerfCounterControl processorPercentPerfCounter = null;
 
   88             IConfig cfg = source.Configs[
"Monitoring"];
 
   91                 Enabled = cfg.GetBoolean(
"ServerStatsEnabled", 
true);
 
   95                 NetworkInterfaceTypes = cfg.GetString(
"NetworkInterfaceTypes", 
"Ethernet");
 
  101             if (RegisteredStats.Count == 0)
 
  102                 RegisterServerStats();
 
  107             if (RegisteredStats.Count > 0)
 
  109                 foreach (
Stat stat 
in RegisteredStats.Values)
 
  111                     StatsManager.DeregisterStat(stat);
 
  114                 RegisteredStats.Clear();
 
  118         private void MakeStat(
string pName, 
string pDesc, 
string pUnit, 
string pContainer, Action<Stat> act)
 
  123         private void MakeStat(
string pName, 
string pDesc, 
string pUnit, 
string pContainer, Action<Stat> act, 
MeasuresOfInterest moi)
 
  128             Stat stat = 
new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, 
StatType.Pull, moi, act, 
StatVerbosity.Debug);
 
  129             StatsManager.RegisterStat(stat);
 
  130             RegisteredStats.Add(pName, stat);
 
  136             PerformanceCounter tempPC;
 
  142                 tempName = 
"CPUPercent";
 
  143                 tempPC = 
new PerformanceCounter(
"Processor", 
"% Processor Time", 
"_Total");
 
  144                 processorPercentPerfCounter = 
new PerfCounterControl(tempPC);
 
  146                 tempStat = 
new Stat(tempName, tempName, 
"", 
"percent", CategoryServer, ContainerProcessor,
 
  147                                 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter); },
 
  149                 StatsManager.RegisterStat(tempStat);
 
  150                 RegisteredStats.Add(tempName, tempStat);
 
  152                 MakeStat(
"TotalProcessorTime", null, 
"sec", ContainerProcessor,
 
  153                                     (s) => { s.Value = Math.Round(Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds, 3); });
 
  155                 MakeStat(
"UserProcessorTime", null, 
"sec", ContainerProcessor,
 
  156                                     (s) => { s.Value = Math.Round(Process.GetCurrentProcess().UserProcessorTime.TotalSeconds, 3); });
 
  158                 MakeStat(
"PrivilegedProcessorTime", null, 
"sec", ContainerProcessor,
 
  159                                     (s) => { s.Value = Math.Round(Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds, 3); });
 
  161                 MakeStat(
"Threads", null, 
"threads", ContainerProcessor,
 
  162                                     (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
 
  166                 m_log.ErrorFormat(
"{0} Exception creating 'Process': {1}", LogHeader, e);
 
  169             MakeStat(
"BuiltinThreadpoolWorkerThreadsAvailable", null, 
"threads", ContainerThreadpool,
 
  172                     int workerThreads, iocpThreads; 
 
  173                     ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); 
 
  174                     s.Value = workerThreads;
 
  177             MakeStat(
"BuiltinThreadpoolIOCPThreadsAvailable", null, 
"threads", ContainerThreadpool,
 
  180                     int workerThreads, iocpThreads; 
 
  181                     ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); 
 
  182                     s.Value = iocpThreads;
 
  185             if (Util.FireAndForgetMethod == 
FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
 
  187                 MakeStat(
"STPMaxThreads", null, 
"threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
 
  188                 MakeStat(
"STPMinThreads", null, 
"threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
 
  189                 MakeStat(
"STPConcurrency", null, 
"threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
 
  190                 MakeStat(
"STPActiveThreads", null, 
"threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
 
  191                 MakeStat(
"STPInUseThreads", null, 
"threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
 
  192                 MakeStat(
"STPWorkItemsWaiting", null, 
"threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
 
  197                 "Number of outbound HTTP requests made", 
 
  200                 s => s.Value = WebUtil.RequestNumber,
 
  205                 List<string> okInterfaceTypes = 
new List<string>(NetworkInterfaceTypes.Split(
','));
 
  208                 foreach (NetworkInterface nic 
in nics)
 
  210                     if (nic.OperationalStatus != OperationalStatus.Up)
 
  213                     string nicInterfaceType = nic.NetworkInterfaceType.ToString();
 
  214                     if (!okInterfaceTypes.Contains(nicInterfaceType))
 
  216                         m_log.DebugFormat(
"{0} Not including stats for network interface '{1}' of type '{2}'.",
 
  217                                                 LogHeader, nic.Name, nicInterfaceType);
 
  218                         m_log.DebugFormat(
"{0}     To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
 
  219                                                 LogHeader, NetworkInterfaceTypes);
 
  223                     if (nic.Supports(NetworkInterfaceComponent.IPv4))
 
  225                         IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
 
  226                         if (nicStats != null)
 
  228                             MakeStat(
"BytesRcvd/" + nic.Name, nic.Name, 
"KB", ContainerNetwork,
 
  229                                             (s) => { LookupNic(s, (ns) => { 
return ns.BytesReceived; }, 1024.0); });
 
  230                             MakeStat(
"BytesSent/" + nic.Name, nic.Name, 
"KB", ContainerNetwork,
 
  231                                             (s) => { LookupNic(s, (ns) => { 
return ns.BytesSent; }, 1024.0); });
 
  232                             MakeStat(
"TotalBytes/" + nic.Name, nic.Name, 
"KB", ContainerNetwork,
 
  233                                             (s) => { LookupNic(s, (ns) => { 
return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
 
  241                 m_log.ErrorFormat(
"{0} Exception creating 'Network Interface': {1}", LogHeader, e);
 
  244             MakeStat(
"ProcessMemory", null, 
"MB", ContainerMemory,
 
  245                                 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
 
  246             MakeStat(
"HeapMemory", null, 
"MB", ContainerMemory,
 
  247                                 (s) => { s.Value = Math.Round(GC.GetTotalMemory(
false) / 1024d / 1024d, 3); });
 
  248             MakeStat(
"LastHeapAllocationRate", null, 
"MB/sec", ContainerMemory,
 
  249                                 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
 
  250             MakeStat(
"AverageHeapAllocationRate", null, 
"MB/sec", ContainerMemory,
 
  251                                 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
 
  253             MakeStat(
"ProcessResident", null, 
"MB", ContainerProcess,
 
  256                                     Process myprocess = Process.GetCurrentProcess();
 
  258                                     s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0);
 
  260             MakeStat(
"ProcessPaged", null, 
"MB", ContainerProcess,
 
  263                                     Process myprocess = Process.GetCurrentProcess();
 
  265                                     s.Value = Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0);
 
  267             MakeStat(
"ProcessVirtual", null, 
"MB", ContainerProcess,
 
  270                                     Process myprocess = Process.GetCurrentProcess();
 
  272                                     s.Value = Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0);
 
  274             MakeStat(
"PeakProcessResident", null, 
"MB", ContainerProcess,
 
  277                                     Process myprocess = Process.GetCurrentProcess();
 
  279                                     s.Value = Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0);
 
  281             MakeStat(
"PeakProcessPaged", null, 
"MB", ContainerProcess,
 
  284                                     Process myprocess = Process.GetCurrentProcess();
 
  286                                     s.Value = Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0);
 
  288             MakeStat(
"PeakProcessVirtual", null, 
"MB", ContainerProcess,
 
  291                                     Process myprocess = Process.GetCurrentProcess();
 
  293                                     s.Value = Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0);
 
  301         private delegate 
double PerfCounterNextValue();
 
  303         private void GetNextValue(Stat stat, PerfCounterControl perfControl)
 
  305             if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
 
  307                 if (perfControl != null && perfControl.perfCounter != null)
 
  311                         stat.Value = Math.Round(perfControl.perfCounter.NextValue(), 3);
 
  315                         m_log.ErrorFormat(
"{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
 
  318                     perfControl.lastFetch = Util.EnvironmentTickCount();
 
  325         private delegate 
double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
 
  326         private void LookupNic(Stat stat, GetIPv4StatValue getter, 
double factor)
 
  330                                   (network) => network.Name == stat.Description);
 
  333                 foreach (NetworkInterface nic 
in nics)
 
  335                     IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
 
  336                     if (intrStats != null)
 
  338                         double newVal = Math.Round(getter(intrStats) / factor, 3);
 
  347                 m_log.ErrorFormat(
"{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
 
  377             StringBuilder sb = 
new StringBuilder();
 
  379             return sb.ToString();
 
FireAndForgetMethod
The method used by Util.FireAndForget for asynchronously firing events 
OpenMetaverse.StructuredData.OSDMap OSDMap
Holds individual statistic details 
ServerStatsAggregator(string shortName, string name, string description, string unitName, string category, string container)
override OSDMap ToOSDMap()
StatVerbosity
Verbosity of stat. 
System.Collections.IEnumerable IEnumerable
override string ToConsoleString()
void RegisterServerStats()
MeasuresOfInterest
Measures of interest for this stat. 
void Initialise(IConfigSource source)