From 0d2fd0d914581f755661455b8db2b9e399154632 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 17 Jun 2013 22:39:00 +0100 Subject: Make general server stats available on the robust console as well as the simulator console This means the "show stats" command is now active on the robust console. --- .../Framework/Monitoring/ServerStatsCollector.cs | 309 +++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 OpenSim/Framework/Monitoring/ServerStatsCollector.cs (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs new file mode 100644 index 0000000..80d0a89 --- /dev/null +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -0,0 +1,309 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading; +using log4net; +using Nini.Config; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; + +namespace OpenSim.Framework.Monitoring +{ + public class ServerStatsCollector + { + private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private readonly string LogHeader = "[SERVER STATS]"; + + public bool Enabled = false; + private static Dictionary RegisteredStats = new Dictionary(); + + public readonly string CategoryServer = "server"; + + public readonly string ContainerProcessor = "processor"; + public readonly string ContainerMemory = "memory"; + public readonly string ContainerNetwork = "network"; + public readonly string ContainerProcess = "process"; + + public string NetworkInterfaceTypes = "Ethernet"; + + readonly int performanceCounterSampleInterval = 500; +// int lastperformanceCounterSampleTime = 0; + + private class PerfCounterControl + { + public PerformanceCounter perfCounter; + public int lastFetch; + public string name; + public PerfCounterControl(PerformanceCounter pPc) + : this(pPc, String.Empty) + { + } + public PerfCounterControl(PerformanceCounter pPc, string pName) + { + perfCounter = pPc; + lastFetch = 0; + name = pName; + } + } + + PerfCounterControl processorPercentPerfCounter = null; + + // IRegionModuleBase.Initialize + public void Initialise(IConfigSource source) + { + IConfig cfg = source.Configs["Monitoring"]; + + if (cfg != null) + Enabled = cfg.GetBoolean("ServerStatsEnabled", true); + + if (Enabled) + { + NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet"); + } + } + + public void Start() + { + if (RegisteredStats.Count == 0) + RegisterServerStats(); + } + + public void Close() + { + if (RegisteredStats.Count > 0) + { + foreach (Stat stat in RegisteredStats.Values) + { + StatsManager.DeregisterStat(stat); + stat.Dispose(); + } + RegisteredStats.Clear(); + } + } + + private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act) + { + string desc = pDesc; + if (desc == null) + desc = pName; + Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); + StatsManager.RegisterStat(stat); + RegisteredStats.Add(pName, stat); + } + + public void RegisterServerStats() + { +// lastperformanceCounterSampleTime = Util.EnvironmentTickCount(); + PerformanceCounter tempPC; + Stat tempStat; + string tempName; + + try + { + tempName = "CPUPercent"; + tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total"); + 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. + tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, + StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, + StatVerbosity.Info); + StatsManager.RegisterStat(tempStat); + RegisteredStats.Add(tempName, tempStat); + + MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); + + MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); + + MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); + + MakeStat("Threads", null, "threads", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); + } + catch (Exception e) + { + m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); + } + + try + { + List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); + + IEnumerable nics = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface nic in nics) + { + if (nic.OperationalStatus != OperationalStatus.Up) + continue; + + string nicInterfaceType = nic.NetworkInterfaceType.ToString(); + if (!okInterfaceTypes.Contains(nicInterfaceType)) + { + m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.", + LogHeader, nic.Name, nicInterfaceType); + m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}", + LogHeader, NetworkInterfaceTypes); + continue; + } + + if (nic.Supports(NetworkInterfaceComponent.IPv4)) + { + IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); + if (nicStats != null) + { + MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork, + (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); + MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork, + (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); + MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork, + (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); + } + } + // TODO: add IPv6 (it may actually happen someday) + } + } + catch (Exception e) + { + m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); + } + + MakeStat("ProcessMemory", null, "MB", ContainerMemory, + (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); + MakeStat("ObjectMemory", null, "MB", ContainerMemory, + (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); + MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); + MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); + } + + // Notes on performance counters: + // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx + // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c + // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters + private delegate double PerfCounterNextValue(); + private void GetNextValue(Stat stat, PerfCounterControl perfControl) + { + GetNextValue(stat, perfControl, 1.0); + } + private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor) + { + if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) + { + if (perfControl != null && perfControl.perfCounter != null) + { + try + { + // Kludge for factor to run double duty. If -1, subtract the value from one + if (factor == -1) + stat.Value = 1 - perfControl.perfCounter.NextValue(); + else + stat.Value = perfControl.perfCounter.NextValue() / factor; + } + catch (Exception e) + { + m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); + } + perfControl.lastFetch = Util.EnvironmentTickCount(); + } + } + } + + // Lookup the nic that goes with this stat and set the value by using a fetch action. + // Not sure about closure with delegates inside delegates. + private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); + private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) + { + // Get the one nic that has the name of this stat + IEnumerable nics = NetworkInterface.GetAllNetworkInterfaces().Where( + (network) => network.Name == stat.Description); + try + { + foreach (NetworkInterface nic in nics) + { + IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); + if (intrStats != null) + { + double newVal = Math.Round(getter(intrStats) / factor, 3); + stat.Value = newVal; + } + break; + } + } + catch + { + // There are times interfaces go away so we just won't update the stat for this + m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description); + } + } + } + + public class ServerStatsAggregator : Stat + { + public ServerStatsAggregator( + string shortName, + string name, + string description, + string unitName, + string category, + string container + ) + : base( + shortName, + name, + description, + unitName, + category, + container, + StatType.Push, + MeasuresOfInterest.None, + null, + StatVerbosity.Info) + { + } + public override string ToConsoleString() + { + StringBuilder sb = new StringBuilder(); + + return sb.ToString(); + } + + public override OSDMap ToOSDMap() + { + OSDMap ret = new OSDMap(); + + return ret; + } + } +} -- cgit v1.1 From 2c9bb0f9738534732e147c090fac43f3373af1bb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 17 Jun 2013 22:55:25 +0100 Subject: Add server stats for available builtin threadpool and iocp workers --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 80d0a89..fe74ef7 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -157,6 +157,22 @@ namespace OpenSim.Framework.Monitoring m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); } + MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerProcessor, + s => + { + int workerThreads, iocpThreads; + ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); + s.Value = workerThreads; + }); + + MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerProcessor, + s => + { + int workerThreads, iocpThreads; + ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); + s.Value = iocpThreads; + }); + try { List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); -- cgit v1.1 From 865d46ae1e0477f957ad674ed2a1a11ef85d885a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 17 Jun 2013 22:56:39 +0100 Subject: Drop server level stats to debug instead of info. This was the original intention with these stats, as I didn't believe they would be useful to ordinary users if everything is working as it should. Please amend if this is an issue. Just for now, levels actually have no impact on what is displayed via the "show stats" command. --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index fe74ef7..c601c17 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -116,7 +116,7 @@ namespace OpenSim.Framework.Monitoring string desc = pDesc; if (desc == null) desc = pName; - Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); + Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Debug); StatsManager.RegisterStat(stat); RegisteredStats.Add(pName, stat); } -- cgit v1.1 From a1e32b843745581f7296359427a59e988814106b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 18 Jun 2013 00:10:21 +0100 Subject: If SmartThreadPool is active, display statistical information about it in "show stats server" Also puts these and previous builtin threadpool stats in the "threadpool" stat container rather than "processor" --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index c601c17..0ab4b93 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -49,6 +49,7 @@ namespace OpenSim.Framework.Monitoring public readonly string CategoryServer = "server"; + public readonly string ContainerThreadpool = "threadpool"; public readonly string ContainerProcessor = "processor"; public readonly string ContainerMemory = "memory"; public readonly string ContainerNetwork = "network"; @@ -157,7 +158,7 @@ namespace OpenSim.Framework.Monitoring m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); } - MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerProcessor, + MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -165,7 +166,7 @@ namespace OpenSim.Framework.Monitoring s.Value = workerThreads; }); - MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerProcessor, + MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -173,6 +174,16 @@ namespace OpenSim.Framework.Monitoring s.Value = iocpThreads; }); + if (Util.FireAndForgetMethod != null && Util.GetSmartThreadPoolInfo() != null) + { + MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads); + MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads); + MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems); + MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads); + MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads); + MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks); + } + try { List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); -- cgit v1.1 From 84af1cab9ba991b2356f1025cab7f58433e2ec19 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 19 Jun 2013 20:48:12 +0100 Subject: Display existing statistic of how many http requests a server is making as server.network.HTTPRequestsMade in "show stats all" --- .../Framework/Monitoring/ServerStatsCollector.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 0ab4b93..07ca14b 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -114,10 +114,15 @@ namespace OpenSim.Framework.Monitoring private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act) { + MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None); + } + + private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act, MeasuresOfInterest moi) + { string desc = pDesc; if (desc == null) desc = pName; - Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Debug); + Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug); StatsManager.RegisterStat(stat); RegisteredStats.Add(pName, stat); } @@ -141,7 +146,7 @@ namespace OpenSim.Framework.Monitoring StatsManager.RegisterStat(tempStat); RegisteredStats.Add(tempName, tempStat); - MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, + MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, @@ -158,7 +163,7 @@ namespace OpenSim.Framework.Monitoring m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); } - MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, + MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -166,7 +171,7 @@ namespace OpenSim.Framework.Monitoring s.Value = workerThreads; }); - MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, + MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -184,6 +189,14 @@ namespace OpenSim.Framework.Monitoring MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks); } + MakeStat( + "HTTPRequestsMade", + "Number of outbound HTTP requests made", + "requests", + ContainerNetwork, + s => s.Value = WebUtil.RequestNumber, + MeasuresOfInterest.AverageChangeOverTime); + try { List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); -- cgit v1.1 From d97333255d45da686bb71d85ef492c5631c4dc31 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 20 Jun 2013 00:20:04 +0100 Subject: Fix minor bug where the check whether to display SmartThreadPool stats was accidentally != null rather than == FireAndForgetMethod.SmartThreadPool Due to another check this had no practical effect --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 07ca14b..5d1c270 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -179,7 +179,7 @@ namespace OpenSim.Framework.Monitoring s.Value = iocpThreads; }); - if (Util.FireAndForgetMethod != null && Util.GetSmartThreadPoolInfo() != null) + if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null) { MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads); MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads); -- cgit v1.1 From 5b1a9f84fdf4f9938180b403dd002b44e25c6efb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 20 Jun 2013 00:32:12 +0100 Subject: minor: Change "memory churn" terminology in statistics to "heap allocation rate" since this is more generally meaningful --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 5d1c270..b22da1d 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -242,10 +242,10 @@ namespace OpenSim.Framework.Monitoring (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); MakeStat("ObjectMemory", null, "MB", ContainerMemory, (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); - MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, - (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); - MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, - (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); + MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); + MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); } // Notes on performance counters: -- cgit v1.1 From 085a87060a2ccb4910305b7c5f5374d1cc779d1a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 20 Jun 2013 00:52:39 +0100 Subject: Change "ObjectMemory" stat to "HeapMemory" to align with other stat names. Also round this and ProcessMemory to three decimal places in common with other memory stats. I believe leaving out such minor info makes stats easier to read --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index b22da1d..ac0f0bc 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -239,9 +239,9 @@ namespace OpenSim.Framework.Monitoring } MakeStat("ProcessMemory", null, "MB", ContainerMemory, - (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); - MakeStat("ObjectMemory", null, "MB", ContainerMemory, - (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); + (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); }); + MakeStat("HeapMemory", null, "MB", ContainerMemory, + (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); }); MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory, (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, -- cgit v1.1 From 200dcee1b7fa799936aaf43a18a34bfbf8b94449 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 21 Jul 2014 22:51:11 +0100 Subject: Fix CPU processor use reporting on Mono. Despite the comments in the code, it appears that the issue where the .NET performance counter was wrongly idle time time on Mono was fixed in 2009. https://bugzilla.novell.com/show_bug.cgi?id=468625 Which means that the workaround is no longer necessary and produces bad results instead. --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index ac0f0bc..b4e0b16 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -141,7 +141,7 @@ namespace OpenSim.Framework.Monitoring 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. tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, - StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, + StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter); }, StatVerbosity.Info); StatsManager.RegisterStat(tempStat); RegisteredStats.Add(tempName, tempStat); @@ -253,28 +253,22 @@ namespace OpenSim.Framework.Monitoring // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters private delegate double PerfCounterNextValue(); + private void GetNextValue(Stat stat, PerfCounterControl perfControl) { - GetNextValue(stat, perfControl, 1.0); - } - private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor) - { if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) { if (perfControl != null && perfControl.perfCounter != null) { try { - // Kludge for factor to run double duty. If -1, subtract the value from one - if (factor == -1) - stat.Value = 1 - perfControl.perfCounter.NextValue(); - else - stat.Value = perfControl.perfCounter.NextValue() / factor; + stat.Value = perfControl.perfCounter.NextValue(); } catch (Exception e) { m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); } + perfControl.lastFetch = Util.EnvironmentTickCount(); } } -- cgit v1.1 From 3355bedaeb26b07b6b91c5de194991acaf2cdf36 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 21 Jul 2014 23:08:15 +0100 Subject: minor: Limit processor related stats to 3 decimal places instead of all the places. Easier to read and analyze, and probably still too much detail (1 dp would probably be fine) --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index b4e0b16..ff0fcd5 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -147,13 +147,13 @@ namespace OpenSim.Framework.Monitoring RegisteredStats.Add(tempName, tempStat); MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); + (s) => { s.Value = Math.Round(Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds, 3); }); MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); + (s) => { s.Value = Math.Round(Process.GetCurrentProcess().UserProcessorTime.TotalSeconds, 3); }); MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); + (s) => { s.Value = Math.Round(Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds, 3); }); MakeStat("Threads", null, "threads", ContainerProcessor, (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); @@ -262,7 +262,7 @@ namespace OpenSim.Framework.Monitoring { try { - stat.Value = perfControl.perfCounter.NextValue(); + stat.Value = Math.Round(perfControl.perfCounter.NextValue(), 3); } catch (Exception e) { -- cgit v1.1 From f1f935ed9543141cc5861a7204b6df85a7358ab4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 13 Aug 2014 19:53:42 +0100 Subject: Add 'server' stats information to pCampbot, as used elsewhere in OpenSimulator This adds the "show stats", "stats record", etc. commands and information on available Threadpool threads, etc. It also adds the Watchdog which logs warnings if time between executions is unexpectedly large. --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Framework/Monitoring/ServerStatsCollector.cs') diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index ff0fcd5..77315bb 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -82,6 +82,9 @@ namespace OpenSim.Framework.Monitoring // IRegionModuleBase.Initialize public void Initialise(IConfigSource source) { + if (source == null) + return; + IConfig cfg = source.Configs["Monitoring"]; if (cfg != null) -- cgit v1.1