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 ++++
7 files changed, 881 insertions(+)
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
(limited to 'OpenSim/Framework/Monitoring')
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);
+ }
+ }
+}
--
cgit v1.1