From 31304c222df1e5a832afd0ebcf7d3ed403543e54 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 21:00:59 +0100 Subject: Make SceneManager.OnRegionsReadyStatusChange event available. This is fired when all regions are ready or when at least one region becomes not ready. Recently added EventManager.OnRegionReady becomes OnRegionReadyStatusChange to match OnLoginsEnabledStatusChange --- OpenSim/Framework/IScene.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 2c38e0f..87ec99e 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -71,6 +71,14 @@ namespace OpenSim.Framework /// bool LoginsEnabled { get; set; } + /// + /// Is this region ready for use? + /// + /// + /// This does not mean that logins are enabled, merely that they can be. + /// + bool Ready { get; set; } + float TimeDilation { get; } bool AllowScriptCrossings { get; } -- cgit v1.1 From a1e99642c19810f98084e77723df1e242d2c26d0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 22:29:40 +0100 Subject: Add experimental "OpenSim object memory churn" statistics to output of region console "show stats" command This aims to capture the amount of memory that OpenSim turns over whilst operating a region. This memory is not lost - apart from leaks it is reclaimed by the garbage collector. However, the more memory that gets turned over the more work the GC has to do to reclaim it. --- OpenSim/Framework/Statistics/BaseStatsCollector.cs | 20 ++++++++++++-------- OpenSim/Framework/Watchdog.cs | 3 +++ 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs index c9e57ce..28ce650 100644 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs @@ -44,14 +44,18 @@ namespace OpenSim.Framework.Statistics StringBuilder sb = new StringBuilder(Environment.NewLine); sb.Append("MEMORY STATISTICS"); sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "Allocated to OpenSim objects: {0} MB\n", - Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); - sb.Append( - string.Format( - "Process memory : {0} MB\n", - Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0))); + + sb.AppendFormat( + "Allocated to OpenSim objects: {0} MB\n", + Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); + + sb.AppendFormat( + "OpenSim object memory churn : {0} KB/s\n", + Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); + + sb.AppendFormat( + "Process memory : {0} MB\n", + Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); return sb.ToString(); } diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs index 8a74f53..54e3d1a 100644 --- a/OpenSim/Framework/Watchdog.cs +++ b/OpenSim/Framework/Watchdog.cs @@ -325,6 +325,9 @@ namespace OpenSim.Framework callback(callbackInfo); } + if (MemoryWatchdog.Enabled) + MemoryWatchdog.Update(); + m_watchdogTimer.Start(); } } -- cgit v1.1 From 22aa436648e7cdddefa5fb7263c0fdec294733b5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 22:33:24 +0100 Subject: Correct churn stat from MB/s from KB/s --- OpenSim/Framework/Statistics/BaseStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs index 28ce650..1fe086c 100644 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs @@ -50,7 +50,7 @@ namespace OpenSim.Framework.Statistics Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); sb.AppendFormat( - "OpenSim object memory churn : {0} KB/s\n", + "OpenSim object memory churn : {0} MB/s\n", Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); sb.AppendFormat( -- cgit v1.1 From 227126adb784ed70739f42aec0072bdd8f06de9a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 22:38:28 +0100 Subject: Add MemoryWatchdog class missing from git master a1e9964 --- OpenSim/Framework/MemoryWatchdog.cs | 129 ++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 OpenSim/Framework/MemoryWatchdog.cs (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/MemoryWatchdog.cs b/OpenSim/Framework/MemoryWatchdog.cs new file mode 100644 index 0000000..1e93077 --- /dev/null +++ b/OpenSim/Framework/MemoryWatchdog.cs @@ -0,0 +1,129 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Threading; +using log4net; + +namespace OpenSim.Framework +{ + /// + /// Experimental watchdog for memory usage. + /// + public static class MemoryWatchdog + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Is this watchdog active? + /// + public static bool Enabled + { + get { return m_enabled; } + set + { +// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); + + if (value && !m_enabled) + UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); + + m_enabled = value; + } + } + private static bool m_enabled; + + /// + /// Average memory churn in bytes per millisecond. + /// + public static double AverageMemoryChurn + { + get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } + } + + /// + /// Maximum number of statistical samples. + /// + /// + /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from + /// the main Watchdog. + /// + private static int m_maxSamples = 24; + + /// + /// Time when the watchdog was last updated. + /// + private static int m_lastUpdateTick; + + /// + /// Memory used at time of last watchdog update. + /// + private static long m_lastUpdateMemory; + + /// + /// Memory churn rate per millisecond. + /// + private static double m_churnRatePerMillisecond; + + /// + /// Historical samples for calculating moving average. + /// + private static Queue m_samples = new Queue(m_maxSamples); + + public static void Update() + { + int now = Util.EnvironmentTickCount(); + long memoryNow = GC.GetTotalMemory(false); + long memoryDiff = memoryNow - m_lastUpdateMemory; + + if (memoryDiff >= 0) + { + if (m_samples.Count >= m_maxSamples) + m_samples.Dequeue(); + + double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); + + // This should never happen since it's not useful for updates to occur with no time elapsed, but + // protect ourselves from a divide-by-zero just in case. + if (elapsed == 0) + return; + + m_samples.Enqueue(memoryDiff / (double)elapsed); + } + + UpdateLastRecord(memoryNow, now); + } + + private static void UpdateLastRecord(long memoryNow, int timeNow) + { + m_lastUpdateMemory = memoryNow; + m_lastUpdateTick = timeNow; + } + } +} \ No newline at end of file -- cgit v1.1 From 35efa88c26d249d315837fdca0faf643511e1a4e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 23:11:50 +0100 Subject: Rename OpenSim.Framework.Statistics to OpenSim.Framework.Monitoring. This better reflects the long-term purpose of that project and matches Monitoring modules. --- .../Framework/Monitoring/AssetStatsCollector.cs | 104 +++++ OpenSim/Framework/Monitoring/BaseStatsCollector.cs | 67 +++ .../Monitoring/Interfaces/IPullStatsProvider.cs | 41 ++ .../Monitoring/Interfaces/IStatsCollector.cs | 49 +++ .../Framework/Monitoring/SimExtraStatsCollector.cs | 463 ++++++++++++++++++++ OpenSim/Framework/Monitoring/StatsManager.cs | 65 +++ OpenSim/Framework/Monitoring/UserStatsCollector.cs | 92 ++++ OpenSim/Framework/Servers/BaseOpenSimServer.cs | 2 +- .../Framework/Statistics/AssetStatsCollector.cs | 104 ----- OpenSim/Framework/Statistics/BaseStatsCollector.cs | 68 --- .../Statistics/Interfaces/IPullStatsProvider.cs | 41 -- .../Statistics/Interfaces/IStatsCollector.cs | 49 --- .../Framework/Statistics/SimExtraStatsCollector.cs | 464 --------------------- OpenSim/Framework/Statistics/StatsManager.cs | 65 --- OpenSim/Framework/Statistics/UserStatsCollector.cs | 92 ---- 15 files changed, 882 insertions(+), 884 deletions(-) create mode 100644 OpenSim/Framework/Monitoring/AssetStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/BaseStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs create mode 100644 OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/StatsManager.cs create mode 100644 OpenSim/Framework/Monitoring/UserStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/AssetStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/BaseStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs delete mode 100644 OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/SimExtraStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/StatsManager.cs delete mode 100644 OpenSim/Framework/Statistics/UserStatsCollector.cs (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/Monitoring/AssetStatsCollector.cs b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs new file mode 100644 index 0000000..2a4d45b --- /dev/null +++ b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs @@ -0,0 +1,104 @@ +/* + * 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.Timers; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Asset service statistics collection + /// + public class AssetStatsCollector : BaseStatsCollector + { + private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); + private DateTime startTime = DateTime.Now; + + private long assetRequestsToday; + private long assetRequestsNotFoundToday; + private long assetRequestsYesterday; + private long assetRequestsNotFoundYesterday; + + public long AssetRequestsToday { get { return assetRequestsToday; } } + public long AssetRequestsNotFoundToday { get { return assetRequestsNotFoundToday; } } + public long AssetRequestsYesterday { get { return assetRequestsYesterday; } } + public long AssetRequestsNotFoundYesterday { get { return assetRequestsNotFoundYesterday; } } + + public AssetStatsCollector() + { + ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); + ageStatsTimer.Enabled = true; + } + + private void OnAgeing(object source, ElapsedEventArgs e) + { + assetRequestsYesterday = assetRequestsToday; + + // There is a possibility that an asset request could occur between the execution of these + // two statements. But we're better off without the synchronization overhead. + assetRequestsToday = 0; + + assetRequestsNotFoundYesterday = assetRequestsNotFoundToday; + assetRequestsNotFoundToday = 0; + } + + /// + /// Record that an asset request failed to find an asset + /// + public void AddNotFoundRequest() + { + assetRequestsNotFoundToday++; + } + + /// + /// Record that a request was made to the asset server + /// + public void AddRequest() + { + assetRequestsToday++; + } + + /// + /// Report back collected statistical information. + /// + /// + override public string Report() + { + double elapsedHours = (DateTime.Now - startTime).TotalHours; + if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero + + long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours); + long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0); + + return string.Format( +@"Asset requests today : {0} ({1} per hour) of which {2} were not found +Asset requests yesterday : {3} ({4} per hour) of which {5} were not found", + AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, + AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); + } + } +} diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs new file mode 100644 index 0000000..57a63ef --- /dev/null +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs @@ -0,0 +1,67 @@ +/* + * 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.Diagnostics; +using System.Text; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Statistics which all collectors are interested in reporting + /// + public class BaseStatsCollector : IStatsCollector + { + public virtual string Report() + { + StringBuilder sb = new StringBuilder(Environment.NewLine); + sb.Append("MEMORY STATISTICS"); + sb.Append(Environment.NewLine); + + sb.AppendFormat( + "Allocated to OpenSim objects: {0} MB\n", + Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); + + sb.AppendFormat( + "OpenSim object memory churn : {0} MB/s\n", + Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); + + sb.AppendFormat( + "Process memory : {0} MB\n", + Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); + + return sb.ToString(); + } + + public virtual string XReport(string uptime, string version) + { + return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; + } + } +} diff --git a/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs new file mode 100644 index 0000000..86a6620 --- /dev/null +++ b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs @@ -0,0 +1,41 @@ +/* + * 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. + */ + +namespace OpenSim.Framework.Monitoring.Interfaces +{ + /// + /// Implemented by objects which allow statistical information to be pulled from them. + /// + public interface IPullStatsProvider + { + /// + /// Provide statistical information. Only temporary one long string. + /// + /// + string GetStats(); + } +} diff --git a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs new file mode 100644 index 0000000..99f75e3 --- /dev/null +++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs @@ -0,0 +1,49 @@ +/* + * 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. + */ + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Implemented by classes which collect up non-viewer statistical information + /// + public interface IStatsCollector + { + /// + /// Report back collected statistical information. + /// + /// + string Report(); + + /// + /// Report back collected statistical information in json + /// + /// + /// A + /// + string XReport(string uptime, string version); + } +} diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs new file mode 100644 index 0000000..cdd7cc7 --- /dev/null +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -0,0 +1,463 @@ +/* + * 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.Text; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework.Monitoring.Interfaces; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane + /// + public class SimExtraStatsCollector : BaseStatsCollector + { + private long abnormalClientThreadTerminations; + +// private long assetsInCache; +// private long texturesInCache; +// private long assetCacheMemoryUsage; +// private long textureCacheMemoryUsage; +// private TimeSpan assetRequestTimeAfterCacheMiss; +// private long blockedMissingTextureRequests; + +// private long assetServiceRequestFailures; +// private long inventoryServiceRetrievalFailures; + + private volatile float timeDilation; + private volatile float simFps; + private volatile float physicsFps; + private volatile float agentUpdates; + private volatile float rootAgents; + private volatile float childAgents; + private volatile float totalPrims; + private volatile float activePrims; + private volatile float totalFrameTime; + private volatile float netFrameTime; + private volatile float physicsFrameTime; + private volatile float otherFrameTime; + private volatile float imageFrameTime; + private volatile float inPacketsPerSecond; + private volatile float outPacketsPerSecond; + private volatile float unackedBytes; + private volatile float agentFrameTime; + private volatile float pendingDownloads; + private volatile float pendingUploads; + private volatile float activeScripts; + private volatile float scriptLinesPerSecond; + + /// + /// Number of times that a client thread terminated because of an exception + /// + public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } } + +// /// +// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the +// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these +// /// haven't yet been implemented... +// /// +// public long AssetsInCache { get { return assetsInCache; } } +// +// /// +// /// Currently unused +// /// +// public long TexturesInCache { get { return texturesInCache; } } +// +// /// +// /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit +// /// +// public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } +// +// /// +// /// Currently unused +// /// +// public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } + + public float TimeDilation { get { return timeDilation; } } + public float SimFps { get { return simFps; } } + public float PhysicsFps { get { return physicsFps; } } + public float AgentUpdates { get { return agentUpdates; } } + public float RootAgents { get { return rootAgents; } } + public float ChildAgents { get { return childAgents; } } + public float TotalPrims { get { return totalPrims; } } + public float ActivePrims { get { return activePrims; } } + public float TotalFrameTime { get { return totalFrameTime; } } + public float NetFrameTime { get { return netFrameTime; } } + public float PhysicsFrameTime { get { return physicsFrameTime; } } + public float OtherFrameTime { get { return otherFrameTime; } } + public float ImageFrameTime { get { return imageFrameTime; } } + public float InPacketsPerSecond { get { return inPacketsPerSecond; } } + public float OutPacketsPerSecond { get { return outPacketsPerSecond; } } + public float UnackedBytes { get { return unackedBytes; } } + public float AgentFrameTime { get { return agentFrameTime; } } + public float PendingDownloads { get { return pendingDownloads; } } + public float PendingUploads { get { return pendingUploads; } } + public float ActiveScripts { get { return activeScripts; } } + public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } + +// /// +// /// This is the time it took for the last asset request made in response to a cache miss. +// /// +// public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } } +// +// /// +// /// Number of persistent requests for missing textures we have started blocking from clients. To some extent +// /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either +// /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics +// /// driver bugs on clients (though this seems less likely). +// /// +// public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } } +// +// /// +// /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as +// /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted +// /// as a failure +// /// +// public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } } + + /// + /// Number of known failures to retrieve avatar inventory from the inventory service. This does not + /// cover situations where the inventory service accepts the request but never returns any data, since + /// we do not yet timeout this situation. + /// + /// Commented out because we do not cache inventory at this point +// public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } } + + /// + /// Retrieve the total frame time (in ms) of the last frame + /// + //public float TotalFrameTime { get { return totalFrameTime; } } + + /// + /// Retrieve the physics update component (in ms) of the last frame + /// + //public float PhysicsFrameTime { get { return physicsFrameTime; } } + + /// + /// Retain a dictionary of all packet queues stats reporters + /// + private IDictionary packetQueueStatsCollectors + = new Dictionary(); + + public void AddAbnormalClientThreadTermination() + { + abnormalClientThreadTerminations++; + } + +// public void AddAsset(AssetBase asset) +// { +// assetsInCache++; +// //assetCacheMemoryUsage += asset.Data.Length; +// } +// +// public void RemoveAsset(UUID uuid) +// { +// assetsInCache--; +// } +// +// public void AddTexture(AssetBase image) +// { +// if (image.Data != null) +// { +// texturesInCache++; +// +// // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates +// textureCacheMemoryUsage += image.Data.Length; +// } +// } +// +// /// +// /// Signal that the asset cache has been cleared. +// /// +// public void ClearAssetCacheStatistics() +// { +// assetsInCache = 0; +// assetCacheMemoryUsage = 0; +// texturesInCache = 0; +// textureCacheMemoryUsage = 0; +// } +// +// public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) +// { +// assetRequestTimeAfterCacheMiss = ts; +// } +// +// public void AddBlockedMissingTextureRequest() +// { +// blockedMissingTextureRequests++; +// } +// +// public void AddAssetServiceRequestFailure() +// { +// assetServiceRequestFailures++; +// } + +// public void AddInventoryServiceRetrievalFailure() +// { +// inventoryServiceRetrievalFailures++; +// } + + /// + /// Register as a packet queue stats provider + /// + /// An agent UUID + /// + public void RegisterPacketQueueStatsProvider(UUID uuid, IPullStatsProvider provider) + { + lock (packetQueueStatsCollectors) + { + // FIXME: If the region service is providing more than one region, then the child and root agent + // queues are wrongly replacing each other here. + packetQueueStatsCollectors[uuid] = new PacketQueueStatsCollector(provider); + } + } + + /// + /// Deregister a packet queue stats provider + /// + /// An agent UUID + public void DeregisterPacketQueueStatsProvider(UUID uuid) + { + lock (packetQueueStatsCollectors) + { + packetQueueStatsCollectors.Remove(uuid); + } + } + + /// + /// This is the method on which the classic sim stats reporter (which collects stats for + /// client purposes) sends information to listeners. + /// + /// + public void ReceiveClassicSimStatsPacket(SimStats stats) + { + // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original + // SimStatsPacket that was being used). + timeDilation = stats.StatsBlock[0].StatValue; + simFps = stats.StatsBlock[1].StatValue; + physicsFps = stats.StatsBlock[2].StatValue; + agentUpdates = stats.StatsBlock[3].StatValue; + rootAgents = stats.StatsBlock[4].StatValue; + childAgents = stats.StatsBlock[5].StatValue; + totalPrims = stats.StatsBlock[6].StatValue; + activePrims = stats.StatsBlock[7].StatValue; + totalFrameTime = stats.StatsBlock[8].StatValue; + netFrameTime = stats.StatsBlock[9].StatValue; + physicsFrameTime = stats.StatsBlock[10].StatValue; + otherFrameTime = stats.StatsBlock[11].StatValue; + imageFrameTime = stats.StatsBlock[12].StatValue; + inPacketsPerSecond = stats.StatsBlock[13].StatValue; + outPacketsPerSecond = stats.StatsBlock[14].StatValue; + unackedBytes = stats.StatsBlock[15].StatValue; + agentFrameTime = stats.StatsBlock[16].StatValue; + pendingDownloads = stats.StatsBlock[17].StatValue; + pendingUploads = stats.StatsBlock[18].StatValue; + activeScripts = stats.StatsBlock[19].StatValue; + scriptLinesPerSecond = stats.StatsBlock[20].StatValue; + } + + /// + /// Report back collected statistical information. + /// + /// + public override string Report() + { + StringBuilder sb = new StringBuilder(Environment.NewLine); +// sb.Append("ASSET STATISTICS"); +// sb.Append(Environment.NewLine); + + /* + sb.Append( + string.Format( +@"Asset cache contains {0,6} non-texture assets using {1,10} K +Texture cache contains {2,6} texture assets using {3,10} K +Latest asset request time after cache miss: {4}s +Blocked client requests for missing textures: {5} +Asset service request failures: {6}"+ Environment.NewLine, + AssetsInCache, Math.Round(AssetCacheMemoryUsage / 1024.0), + TexturesInCache, Math.Round(TextureCacheMemoryUsage / 1024.0), + assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, + BlockedMissingTextureRequests, + AssetServiceRequestFailures)); + */ + + /* + sb.Append( + string.Format( +@"Asset cache contains {0,6} assets +Latest asset request time after cache miss: {1}s +Blocked client requests for missing textures: {2} +Asset service request failures: {3}" + Environment.NewLine, + AssetsInCache, + assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, + BlockedMissingTextureRequests, + AssetServiceRequestFailures)); + */ + + sb.Append(Environment.NewLine); + sb.Append("CONNECTION STATISTICS"); + sb.Append(Environment.NewLine); + sb.Append( + string.Format( + "Abnormal client thread terminations: {0}" + Environment.NewLine, + abnormalClientThreadTerminations)); + +// sb.Append(Environment.NewLine); +// sb.Append("INVENTORY STATISTICS"); +// sb.Append(Environment.NewLine); +// sb.Append( +// string.Format( +// "Initial inventory caching failures: {0}" + Environment.NewLine, +// InventoryServiceRetrievalFailures)); + + sb.Append(Environment.NewLine); + sb.Append("FRAME STATISTICS"); + sb.Append(Environment.NewLine); + sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS"); + sb.Append(Environment.NewLine); + sb.Append( + string.Format( + "{0,6:0.00} {1,6:0} {2,6:0.0} {3,6:0.0} {4,6:0} {5,6:0} {6,6:0} {7,6:0} {8,6:0} {9,6:0}", + timeDilation, simFps, physicsFps, agentUpdates, rootAgents, + childAgents, totalPrims, activePrims, activeScripts, scriptLinesPerSecond)); + + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + // There is no script frame time currently because we don't yet collect it + sb.Append("PktsIn PktOut PendDl PendUl UnackB TotlFt NetFt PhysFt OthrFt AgntFt ImgsFt"); + sb.Append(Environment.NewLine); + sb.Append( + string.Format( + "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", + inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, + netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); + sb.Append(Environment.NewLine); + + /* + sb.Append(Environment.NewLine); + sb.Append("PACKET QUEUE STATISTICS"); + sb.Append(Environment.NewLine); + sb.Append("Agent UUID "); + sb.Append( + string.Format( + " {0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", + "Send", "In", "Out", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset")); + sb.Append(Environment.NewLine); + + foreach (UUID key in packetQueueStatsCollectors.Keys) + { + sb.Append(string.Format("{0}: ", key)); + sb.Append(packetQueueStatsCollectors[key].Report()); + sb.Append(Environment.NewLine); + } + */ + + sb.Append(base.Report()); + + return sb.ToString(); + } + + /// + /// Report back collected statistical information as json serialization. + /// + /// + public override string XReport(string uptime, string version) + { + OSDMap args = new OSDMap(30); +// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); +// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", +// assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0)); +// args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}", +// BlockedMissingTextureRequests)); +// args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}", +// AssetServiceRequestFailures)); +// args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}", +// abnormalClientThreadTerminations)); +// args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}", +// InventoryServiceRetrievalFailures)); + args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", timeDilation)); + args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", simFps)); + args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", physicsFps)); + args["AgntUp"] = OSD.FromString (String.Format ("{0:0.##}", agentUpdates)); + args["RootAg"] = OSD.FromString (String.Format ("{0:0.##}", rootAgents)); + args["ChldAg"] = OSD.FromString (String.Format ("{0:0.##}", childAgents)); + args["Prims"] = OSD.FromString (String.Format ("{0:0.##}", totalPrims)); + args["AtvPrm"] = OSD.FromString (String.Format ("{0:0.##}", activePrims)); + args["AtvScr"] = OSD.FromString (String.Format ("{0:0.##}", activeScripts)); + args["ScrLPS"] = OSD.FromString (String.Format ("{0:0.##}", scriptLinesPerSecond)); + args["PktsIn"] = OSD.FromString (String.Format ("{0:0.##}", inPacketsPerSecond)); + args["PktOut"] = OSD.FromString (String.Format ("{0:0.##}", outPacketsPerSecond)); + args["PendDl"] = OSD.FromString (String.Format ("{0:0.##}", pendingDownloads)); + args["PendUl"] = OSD.FromString (String.Format ("{0:0.##}", pendingUploads)); + args["UnackB"] = OSD.FromString (String.Format ("{0:0.##}", unackedBytes)); + args["TotlFt"] = OSD.FromString (String.Format ("{0:0.##}", totalFrameTime)); + args["NetFt"] = OSD.FromString (String.Format ("{0:0.##}", netFrameTime)); + args["PhysFt"] = OSD.FromString (String.Format ("{0:0.##}", physicsFrameTime)); + args["OthrFt"] = OSD.FromString (String.Format ("{0:0.##}", otherFrameTime)); + args["AgntFt"] = OSD.FromString (String.Format ("{0:0.##}", agentFrameTime)); + args["ImgsFt"] = OSD.FromString (String.Format ("{0:0.##}", imageFrameTime)); + args["Memory"] = OSD.FromString (base.XReport (uptime, version)); + args["Uptime"] = OSD.FromString (uptime); + args["Version"] = OSD.FromString (version); + + string strBuffer = ""; + strBuffer = OSDParser.SerializeJsonString(args); + + return strBuffer; + } + } + + /// + /// Pull packet queue stats from packet queues and report + /// + public class PacketQueueStatsCollector : IStatsCollector + { + private IPullStatsProvider m_statsProvider; + + public PacketQueueStatsCollector(IPullStatsProvider provider) + { + m_statsProvider = provider; + } + + /// + /// Report back collected statistical information. + /// + /// + public string Report() + { + return m_statsProvider.GetStats(); + } + + public string XReport(string uptime, string version) + { + return ""; + } + } +} diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs new file mode 100644 index 0000000..d78fa6a --- /dev/null +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -0,0 +1,65 @@ +/* + * 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. + */ + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Singleton used to provide access to statistics reporters + /// + public class StatsManager + { + private static AssetStatsCollector assetStats; + private static UserStatsCollector userStats; + private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); + + public static AssetStatsCollector AssetStats { get { return assetStats; } } + public static UserStatsCollector UserStats { get { return userStats; } } + public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } + + /// + /// Start collecting statistics related to assets. + /// Should only be called once. + /// + public static AssetStatsCollector StartCollectingAssetStats() + { + assetStats = new AssetStatsCollector(); + + return assetStats; + } + + /// + /// Start collecting statistics related to users. + /// Should only be called once. + /// + public static UserStatsCollector StartCollectingUserStats() + { + userStats = new UserStatsCollector(); + + return userStats; + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/UserStatsCollector.cs b/OpenSim/Framework/Monitoring/UserStatsCollector.cs new file mode 100644 index 0000000..e89c8e6 --- /dev/null +++ b/OpenSim/Framework/Monitoring/UserStatsCollector.cs @@ -0,0 +1,92 @@ +/* + * 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.Timers; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Collects user service statistics + /// + public class UserStatsCollector : BaseStatsCollector + { + private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); + + private int successfulLoginsToday; + public int SuccessfulLoginsToday { get { return successfulLoginsToday; } } + + private int successfulLoginsYesterday; + public int SuccessfulLoginsYesterday { get { return successfulLoginsYesterday; } } + + private int successfulLogins; + public int SuccessfulLogins { get { return successfulLogins; } } + + private int logouts; + public int Logouts { get { return logouts; } } + + public UserStatsCollector() + { + ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); + ageStatsTimer.Enabled = true; + } + + private void OnAgeing(object source, ElapsedEventArgs e) + { + successfulLoginsYesterday = successfulLoginsToday; + + // There is a possibility that an asset request could occur between the execution of these + // two statements. But we're better off without the synchronization overhead. + successfulLoginsToday = 0; + } + + /// + /// Record a successful login + /// + public void AddSuccessfulLogin() + { + successfulLogins++; + successfulLoginsToday++; + } + + public void AddLogout() + { + logouts++; + } + + /// + /// Report back collected statistical information. + /// + /// + override public string Report() + { + return string.Format( +@"Successful logins total : {0}, today : {1}, yesterday : {2} + Logouts total : {3}", + SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); + } + } +} diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 14d8b0c..ab8d95a 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -42,7 +42,7 @@ using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using Timer=System.Timers.Timer; using OpenMetaverse; diff --git a/OpenSim/Framework/Statistics/AssetStatsCollector.cs b/OpenSim/Framework/Statistics/AssetStatsCollector.cs deleted file mode 100644 index 7082ef3..0000000 --- a/OpenSim/Framework/Statistics/AssetStatsCollector.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.Timers; - -namespace OpenSim.Framework.Statistics -{ - /// - /// Asset service statistics collection - /// - public class AssetStatsCollector : BaseStatsCollector - { - private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); - private DateTime startTime = DateTime.Now; - - private long assetRequestsToday; - private long assetRequestsNotFoundToday; - private long assetRequestsYesterday; - private long assetRequestsNotFoundYesterday; - - public long AssetRequestsToday { get { return assetRequestsToday; } } - public long AssetRequestsNotFoundToday { get { return assetRequestsNotFoundToday; } } - public long AssetRequestsYesterday { get { return assetRequestsYesterday; } } - public long AssetRequestsNotFoundYesterday { get { return assetRequestsNotFoundYesterday; } } - - public AssetStatsCollector() - { - ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); - ageStatsTimer.Enabled = true; - } - - private void OnAgeing(object source, ElapsedEventArgs e) - { - assetRequestsYesterday = assetRequestsToday; - - // There is a possibility that an asset request could occur between the execution of these - // two statements. But we're better off without the synchronization overhead. - assetRequestsToday = 0; - - assetRequestsNotFoundYesterday = assetRequestsNotFoundToday; - assetRequestsNotFoundToday = 0; - } - - /// - /// Record that an asset request failed to find an asset - /// - public void AddNotFoundRequest() - { - assetRequestsNotFoundToday++; - } - - /// - /// Record that a request was made to the asset server - /// - public void AddRequest() - { - assetRequestsToday++; - } - - /// - /// Report back collected statistical information. - /// - /// - override public string Report() - { - double elapsedHours = (DateTime.Now - startTime).TotalHours; - if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero - - long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours); - long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0); - - return string.Format( -@"Asset requests today : {0} ({1} per hour) of which {2} were not found -Asset requests yesterday : {3} ({4} per hour) of which {5} were not found", - AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, - AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); - } - } -} diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs deleted file mode 100644 index 1fe086c..0000000 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.Diagnostics; -using System.Text; -using OpenMetaverse; -using OpenMetaverse.StructuredData; - - -namespace OpenSim.Framework.Statistics -{ - /// - /// Statistics which all collectors are interested in reporting - /// - public class BaseStatsCollector : IStatsCollector - { - public virtual string Report() - { - StringBuilder sb = new StringBuilder(Environment.NewLine); - sb.Append("MEMORY STATISTICS"); - sb.Append(Environment.NewLine); - - sb.AppendFormat( - "Allocated to OpenSim objects: {0} MB\n", - Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); - - sb.AppendFormat( - "OpenSim object memory churn : {0} MB/s\n", - Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); - - sb.AppendFormat( - "Process memory : {0} MB\n", - Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); - - return sb.ToString(); - } - - public virtual string XReport(string uptime, string version) - { - return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; - } - } -} diff --git a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs b/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs deleted file mode 100644 index 430e580..0000000 --- a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -namespace OpenSim.Framework.Statistics.Interfaces -{ - /// - /// Implemented by objects which allow statistical information to be pulled from them. - /// - public interface IPullStatsProvider - { - /// - /// Provide statistical information. Only temporary one long string. - /// - /// - string GetStats(); - } -} diff --git a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs deleted file mode 100644 index 477bbb3..0000000 --- a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -namespace OpenSim.Framework.Statistics -{ - /// - /// Implemented by classes which collect up non-viewer statistical information - /// - public interface IStatsCollector - { - /// - /// Report back collected statistical information. - /// - /// - string Report(); - - /// - /// Report back collected statistical information in json - /// - /// - /// A - /// - string XReport(string uptime, string version); - } -} diff --git a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs b/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs deleted file mode 100644 index a506e3b..0000000 --- a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs +++ /dev/null @@ -1,464 +0,0 @@ -/* - * 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.Text; - -using OpenMetaverse; -using OpenSim.Framework.Statistics.Interfaces; -using OpenMetaverse.StructuredData; - -namespace OpenSim.Framework.Statistics -{ - /// - /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane - /// - public class SimExtraStatsCollector : BaseStatsCollector - { - private long abnormalClientThreadTerminations; - -// private long assetsInCache; -// private long texturesInCache; -// private long assetCacheMemoryUsage; -// private long textureCacheMemoryUsage; -// private TimeSpan assetRequestTimeAfterCacheMiss; -// private long blockedMissingTextureRequests; - -// private long assetServiceRequestFailures; -// private long inventoryServiceRetrievalFailures; - - private volatile float timeDilation; - private volatile float simFps; - private volatile float physicsFps; - private volatile float agentUpdates; - private volatile float rootAgents; - private volatile float childAgents; - private volatile float totalPrims; - private volatile float activePrims; - private volatile float totalFrameTime; - private volatile float netFrameTime; - private volatile float physicsFrameTime; - private volatile float otherFrameTime; - private volatile float imageFrameTime; - private volatile float inPacketsPerSecond; - private volatile float outPacketsPerSecond; - private volatile float unackedBytes; - private volatile float agentFrameTime; - private volatile float pendingDownloads; - private volatile float pendingUploads; - private volatile float activeScripts; - private volatile float scriptLinesPerSecond; - - /// - /// Number of times that a client thread terminated because of an exception - /// - public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } } - -// /// -// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the -// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these -// /// haven't yet been implemented... -// /// -// public long AssetsInCache { get { return assetsInCache; } } -// -// /// -// /// Currently unused -// /// -// public long TexturesInCache { get { return texturesInCache; } } -// -// /// -// /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit -// /// -// public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } -// -// /// -// /// Currently unused -// /// -// public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } - - public float TimeDilation { get { return timeDilation; } } - public float SimFps { get { return simFps; } } - public float PhysicsFps { get { return physicsFps; } } - public float AgentUpdates { get { return agentUpdates; } } - public float RootAgents { get { return rootAgents; } } - public float ChildAgents { get { return childAgents; } } - public float TotalPrims { get { return totalPrims; } } - public float ActivePrims { get { return activePrims; } } - public float TotalFrameTime { get { return totalFrameTime; } } - public float NetFrameTime { get { return netFrameTime; } } - public float PhysicsFrameTime { get { return physicsFrameTime; } } - public float OtherFrameTime { get { return otherFrameTime; } } - public float ImageFrameTime { get { return imageFrameTime; } } - public float InPacketsPerSecond { get { return inPacketsPerSecond; } } - public float OutPacketsPerSecond { get { return outPacketsPerSecond; } } - public float UnackedBytes { get { return unackedBytes; } } - public float AgentFrameTime { get { return agentFrameTime; } } - public float PendingDownloads { get { return pendingDownloads; } } - public float PendingUploads { get { return pendingUploads; } } - public float ActiveScripts { get { return activeScripts; } } - public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } - -// /// -// /// This is the time it took for the last asset request made in response to a cache miss. -// /// -// public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } } -// -// /// -// /// Number of persistent requests for missing textures we have started blocking from clients. To some extent -// /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either -// /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics -// /// driver bugs on clients (though this seems less likely). -// /// -// public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } } -// -// /// -// /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as -// /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted -// /// as a failure -// /// -// public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } } - - /// - /// Number of known failures to retrieve avatar inventory from the inventory service. This does not - /// cover situations where the inventory service accepts the request but never returns any data, since - /// we do not yet timeout this situation. - /// - /// Commented out because we do not cache inventory at this point -// public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } } - - /// - /// Retrieve the total frame time (in ms) of the last frame - /// - //public float TotalFrameTime { get { return totalFrameTime; } } - - /// - /// Retrieve the physics update component (in ms) of the last frame - /// - //public float PhysicsFrameTime { get { return physicsFrameTime; } } - - /// - /// Retain a dictionary of all packet queues stats reporters - /// - private IDictionary packetQueueStatsCollectors - = new Dictionary(); - - public void AddAbnormalClientThreadTermination() - { - abnormalClientThreadTerminations++; - } - -// public void AddAsset(AssetBase asset) -// { -// assetsInCache++; -// //assetCacheMemoryUsage += asset.Data.Length; -// } -// -// public void RemoveAsset(UUID uuid) -// { -// assetsInCache--; -// } -// -// public void AddTexture(AssetBase image) -// { -// if (image.Data != null) -// { -// texturesInCache++; -// -// // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates -// textureCacheMemoryUsage += image.Data.Length; -// } -// } -// -// /// -// /// Signal that the asset cache has been cleared. -// /// -// public void ClearAssetCacheStatistics() -// { -// assetsInCache = 0; -// assetCacheMemoryUsage = 0; -// texturesInCache = 0; -// textureCacheMemoryUsage = 0; -// } -// -// public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) -// { -// assetRequestTimeAfterCacheMiss = ts; -// } -// -// public void AddBlockedMissingTextureRequest() -// { -// blockedMissingTextureRequests++; -// } -// -// public void AddAssetServiceRequestFailure() -// { -// assetServiceRequestFailures++; -// } - -// public void AddInventoryServiceRetrievalFailure() -// { -// inventoryServiceRetrievalFailures++; -// } - - /// - /// Register as a packet queue stats provider - /// - /// An agent UUID - /// - public void RegisterPacketQueueStatsProvider(UUID uuid, IPullStatsProvider provider) - { - lock (packetQueueStatsCollectors) - { - // FIXME: If the region service is providing more than one region, then the child and root agent - // queues are wrongly replacing each other here. - packetQueueStatsCollectors[uuid] = new PacketQueueStatsCollector(provider); - } - } - - /// - /// Deregister a packet queue stats provider - /// - /// An agent UUID - public void DeregisterPacketQueueStatsProvider(UUID uuid) - { - lock (packetQueueStatsCollectors) - { - packetQueueStatsCollectors.Remove(uuid); - } - } - - /// - /// This is the method on which the classic sim stats reporter (which collects stats for - /// client purposes) sends information to listeners. - /// - /// - public void ReceiveClassicSimStatsPacket(SimStats stats) - { - // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original - // SimStatsPacket that was being used). - timeDilation = stats.StatsBlock[0].StatValue; - simFps = stats.StatsBlock[1].StatValue; - physicsFps = stats.StatsBlock[2].StatValue; - agentUpdates = stats.StatsBlock[3].StatValue; - rootAgents = stats.StatsBlock[4].StatValue; - childAgents = stats.StatsBlock[5].StatValue; - totalPrims = stats.StatsBlock[6].StatValue; - activePrims = stats.StatsBlock[7].StatValue; - totalFrameTime = stats.StatsBlock[8].StatValue; - netFrameTime = stats.StatsBlock[9].StatValue; - physicsFrameTime = stats.StatsBlock[10].StatValue; - otherFrameTime = stats.StatsBlock[11].StatValue; - imageFrameTime = stats.StatsBlock[12].StatValue; - inPacketsPerSecond = stats.StatsBlock[13].StatValue; - outPacketsPerSecond = stats.StatsBlock[14].StatValue; - unackedBytes = stats.StatsBlock[15].StatValue; - agentFrameTime = stats.StatsBlock[16].StatValue; - pendingDownloads = stats.StatsBlock[17].StatValue; - pendingUploads = stats.StatsBlock[18].StatValue; - activeScripts = stats.StatsBlock[19].StatValue; - scriptLinesPerSecond = stats.StatsBlock[20].StatValue; - } - - /// - /// Report back collected statistical information. - /// - /// - public override string Report() - { - StringBuilder sb = new StringBuilder(Environment.NewLine); -// sb.Append("ASSET STATISTICS"); -// sb.Append(Environment.NewLine); - - /* - sb.Append( - string.Format( -@"Asset cache contains {0,6} non-texture assets using {1,10} K -Texture cache contains {2,6} texture assets using {3,10} K -Latest asset request time after cache miss: {4}s -Blocked client requests for missing textures: {5} -Asset service request failures: {6}"+ Environment.NewLine, - AssetsInCache, Math.Round(AssetCacheMemoryUsage / 1024.0), - TexturesInCache, Math.Round(TextureCacheMemoryUsage / 1024.0), - assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, - BlockedMissingTextureRequests, - AssetServiceRequestFailures)); - */ - - /* - sb.Append( - string.Format( -@"Asset cache contains {0,6} assets -Latest asset request time after cache miss: {1}s -Blocked client requests for missing textures: {2} -Asset service request failures: {3}" + Environment.NewLine, - AssetsInCache, - assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, - BlockedMissingTextureRequests, - AssetServiceRequestFailures)); - */ - - sb.Append(Environment.NewLine); - sb.Append("CONNECTION STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "Abnormal client thread terminations: {0}" + Environment.NewLine, - abnormalClientThreadTerminations)); - -// sb.Append(Environment.NewLine); -// sb.Append("INVENTORY STATISTICS"); -// sb.Append(Environment.NewLine); -// sb.Append( -// string.Format( -// "Initial inventory caching failures: {0}" + Environment.NewLine, -// InventoryServiceRetrievalFailures)); - - sb.Append(Environment.NewLine); - sb.Append("FRAME STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "{0,6:0.00} {1,6:0} {2,6:0.0} {3,6:0.0} {4,6:0} {5,6:0} {6,6:0} {7,6:0} {8,6:0} {9,6:0}", - timeDilation, simFps, physicsFps, agentUpdates, rootAgents, - childAgents, totalPrims, activePrims, activeScripts, scriptLinesPerSecond)); - - sb.Append(Environment.NewLine); - sb.Append(Environment.NewLine); - // There is no script frame time currently because we don't yet collect it - sb.Append("PktsIn PktOut PendDl PendUl UnackB TotlFt NetFt PhysFt OthrFt AgntFt ImgsFt"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", - inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, - netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); - sb.Append(Environment.NewLine); - - /* - sb.Append(Environment.NewLine); - sb.Append("PACKET QUEUE STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append("Agent UUID "); - sb.Append( - string.Format( - " {0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", - "Send", "In", "Out", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset")); - sb.Append(Environment.NewLine); - - foreach (UUID key in packetQueueStatsCollectors.Keys) - { - sb.Append(string.Format("{0}: ", key)); - sb.Append(packetQueueStatsCollectors[key].Report()); - sb.Append(Environment.NewLine); - } - */ - - sb.Append(base.Report()); - - return sb.ToString(); - } - - /// - /// Report back collected statistical information as json serialization. - /// - /// - public override string XReport(string uptime, string version) - { - OSDMap args = new OSDMap(30); -// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); -// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", -// assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0)); -// args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}", -// BlockedMissingTextureRequests)); -// args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}", -// AssetServiceRequestFailures)); -// args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}", -// abnormalClientThreadTerminations)); -// args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}", -// InventoryServiceRetrievalFailures)); - args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", timeDilation)); - args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", simFps)); - args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", physicsFps)); - args["AgntUp"] = OSD.FromString (String.Format ("{0:0.##}", agentUpdates)); - args["RootAg"] = OSD.FromString (String.Format ("{0:0.##}", rootAgents)); - args["ChldAg"] = OSD.FromString (String.Format ("{0:0.##}", childAgents)); - args["Prims"] = OSD.FromString (String.Format ("{0:0.##}", totalPrims)); - args["AtvPrm"] = OSD.FromString (String.Format ("{0:0.##}", activePrims)); - args["AtvScr"] = OSD.FromString (String.Format ("{0:0.##}", activeScripts)); - args["ScrLPS"] = OSD.FromString (String.Format ("{0:0.##}", scriptLinesPerSecond)); - args["PktsIn"] = OSD.FromString (String.Format ("{0:0.##}", inPacketsPerSecond)); - args["PktOut"] = OSD.FromString (String.Format ("{0:0.##}", outPacketsPerSecond)); - args["PendDl"] = OSD.FromString (String.Format ("{0:0.##}", pendingDownloads)); - args["PendUl"] = OSD.FromString (String.Format ("{0:0.##}", pendingUploads)); - args["UnackB"] = OSD.FromString (String.Format ("{0:0.##}", unackedBytes)); - args["TotlFt"] = OSD.FromString (String.Format ("{0:0.##}", totalFrameTime)); - args["NetFt"] = OSD.FromString (String.Format ("{0:0.##}", netFrameTime)); - args["PhysFt"] = OSD.FromString (String.Format ("{0:0.##}", physicsFrameTime)); - args["OthrFt"] = OSD.FromString (String.Format ("{0:0.##}", otherFrameTime)); - args["AgntFt"] = OSD.FromString (String.Format ("{0:0.##}", agentFrameTime)); - args["ImgsFt"] = OSD.FromString (String.Format ("{0:0.##}", imageFrameTime)); - args["Memory"] = OSD.FromString (base.XReport (uptime, version)); - args["Uptime"] = OSD.FromString (uptime); - args["Version"] = OSD.FromString (version); - - string strBuffer = ""; - strBuffer = OSDParser.SerializeJsonString(args); - - return strBuffer; - } - } - - /// - /// Pull packet queue stats from packet queues and report - /// - public class PacketQueueStatsCollector : IStatsCollector - { - private IPullStatsProvider m_statsProvider; - - public PacketQueueStatsCollector(IPullStatsProvider provider) - { - m_statsProvider = provider; - } - - /// - /// Report back collected statistical information. - /// - /// - public string Report() - { - return m_statsProvider.GetStats(); - } - - public string XReport(string uptime, string version) - { - return ""; - } - } -} diff --git a/OpenSim/Framework/Statistics/StatsManager.cs b/OpenSim/Framework/Statistics/StatsManager.cs deleted file mode 100644 index 436ce2f..0000000 --- a/OpenSim/Framework/Statistics/StatsManager.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -namespace OpenSim.Framework.Statistics -{ - /// - /// Singleton used to provide access to statistics reporters - /// - public class StatsManager - { - private static AssetStatsCollector assetStats; - private static UserStatsCollector userStats; - private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); - - public static AssetStatsCollector AssetStats { get { return assetStats; } } - public static UserStatsCollector UserStats { get { return userStats; } } - public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } - - /// - /// Start collecting statistics related to assets. - /// Should only be called once. - /// - public static AssetStatsCollector StartCollectingAssetStats() - { - assetStats = new AssetStatsCollector(); - - return assetStats; - } - - /// - /// Start collecting statistics related to users. - /// Should only be called once. - /// - public static UserStatsCollector StartCollectingUserStats() - { - userStats = new UserStatsCollector(); - - return userStats; - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Statistics/UserStatsCollector.cs b/OpenSim/Framework/Statistics/UserStatsCollector.cs deleted file mode 100644 index fd2a9bf..0000000 --- a/OpenSim/Framework/Statistics/UserStatsCollector.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.Timers; - -namespace OpenSim.Framework.Statistics -{ - /// - /// Collects user service statistics - /// - public class UserStatsCollector : BaseStatsCollector - { - private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); - - private int successfulLoginsToday; - public int SuccessfulLoginsToday { get { return successfulLoginsToday; } } - - private int successfulLoginsYesterday; - public int SuccessfulLoginsYesterday { get { return successfulLoginsYesterday; } } - - private int successfulLogins; - public int SuccessfulLogins { get { return successfulLogins; } } - - private int logouts; - public int Logouts { get { return logouts; } } - - public UserStatsCollector() - { - ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); - ageStatsTimer.Enabled = true; - } - - private void OnAgeing(object source, ElapsedEventArgs e) - { - successfulLoginsYesterday = successfulLoginsToday; - - // There is a possibility that an asset request could occur between the execution of these - // two statements. But we're better off without the synchronization overhead. - successfulLoginsToday = 0; - } - - /// - /// Record a successful login - /// - public void AddSuccessfulLogin() - { - successfulLogins++; - successfulLoginsToday++; - } - - public void AddLogout() - { - logouts++; - } - - /// - /// Report back collected statistical information. - /// - /// - override public string Report() - { - return string.Format( -@"Successful logins total : {0}, today : {1}, yesterday : {2} - Logouts total : {3}", - SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); - } - } -} -- cgit v1.1 From 5aec0ff207e9427b8756471eb003fd68859f67b1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 23:27:00 +0100 Subject: Move Watchdog and MemoryWatchdog classes into OpenSim.Framework.Monitoring with other monitoring code from OpenSim.Framework --- OpenSim/Framework/MemoryWatchdog.cs | 129 -------- OpenSim/Framework/Monitoring/MemoryWatchdog.cs | 129 ++++++++ OpenSim/Framework/Monitoring/Watchdog.cs | 334 +++++++++++++++++++++ OpenSim/Framework/Servers/BaseOpenSimServer.cs | 1 + .../Framework/Servers/HttpServer/BaseHttpServer.cs | 1 + .../HttpServer/PollServiceRequestManager.cs | 1 + .../Servers/HttpServer/PollServiceWorkerThread.cs | 1 + OpenSim/Framework/Watchdog.cs | 334 --------------------- 8 files changed, 467 insertions(+), 463 deletions(-) delete mode 100644 OpenSim/Framework/MemoryWatchdog.cs create mode 100644 OpenSim/Framework/Monitoring/MemoryWatchdog.cs create mode 100644 OpenSim/Framework/Monitoring/Watchdog.cs delete mode 100644 OpenSim/Framework/Watchdog.cs (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/MemoryWatchdog.cs b/OpenSim/Framework/MemoryWatchdog.cs deleted file mode 100644 index 1e93077..0000000 --- a/OpenSim/Framework/MemoryWatchdog.cs +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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.Linq; -using System.Reflection; -using System.Threading; -using log4net; - -namespace OpenSim.Framework -{ - /// - /// Experimental watchdog for memory usage. - /// - public static class MemoryWatchdog - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Is this watchdog active? - /// - public static bool Enabled - { - get { return m_enabled; } - set - { -// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); - - if (value && !m_enabled) - UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); - - m_enabled = value; - } - } - private static bool m_enabled; - - /// - /// Average memory churn in bytes per millisecond. - /// - public static double AverageMemoryChurn - { - get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } - } - - /// - /// Maximum number of statistical samples. - /// - /// - /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from - /// the main Watchdog. - /// - private static int m_maxSamples = 24; - - /// - /// Time when the watchdog was last updated. - /// - private static int m_lastUpdateTick; - - /// - /// Memory used at time of last watchdog update. - /// - private static long m_lastUpdateMemory; - - /// - /// Memory churn rate per millisecond. - /// - private static double m_churnRatePerMillisecond; - - /// - /// Historical samples for calculating moving average. - /// - private static Queue m_samples = new Queue(m_maxSamples); - - public static void Update() - { - int now = Util.EnvironmentTickCount(); - long memoryNow = GC.GetTotalMemory(false); - long memoryDiff = memoryNow - m_lastUpdateMemory; - - if (memoryDiff >= 0) - { - if (m_samples.Count >= m_maxSamples) - m_samples.Dequeue(); - - double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); - - // This should never happen since it's not useful for updates to occur with no time elapsed, but - // protect ourselves from a divide-by-zero just in case. - if (elapsed == 0) - return; - - m_samples.Enqueue(memoryDiff / (double)elapsed); - } - - UpdateLastRecord(memoryNow, now); - } - - private static void UpdateLastRecord(long memoryNow, int timeNow) - { - m_lastUpdateMemory = memoryNow; - m_lastUpdateTick = timeNow; - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs new file mode 100644 index 0000000..6599613 --- /dev/null +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs @@ -0,0 +1,129 @@ +/* + * 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.Linq; +using System.Reflection; +using System.Threading; +using log4net; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Experimental watchdog for memory usage. + /// + public static class MemoryWatchdog + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Is this watchdog active? + /// + public static bool Enabled + { + get { return m_enabled; } + set + { +// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); + + if (value && !m_enabled) + UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); + + m_enabled = value; + } + } + private static bool m_enabled; + + /// + /// Average memory churn in bytes per millisecond. + /// + public static double AverageMemoryChurn + { + get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } + } + + /// + /// Maximum number of statistical samples. + /// + /// + /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from + /// the main Watchdog. + /// + private static int m_maxSamples = 24; + + /// + /// Time when the watchdog was last updated. + /// + private static int m_lastUpdateTick; + + /// + /// Memory used at time of last watchdog update. + /// + private static long m_lastUpdateMemory; + + /// + /// Memory churn rate per millisecond. + /// + private static double m_churnRatePerMillisecond; + + /// + /// Historical samples for calculating moving average. + /// + private static Queue m_samples = new Queue(m_maxSamples); + + public static void Update() + { + int now = Util.EnvironmentTickCount(); + long memoryNow = GC.GetTotalMemory(false); + long memoryDiff = memoryNow - m_lastUpdateMemory; + + if (memoryDiff >= 0) + { + if (m_samples.Count >= m_maxSamples) + m_samples.Dequeue(); + + double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); + + // This should never happen since it's not useful for updates to occur with no time elapsed, but + // protect ourselves from a divide-by-zero just in case. + if (elapsed == 0) + return; + + m_samples.Enqueue(memoryDiff / (double)elapsed); + } + + UpdateLastRecord(memoryNow, now); + } + + private static void UpdateLastRecord(long memoryNow, int timeNow) + { + m_lastUpdateMemory = memoryNow; + m_lastUpdateTick = timeNow; + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs new file mode 100644 index 0000000..d4cf02f --- /dev/null +++ b/OpenSim/Framework/Monitoring/Watchdog.cs @@ -0,0 +1,334 @@ +/* + * 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.Linq; +using System.Threading; +using log4net; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Manages launching threads and keeping watch over them for timeouts + /// + public static class Watchdog + { + /// Timer interval in milliseconds for the watchdog timer + const double WATCHDOG_INTERVAL_MS = 2500.0d; + + /// Default timeout in milliseconds before a thread is considered dead + public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000; + + [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] + public class ThreadWatchdogInfo + { + public Thread Thread { get; private set; } + + /// + /// Approximate tick when this thread was started. + /// + /// + /// Not terribly good since this quickly wraps around. + /// + public int FirstTick { get; private set; } + + /// + /// Last time this heartbeat update was invoked + /// + public int LastTick { get; set; } + + /// + /// Number of milliseconds before we notify that the thread is having a problem. + /// + public int Timeout { get; set; } + + /// + /// Is this thread considered timed out? + /// + public bool IsTimedOut { get; set; } + + /// + /// Will this thread trigger the alarm function if it has timed out? + /// + public bool AlarmIfTimeout { get; set; } + + /// + /// Method execute if alarm goes off. If null then no alarm method is fired. + /// + public Func AlarmMethod { get; set; } + + public ThreadWatchdogInfo(Thread thread, int timeout) + { + Thread = thread; + Timeout = timeout; + FirstTick = Environment.TickCount & Int32.MaxValue; + LastTick = FirstTick; + } + } + + /// + /// This event is called whenever a tracked thread is + /// stopped or has not called UpdateThread() in time< + /// /summary> + public static event Action OnWatchdogTimeout; + + private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static Dictionary m_threads; + private static System.Timers.Timer m_watchdogTimer; + + /// + /// Last time the watchdog thread ran. + /// + /// + /// Should run every WATCHDOG_INTERVAL_MS + /// + public static int LastWatchdogThreadTick { get; private set; } + + static Watchdog() + { + m_threads = new Dictionary(); + m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); + m_watchdogTimer.AutoReset = false; + m_watchdogTimer.Elapsed += WatchdogTimerElapsed; + + // Set now so we don't get alerted on the first run + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + + m_watchdogTimer.Start(); + } + + /// + /// Start a new thread that is tracked by the watchdog timer. + /// + /// The method that will be executed in a new thread + /// A name to give to the new thread + /// Priority to run the thread at + /// True to run this thread as a background thread, otherwise false + /// Trigger an alarm function is we have timed out + /// The newly created Thread object + public static Thread StartThread( + ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout) + { + return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS); + } + + /// + /// Start a new thread that is tracked by the watchdog timer + /// + /// The method that will be executed in a new thread + /// A name to give to the new thread + /// Priority to run the thread at + /// True to run this thread as a background + /// thread, otherwise false + /// Trigger an alarm function is we have timed out + /// + /// Alarm method to call if alarmIfTimeout is true and there is a timeout. + /// Normally, this will just return some useful debugging information. + /// + /// Number of milliseconds to wait until we issue a warning about timeout. + /// The newly created Thread object + public static Thread StartThread( + ThreadStart start, string name, ThreadPriority priority, bool isBackground, + bool alarmIfTimeout, Func alarmMethod, int timeout) + { + Thread thread = new Thread(start); + thread.Name = name; + thread.Priority = priority; + thread.IsBackground = isBackground; + + ThreadWatchdogInfo twi + = new ThreadWatchdogInfo(thread, timeout) + { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod }; + + m_log.DebugFormat( + "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); + + lock (m_threads) + m_threads.Add(twi.Thread.ManagedThreadId, twi); + + thread.Start(); + + return thread; + } + + /// + /// Marks the current thread as alive + /// + public static void UpdateThread() + { + UpdateThread(Thread.CurrentThread.ManagedThreadId); + } + + /// + /// Stops watchdog tracking on the current thread + /// + /// + /// True if the thread was removed from the list of tracked + /// threads, otherwise false + /// + public static bool RemoveThread() + { + return RemoveThread(Thread.CurrentThread.ManagedThreadId); + } + + private static bool RemoveThread(int threadID) + { + lock (m_threads) + return m_threads.Remove(threadID); + } + + public static bool AbortThread(int threadID) + { + lock (m_threads) + { + if (m_threads.ContainsKey(threadID)) + { + ThreadWatchdogInfo twi = m_threads[threadID]; + twi.Thread.Abort(); + RemoveThread(threadID); + + return true; + } + else + { + return false; + } + } + } + + private static void UpdateThread(int threadID) + { + ThreadWatchdogInfo threadInfo; + + // Although TryGetValue is not a thread safe operation, we use a try/catch here instead + // of a lock for speed. Adding/removing threads is a very rare operation compared to + // UpdateThread(), and a single UpdateThread() failure here and there won't break + // anything + try + { + if (m_threads.TryGetValue(threadID, out threadInfo)) + { + threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; + threadInfo.IsTimedOut = false; + } + else + { + m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID); + } + } + catch { } + } + + /// + /// Get currently watched threads for diagnostic purposes + /// + /// + public static ThreadWatchdogInfo[] GetThreadsInfo() + { + lock (m_threads) + return m_threads.Values.ToArray(); + } + + /// + /// Return the current thread's watchdog info. + /// + /// The watchdog info. null if the thread isn't being monitored. + public static ThreadWatchdogInfo GetCurrentThreadInfo() + { + lock (m_threads) + { + if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId)) + return m_threads[Thread.CurrentThread.ManagedThreadId]; + } + + return null; + } + + /// + /// Check watched threads. Fire alarm if appropriate. + /// + /// + /// + private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) + { + int now = Environment.TickCount & Int32.MaxValue; + int msElapsed = now - LastWatchdogThreadTick; + + if (msElapsed > WATCHDOG_INTERVAL_MS * 2) + m_log.WarnFormat( + "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", + msElapsed, WATCHDOG_INTERVAL_MS); + + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + + Action callback = OnWatchdogTimeout; + + if (callback != null) + { + List callbackInfos = null; + + lock (m_threads) + { + foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) + { + if (threadInfo.Thread.ThreadState == ThreadState.Stopped) + { + RemoveThread(threadInfo.Thread.ManagedThreadId); + + if (callbackInfos == null) + callbackInfos = new List(); + + callbackInfos.Add(threadInfo); + } + else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) + { + threadInfo.IsTimedOut = true; + + if (threadInfo.AlarmIfTimeout) + { + if (callbackInfos == null) + callbackInfos = new List(); + + callbackInfos.Add(threadInfo); + } + } + } + } + + if (callbackInfos != null) + foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) + callback(callbackInfo); + } + + if (MemoryWatchdog.Enabled) + MemoryWatchdog.Update(); + + m_watchdogTimer.Start(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index ab8d95a..2a8ae38 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -40,6 +40,7 @@ using log4net.Core; using log4net.Repository; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Monitoring; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 3de7f9c..f57ea76 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -45,6 +45,7 @@ using OpenMetaverse.StructuredData; using CoolHTTPListener = HttpServer.HttpListener; using HttpListener=System.Net.HttpListener; using LogPrio=HttpServer.LogPrio; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers.HttpServer { diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index 3252251..8d50151 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs @@ -32,6 +32,7 @@ using System.Reflection; using log4net; using HttpServer; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers.HttpServer { diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs index 35a8dee..5adbcd1 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs @@ -34,6 +34,7 @@ using HttpServer; using OpenMetaverse; using System.Reflection; using log4net; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers.HttpServer { diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs deleted file mode 100644 index 54e3d1a..0000000 --- a/OpenSim/Framework/Watchdog.cs +++ /dev/null @@ -1,334 +0,0 @@ -/* - * 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.Linq; -using System.Threading; -using log4net; - -namespace OpenSim.Framework -{ - /// - /// Manages launching threads and keeping watch over them for timeouts - /// - public static class Watchdog - { - /// Timer interval in milliseconds for the watchdog timer - const double WATCHDOG_INTERVAL_MS = 2500.0d; - - /// Default timeout in milliseconds before a thread is considered dead - public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000; - - [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] - public class ThreadWatchdogInfo - { - public Thread Thread { get; private set; } - - /// - /// Approximate tick when this thread was started. - /// - /// - /// Not terribly good since this quickly wraps around. - /// - public int FirstTick { get; private set; } - - /// - /// Last time this heartbeat update was invoked - /// - public int LastTick { get; set; } - - /// - /// Number of milliseconds before we notify that the thread is having a problem. - /// - public int Timeout { get; set; } - - /// - /// Is this thread considered timed out? - /// - public bool IsTimedOut { get; set; } - - /// - /// Will this thread trigger the alarm function if it has timed out? - /// - public bool AlarmIfTimeout { get; set; } - - /// - /// Method execute if alarm goes off. If null then no alarm method is fired. - /// - public Func AlarmMethod { get; set; } - - public ThreadWatchdogInfo(Thread thread, int timeout) - { - Thread = thread; - Timeout = timeout; - FirstTick = Environment.TickCount & Int32.MaxValue; - LastTick = FirstTick; - } - } - - /// - /// This event is called whenever a tracked thread is - /// stopped or has not called UpdateThread() in time< - /// /summary> - public static event Action OnWatchdogTimeout; - - private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private static Dictionary m_threads; - private static System.Timers.Timer m_watchdogTimer; - - /// - /// Last time the watchdog thread ran. - /// - /// - /// Should run every WATCHDOG_INTERVAL_MS - /// - public static int LastWatchdogThreadTick { get; private set; } - - static Watchdog() - { - m_threads = new Dictionary(); - m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); - m_watchdogTimer.AutoReset = false; - m_watchdogTimer.Elapsed += WatchdogTimerElapsed; - - // Set now so we don't get alerted on the first run - LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; - - m_watchdogTimer.Start(); - } - - /// - /// Start a new thread that is tracked by the watchdog timer. - /// - /// The method that will be executed in a new thread - /// A name to give to the new thread - /// Priority to run the thread at - /// True to run this thread as a background thread, otherwise false - /// Trigger an alarm function is we have timed out - /// The newly created Thread object - public static Thread StartThread( - ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout) - { - return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS); - } - - /// - /// Start a new thread that is tracked by the watchdog timer - /// - /// The method that will be executed in a new thread - /// A name to give to the new thread - /// Priority to run the thread at - /// True to run this thread as a background - /// thread, otherwise false - /// Trigger an alarm function is we have timed out - /// - /// Alarm method to call if alarmIfTimeout is true and there is a timeout. - /// Normally, this will just return some useful debugging information. - /// - /// Number of milliseconds to wait until we issue a warning about timeout. - /// The newly created Thread object - public static Thread StartThread( - ThreadStart start, string name, ThreadPriority priority, bool isBackground, - bool alarmIfTimeout, Func alarmMethod, int timeout) - { - Thread thread = new Thread(start); - thread.Name = name; - thread.Priority = priority; - thread.IsBackground = isBackground; - - ThreadWatchdogInfo twi - = new ThreadWatchdogInfo(thread, timeout) - { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod }; - - m_log.DebugFormat( - "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); - - lock (m_threads) - m_threads.Add(twi.Thread.ManagedThreadId, twi); - - thread.Start(); - - return thread; - } - - /// - /// Marks the current thread as alive - /// - public static void UpdateThread() - { - UpdateThread(Thread.CurrentThread.ManagedThreadId); - } - - /// - /// Stops watchdog tracking on the current thread - /// - /// - /// True if the thread was removed from the list of tracked - /// threads, otherwise false - /// - public static bool RemoveThread() - { - return RemoveThread(Thread.CurrentThread.ManagedThreadId); - } - - private static bool RemoveThread(int threadID) - { - lock (m_threads) - return m_threads.Remove(threadID); - } - - public static bool AbortThread(int threadID) - { - lock (m_threads) - { - if (m_threads.ContainsKey(threadID)) - { - ThreadWatchdogInfo twi = m_threads[threadID]; - twi.Thread.Abort(); - RemoveThread(threadID); - - return true; - } - else - { - return false; - } - } - } - - private static void UpdateThread(int threadID) - { - ThreadWatchdogInfo threadInfo; - - // Although TryGetValue is not a thread safe operation, we use a try/catch here instead - // of a lock for speed. Adding/removing threads is a very rare operation compared to - // UpdateThread(), and a single UpdateThread() failure here and there won't break - // anything - try - { - if (m_threads.TryGetValue(threadID, out threadInfo)) - { - threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; - threadInfo.IsTimedOut = false; - } - else - { - m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID); - } - } - catch { } - } - - /// - /// Get currently watched threads for diagnostic purposes - /// - /// - public static ThreadWatchdogInfo[] GetThreadsInfo() - { - lock (m_threads) - return m_threads.Values.ToArray(); - } - - /// - /// Return the current thread's watchdog info. - /// - /// The watchdog info. null if the thread isn't being monitored. - public static ThreadWatchdogInfo GetCurrentThreadInfo() - { - lock (m_threads) - { - if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId)) - return m_threads[Thread.CurrentThread.ManagedThreadId]; - } - - return null; - } - - /// - /// Check watched threads. Fire alarm if appropriate. - /// - /// - /// - private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) - { - int now = Environment.TickCount & Int32.MaxValue; - int msElapsed = now - LastWatchdogThreadTick; - - if (msElapsed > WATCHDOG_INTERVAL_MS * 2) - m_log.WarnFormat( - "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", - msElapsed, WATCHDOG_INTERVAL_MS); - - LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; - - Action callback = OnWatchdogTimeout; - - if (callback != null) - { - List callbackInfos = null; - - lock (m_threads) - { - foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) - { - if (threadInfo.Thread.ThreadState == ThreadState.Stopped) - { - RemoveThread(threadInfo.Thread.ManagedThreadId); - - if (callbackInfos == null) - callbackInfos = new List(); - - callbackInfos.Add(threadInfo); - } - else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) - { - threadInfo.IsTimedOut = true; - - if (threadInfo.AlarmIfTimeout) - { - if (callbackInfos == null) - callbackInfos = new List(); - - callbackInfos.Add(threadInfo); - } - } - } - } - - if (callbackInfos != null) - foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) - callback(callbackInfo); - } - - if (MemoryWatchdog.Enabled) - MemoryWatchdog.Update(); - - m_watchdogTimer.Start(); - } - } -} \ No newline at end of file -- cgit v1.1 From 1133f81dce840e394763a4eea03067fa8d18f0e1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 20:40:25 +0100 Subject: Remove a couple of compiler warnings pointed out by SignpostMarv --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 2a8ae38..7a5c16d 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -43,7 +43,6 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Framework.Monitoring; using Timer=System.Timers.Timer; using OpenMetaverse; -- cgit v1.1 From f3c5ce1bbd86fafa0e436efe5de804b65d64b8af Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 22:20:08 +0100 Subject: minor: Comment out unused MemoryWatchdog.m_churnRatePerMillisecond - this is currently calculated dynamically --- OpenSim/Framework/Monitoring/MemoryWatchdog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs index 6599613..a23cf1f 100644 --- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs @@ -89,7 +89,7 @@ namespace OpenSim.Framework.Monitoring /// /// Memory churn rate per millisecond. /// - private static double m_churnRatePerMillisecond; +// private static double m_churnRatePerMillisecond; /// /// Historical samples for calculating moving average. -- cgit v1.1 From adbdb220df4aacc93e81eeb2eb1854825e4db7fb Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 27 Jul 2012 22:15:25 +0100 Subject: making first run more resilient to bad input (loop until good input, rather than crash) --- OpenSim/Framework/RegionInfo.cs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index a505524..2080a16 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -480,9 +480,16 @@ namespace OpenSim.Framework MainConsole.Instance.Output("=====================================\n"); if (name == String.Empty) - name = MainConsole.Instance.CmdPrompt("New region name", name); - if (name == String.Empty) - throw new Exception("Cannot interactively create region with no name"); + { + while (name.Trim() == string.Empty) + { + name = MainConsole.Instance.CmdPrompt("New region name", name); + if (name.Trim() == string.Empty) + { + MainConsole.Instance.Output("Cannot interactively create region with no name"); + } + } + } source.AddConfig(name); @@ -513,15 +520,20 @@ namespace OpenSim.Framework // allKeys.Remove("RegionUUID"); string regionUUID = config.GetString("RegionUUID", string.Empty); - if (regionUUID == String.Empty) + if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) { UUID newID = UUID.Random(); - - regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); + while (RegionID == UUID.Zero) + { + regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); + if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) + { + MainConsole.Instance.Output("RegionUUID must be a valid UUID"); + } + } config.Set("RegionUUID", regionUUID); } - RegionID = new UUID(regionUUID); originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?) // Location -- cgit v1.1