diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs index 7119964fdd..e1bf29ff8c 100644 --- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs @@ -38,6 +38,11 @@ namespace OpenSim.Framework.Monitoring /// public class BaseStatsCollector : IStatsCollector { + public virtual string Report(IScene scene = null) + { + return string.Empty; + } + public virtual string Report() { StringBuilder sb = new StringBuilder(Environment.NewLine); @@ -78,7 +83,7 @@ namespace OpenSim.Framework.Monitoring public virtual string XReport(string uptime, string version) { - return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; + return (string)Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString(); } public virtual OSDMap OReport(string uptime, string version) @@ -87,5 +92,17 @@ namespace OpenSim.Framework.Monitoring ret.Add("TotalMemory", new OSDReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); return ret; } + + public virtual string XReport(string uptime, string version, string scene) + { + return (string)Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString(); + } + + public virtual OSDMap OReport(string uptime, string version, string scene) + { + OSDMap ret = new OSDMap(); + ret.Add("TotalMemory", new OSDReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); + return ret; + } } } diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index e3eedfe0d5..936ed8fa6a 100755 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Diagnostics; using System.Linq; using System.Text; @@ -42,191 +43,12 @@ namespace OpenSim.Framework.Monitoring /// public class SimExtraStatsCollector : BaseStatsCollector { -// 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 spareTime; - private volatile float sleepTime; - private volatile float physicsStep; - private volatile float scriptEPS; - - - private volatile float scriptLinesPerSecond; - private volatile float m_frameDilation; - private volatile float m_usersLoggingIn; - private volatile float m_totalGeoPrims; - private volatile float m_totalMeshes; - private volatile float m_inUseThreads; - -// /// -// /// 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; } } - public float ScriptEPS { get { return scriptEPS; } } - - // /// - // /// 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 + private readonly Dictionary packetQueueStatsCollectors = new Dictionary(); -// 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 /// @@ -254,6 +76,9 @@ namespace OpenSim.Framework.Monitoring } } + private UUID firstReceivedRegion; + private readonly ConcurrentDictionary ReceivedStats = new ConcurrentDictionary(); + private readonly ConcurrentDictionary ReceivedStatsByName = new ConcurrentDictionary(); /// /// This is the method on which the classic sim stats reporter (which collects stats for /// client purposes) sends information to listeners. @@ -261,160 +86,67 @@ namespace OpenSim.Framework.Monitoring /// 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). - - // For an unknown reason the original designers decided not to - // include the spare MS statistic inside of this class, this is - // located inside the StatsBlock at location 21, thus it is skipped - 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; - imageFrameTime = stats.StatsBlock[11].StatValue; - otherFrameTime = 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; - sleepTime = stats.StatsBlock[20].StatValue; - spareTime = stats.StatsBlock[21].StatValue; - physicsStep = stats.StatsBlock[22].StatValue; - scriptEPS = stats.StatsBlock[28].StatValue; - - scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue; - m_frameDilation = stats.ExtraStatsBlock[1].StatValue; - m_usersLoggingIn = stats.ExtraStatsBlock[2].StatValue; - m_totalGeoPrims = stats.ExtraStatsBlock[3].StatValue; - m_totalMeshes = stats.ExtraStatsBlock[4].StatValue; - m_inUseThreads = stats.ExtraStatsBlock[5].StatValue; + UUID id = stats.RegionUUID; + if (id != UUID.Zero) + { + if(ReceivedStats.Count == 0) + firstReceivedRegion = id; + ReceivedStats[id] = stats; + ReceivedStatsByName[stats.RegionName.ToLower()] = stats; + } } /// /// Report back collected statistical information. /// /// - public override string Report() + public override string Report(IScene scene) { - StringBuilder sb = new StringBuilder(Environment.NewLine); -// sb.Append("ASSET STATISTICS"); -// sb.Append(Environment.NewLine); + SimStats sdata = null; + if (ReceivedStats.Count > 0) + { + if (scene == null) + ReceivedStats.TryGetValue(firstReceivedRegion, out sdata); + else + ReceivedStats.TryGetValue(scene.RegionInfo.RegionID, out sdata); + } - /* - 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); + StringBuilder sb = new StringBuilder(); + sb.AppendLine("CONNECTION STATISTICS"); List stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives"); - sb.AppendFormat( "Client logouts due to no data receive timeout: {0}\n\n", stats != null ? stats.Sum(s => s.Value).ToString() : "unknown"); -// 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("SAMPLE FRAME STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrEPS"); - 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, scriptEPS)); - - 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}\n\n", - inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, - netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); - - /* 20130319 RA: For the moment, disable the dump of 'scene' catagory as they are mostly output by - * the two formatted printouts above. - SortedDictionary> sceneStats; - if (StatsManager.TryGetStats("scene", out sceneStats)) + if(sdata != null) { - foreach (KeyValuePair> kvp in sceneStats) - { - foreach (Stat stat in kvp.Value.Values) - { - if (stat.Verbosity == StatVerbosity.Info) - { - sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName); - } - } - } - } - */ - - /* - 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()); + float[] data = sdata.StatsValues; + sb.AppendFormat("{0} FRAME STATISTICS", sdata.RegionName); sb.Append(Environment.NewLine); - } - */ + sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrEPS\n"); + sb.AppendFormat( + "{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}\n", + data[(int)StatsIndex.TimeDilation], data[(int)StatsIndex.SimFPS], + data[(int)StatsIndex.PhysicsFPS], + data[(int)StatsIndex.AgentUpdates], data[(int)StatsIndex.Agents], + data[(int)StatsIndex.ChildAgents], data[(int)StatsIndex.TotalPrim], + data[(int)StatsIndex.ActivePrim], data[(int)StatsIndex.ActiveScripts], + data[(int)StatsIndex.ScriptEps]); + 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\n"); + sb.AppendFormat( + "{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}\n", + data[(int)StatsIndex.InPacketsPerSecond], data[(int)StatsIndex.OutPacketsPerSecond], + data[(int)StatsIndex.PendingDownloads], data[(int)StatsIndex.PendingUploads], + data[(int)StatsIndex.UnAckedBytes], data[(int)StatsIndex.FrameMS], + data[(int)StatsIndex.NetMS], data[(int)StatsIndex.PhysicsMS], + data[(int)StatsIndex.OtherMS] , data[(int)StatsIndex.AgentMS], + data[(int)StatsIndex.ImageMS]); + } sb.Append(base.Report()); return sb.ToString(); @@ -424,16 +156,16 @@ Asset service request failures: {3}" + Environment.NewLine, /// Report back collected statistical information as json serialization. /// /// - public override string XReport(string uptime, string version) + public override string XReport(string uptime, string version, string scene) { - return OSDParser.SerializeJsonString(OReport(uptime, version)); + return OSDParser.SerializeJsonString(OReport(uptime, version, scene)); } /// /// Report back collected statistical information as an OSDMap /// /// - public override OSDMap OReport(string uptime, string version) + public override OSDMap OReport(string uptime, string version, string scene) { // Get the amount of physical memory, allocated with the instance of this program, in kilobytes; // the working set is the set of memory pages currently visible to this program in physical RAM @@ -454,52 +186,63 @@ Asset service request failures: {3}" + Environment.NewLine, } } - 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["ScrEPS"] = OSD.FromString(String.Format("{0:0.##}", scriptEPS)); - 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); + SimStats sdata = null; + if (ReceivedStats.Count > 0) + { + if (scene == null || string.IsNullOrEmpty(scene)) + ReceivedStats.TryGetValue(firstReceivedRegion, out sdata); + else + { + if(UUID.TryParse(scene, out UUID id)) + ReceivedStats.TryGetValue(id, out sdata); + else + ReceivedStatsByName.TryGetValue(scene.ToLower(), out sdata); + } + } - args["FrameDilatn"] = OSD.FromString(String.Format("{0:0.##}", m_frameDilation)); - args["Logging in Users"] = OSD.FromString(String.Format("{0:0.##}", m_usersLoggingIn)); - args["GeoPrims"] = OSD.FromString(String.Format("{0:0.##}", m_totalGeoPrims)); - args["Mesh Objects"] = OSD.FromString(String.Format("{0:0.##}", m_totalMeshes)); - args["XEngine Thread Count"] = OSD.FromString(String.Format("{0:0.##}", m_inUseThreads)); - args["Util Thread Count"] = OSD.FromString(String.Format("{0:0.##}", Util.GetSmartThreadPoolInfo().InUseThreads)); - args["System Thread Count"] = OSD.FromString(String.Format("{0:0.##}", numberThreadsRunning)); - args["ProcMem"] = OSD.FromString(String.Format("{0:0.##}", memUsage)); + OSDMap args = new OSDMap(33); + if(sdata != null && sdata.StatsValues != null) + { + float[] data = sdata.StatsValues; + args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.TimeDilation])); + args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.SimFPS])); + args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.PhysicsFPS])); + args["AgntUp"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.AgentUpdates])); + args["RootAg"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.Agents])); + args["ChldAg"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.ChildAgents])); + args["Prims"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.TotalPrim])); + args["AtvPrm"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.ActivePrim])); + args["AtvScr"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.ActiveScripts])); + args["ScrLPS"] = OSD.FromString(String.Format("{0:0.##}", data[(int)StatsIndex.LSLScriptLinesPerSecond])); + args["ScrEPS"] = OSD.FromString(String.Format("{0:0.##}", data[(int)StatsIndex.ScriptEps])); + args["PktsIn"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.InPacketsPerSecond])); + args["PktOut"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.OutPacketsPerSecond])); + args["PendDl"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.PendingDownloads])); + args["PendUl"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.PendingUploads])); + args["UnackB"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.UnAckedBytes])); + args["TotlFt"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.FrameMS])); + args["NetFt"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.NetMS])); + args["PhysFt"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.PhysicsMS])); + args["OthrFt"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.OtherMS])); + args["AgntFt"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.AgentMS])); + args["ImgsFt"] = OSD.FromString (String.Format ("{0:0.##}", data[(int)StatsIndex.ImageMS])); + + args["FrameDilatn"] = OSD.FromString(String.Format("{0:0.#}", data[(int)StatsIndex.FrameDilation2])); + args["Logging in Users"] = OSD.FromString(String.Format("{0:0.#}", data[(int)StatsIndex.UsersLoggingIn])); + args["GeoPrims"] = OSD.FromString(String.Format("{0:0.#}", data[(int)StatsIndex.TotalGeoPrim])); + args["Mesh Objects"] = OSD.FromString(String.Format("{0:0.##}", data[(int)StatsIndex.TotalMesh])); + args["Script Engine Thread Count"] = OSD.FromString(String.Format("{0:0.#}", data[(int)StatsIndex.ScriptEngineThreadCount])); + args["Util Thread Count"] = OSD.FromString(String.Format("{0:0.##}", Util.GetSmartThreadPoolInfo().InUseThreads)); + args["System Thread Count"] = OSD.FromString(String.Format("{0:0.##}", numberThreadsRunning)); + args["ProcMem"] = OSD.FromString(String.Format("{0:0.##}", memUsage)); + + args["Memory"] = OSD.FromString(base.XReport(uptime, version)); + args["Uptime"] = OSD.FromString(uptime); + args["Version"] = OSD.FromString(version); + args["RegionName"] = sdata.RegionName; + } + else + args["Error"] = "No data"; return args; } diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index 4b1a2290c9..cb92c2e06d 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs @@ -38,7 +38,7 @@ namespace OpenSim.Framework.Monitoring /// /// Holds individual statistic details /// - public class Stat : IDisposable + public class Stat: IDisposable { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -196,9 +196,20 @@ namespace OpenSim.Framework.Monitoring Verbosity = verbosity; } - // IDisposable.Dispose() - public virtual void Dispose() + ~Stat() { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + PullAction = null; return; } @@ -226,13 +237,26 @@ namespace OpenSim.Framework.Monitoring public virtual string ToConsoleString() { StringBuilder sb = new StringBuilder(); - sb.AppendFormat( - "{0}.{1}.{2} : {3}{4}", - Category, - Container, - ShortName, - Value, - string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName)); + + if(string.IsNullOrEmpty(UnitName)) + { + sb.AppendFormat( + "{0}.{1}.{2} : {3:0.###}", + Category, + Container, + ShortName, + Value); + } + else + { + sb.AppendFormat( + "{0}.{1}.{2} : {3:0.###} {4}", + Category, + Container, + ShortName, + Value, + UnitName); + } AppendMeasuresOfInterest(sb); @@ -321,12 +345,20 @@ namespace OpenSim.Framework.Monitoring if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime)) { - sb.AppendFormat( - ", {0:0.##}{1}/s, {2:0.##}{3}/s", - lastChangeOverTime, - string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName), - averageChangeOverTime, - string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName)); + if(string.IsNullOrEmpty(UnitName)) + { + sb.AppendFormat( + ", {0:0.###}/s, {1:0.###}/s", + lastChangeOverTime, + averageChangeOverTime); + } + else + { + sb.AppendFormat( + ", {0:0.###} {1}/s, {2:0.###} {3}/s", + lastChangeOverTime, UnitName, + averageChangeOverTime, UnitName); + } } } } diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 2517fc1bf9..0e5626b164 100755 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -168,7 +168,7 @@ namespace OpenSim.Framework.Monitoring { // Legacy if (SimExtraStats != null) - con.Output(SimExtraStats.Report()); + con.Output(SimExtraStats.Report(con.ConsoleScene)); else OutputAllStatsToConsole(con); } diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 4ecf15f057..5feb7b521f 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -224,14 +224,16 @@ namespace OpenSim.Framework.Servers public string StatReport(IOSHttpRequest httpRequest) { + httpRequest.QueryAsDictionary.TryGetValue("region", out string id); + // If we catch a request for "callback", wrap the response in the value for jsonp - if (httpRequest.Query.ContainsKey("callback")) + if (httpRequest.QueryAsDictionary.TryGetValue("callback", out string cb) && ! string.IsNullOrEmpty(cb)) { - return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; + return cb + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version, id) + ");"; } else { - return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); + return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version, id); } } } diff --git a/OpenSim/Framework/SimStats.cs b/OpenSim/Framework/SimStats.cs index f19a270e59..adda209b50 100644 --- a/OpenSim/Framework/SimStats.cs +++ b/OpenSim/Framework/SimStats.cs @@ -26,79 +26,249 @@ */ using OpenMetaverse; -using OpenMetaverse.Packets; +using System.Collections.Generic; namespace OpenSim.Framework { + /// + /// These are the IDs of stats required by viewers protocol + /// + /// + /// Some of these are not relevant to OpenSimulator since it is architected differently to other simulators + /// (e.g. script instructions aren't executed as part of the frame loop so 'script time' is tricky). + /// + public enum StatsID : uint + { + // viewers defined IDs + TimeDilation = 0, + SimFPS = 1, + PhysicsFPS = 2, + AgentUpdates = 3, + FrameMS = 4, + NetMS = 5, + OtherMS = 6, + PhysicsMS = 7, + AgentMS = 8, + ImageMS = 9, + ScriptMS = 10, + TotalPrim = 11, + ActivePrim = 12, + Agents = 13, + ChildAgents = 14, + ActiveScripts = 15, + LSLScriptLinesPerSecond = 16, // viewers don't like this anymore + InPacketsPerSecond = 17, + OutPacketsPerSecond = 18, + PendingDownloads = 19, + PendingUploads = 20, + VirtualSizeKb = 21, + ResidentSizeKb = 22, + PendingLocalUploads = 23, + UnAckedBytes = 24, + PhysicsPinnedTasks = 25, + PhysicsLodTasks = 26, + SimPhysicsStepMs = 27, + SimPhysicsShapeMs = 28, + SimPhysicsOtherMs = 29, + SimPhysicsMemory = 30, + ScriptEps = 31, + SimSpareMs = 32, + SimSleepMs = 33, + SimIoPumpTime = 34, + SimPCTSscriptsRun = 35, + SimRegionIdle = 36, // dataserver only + SimRegionIdlePossible = 37, // dataserver only + SimAIStepTimeMS = 38, + SimSkippedSillouet_PS = 39, + SimSkippedCharsPerC = 40, + + // extra stats IDs, just far from viewer defined ones + SimExtraCountStart = 1000, + + internalLSLScriptLinesPerSecond = 1000, + FrameDilation2 = 1001, + UsersLoggingIn = 1002, + TotalGeoPrim = 1003, + TotalMesh = 1004, + ScriptEngineThreadCount = 1005, + + SimExtraCountEnd = 1006 + } + + // stats values are stored on a float[] + // so we need readable indexes to it + // Values sent to viewers via lludp must be first and up to fake index ViewerArraySize + // fake index ArraySize defines the needed array size + // this does not follow same order as IDs, because legacy order + + public enum StatsIndex : int + { + // index into data array + TimeDilation = 0, + SimFPS = 1, + PhysicsFPS = 2, + AgentUpdates = 3, + Agents = 4, + ChildAgents = 5, + TotalPrim = 6, + ActivePrim = 7, + FrameMS = 8, + NetMS = 9, + PhysicsMS = 10, + ImageMS = 11, + OtherMS = 12, + InPacketsPerSecond = 13, + OutPacketsPerSecond = 14, + UnAckedBytes = 15, + AgentMS = 16, + PendingDownloads = 17, + PendingUploads = 18, + ActiveScripts = 19, + SimSleepMs = 20, + SimSpareMs = 21, + SimPhysicsStepMs = 22, + VirtualSizeKb = 23, + ResidentSizeKb = 24, + PendingLocalUploads = 25, + PhysicsPinnedTasks = 26, + PhysicsLodTasks = 27, + ScriptEps = 28, + SimAIStepTimeMS = 29, + SimIoPumpTime = 30, + SimPCTSscriptsRun = 31, + SimRegionIdle = 32, + SimRegionIdlePossible = 33, + SimSkippedSillouet_PS = 34, + SimSkippedCharsPerC = 35, + SimPhysicsMemory = 36, + ScriptMS = 37, + + LSLScriptLinesPerSecond = 38, + SimPhysicsShapeMs = 39, + SimPhysicsOtherMs = 40, + + ViewerArraySize = 41, // just a marker to the end of viewer only stats and start of extra + + internalLSLScriptLinesPerSecond = 41, + FrameDilation2 = 42, + UsersLoggingIn = 43, + TotalGeoPrim = 44, + TotalMesh = 45, + ScriptEngineThreadCount = 46, + + ArraySize = 47 // last is marker for array size + } + + public enum ExtraStatsIndex : int + { + // extra stats IDs irrelevant, just far from viewer defined ones + SimExtraCountStart = 1000, + + internalLSLScriptLinesPerSecond = 1000, + FrameDilation2 = 1001, + UsersLoggingIn = 1002, + TotalGeoPrim = 1003, + TotalMesh = 1004, + ThreadCount = 1005, + + SimExtraCountEnd = 1006 + } + /// /// Enapsulate statistics for a simulator/scene. /// /// TODO: This looks very much like the OpenMetaverse SimStatsPacket. It should be much more generic stats /// storage. /// + public class SimStats { - public uint RegionX - { - get { return m_regionX; } - } - private uint m_regionX; + public uint RegionX; + public uint RegionY; + public uint RegionSizeX; + public uint RegionSizeY; + public uint RegionFlags; + public uint ObjectCapacity; + public UUID RegionUUID; + public string RegionName; - public uint RegionY + public float[] StatsValues { - get { return m_regionY; } + get { return m_statsValues; } } - private uint m_regionY; + private float[] m_statsValues; - public SimStatsPacket.RegionBlock RegionBlock + // a fixed array with the IDs for each viewer relevant stat + // order and size must match StatsIndex enum + public static readonly uint[] StatsIndexID = new uint[] { - get { return m_regionBlock; } - } - private SimStatsPacket.RegionBlock m_regionBlock; + (uint)StatsID.TimeDilation, + (uint)StatsID.SimFPS, + (uint)StatsID.PhysicsFPS, + (uint)StatsID.AgentUpdates, + (uint)StatsID.Agents, + (uint)StatsID.ChildAgents, + (uint)StatsID.TotalPrim, + (uint)StatsID.ActivePrim, + (uint)StatsID.FrameMS, + (uint)StatsID.NetMS, + (uint)StatsID.PhysicsMS, + (uint)StatsID.ImageMS, + (uint)StatsID.OtherMS, + (uint)StatsID.InPacketsPerSecond, + (uint)StatsID.OutPacketsPerSecond, + (uint)StatsID.UnAckedBytes, + (uint)StatsID.AgentMS, + (uint)StatsID.PendingDownloads, + (uint)StatsID.PendingUploads, + (uint)StatsID.ActiveScripts, + (uint)StatsID.SimSleepMs, + (uint)StatsID.SimSpareMs, + (uint)StatsID.SimPhysicsStepMs, + (uint)StatsID.VirtualSizeKb, + (uint)StatsID.ResidentSizeKb, + (uint)StatsID.PendingLocalUploads, + (uint)StatsID.PhysicsPinnedTasks, + (uint)StatsID.PhysicsLodTasks, + (uint)StatsID.ScriptEps, + (uint)StatsID.SimAIStepTimeMS, + (uint)StatsID.SimIoPumpTime, + (uint)StatsID.SimPCTSscriptsRun, + (uint)StatsID.SimRegionIdle, + (uint)StatsID.SimRegionIdlePossible, + (uint)StatsID.SimSkippedSillouet_PS, + (uint)StatsID.SimSkippedCharsPerC, + (uint)StatsID.SimPhysicsMemory, + (uint)StatsID.ScriptMS, - public SimStatsPacket.StatBlock[] StatsBlock - { - get { return m_statsBlock; } - } - private SimStatsPacket.StatBlock[] m_statsBlock; + (uint)StatsID.LSLScriptLinesPerSecond, + (uint)StatsID.SimPhysicsShapeMs, + (uint)StatsID.SimPhysicsOtherMs, - public SimStatsPacket.StatBlock[] ExtraStatsBlock - { - get { return m_extraStatsBlock; } - } - private SimStatsPacket.StatBlock[] m_extraStatsBlock; - - public uint RegionFlags - { - get { return m_regionFlags; } - } - private uint m_regionFlags; - - public uint ObjectCapacity - { - get { return m_objectCapacity; } - } - private uint m_objectCapacity; - - public UUID RegionUUID - { - get { return regionUUID; } - } - private UUID regionUUID; + (uint)StatsID.internalLSLScriptLinesPerSecond, + (uint)StatsID.FrameDilation2, + (uint)StatsID.UsersLoggingIn, + (uint)StatsID.TotalGeoPrim, + (uint)StatsID.TotalMesh, + (uint)StatsID.ScriptEngineThreadCount + }; public SimStats( - uint regionX, uint regionY, uint regionFlags, uint objectCapacity, - SimStatsPacket.RegionBlock regionBlock, SimStatsPacket.StatBlock[] statsBlock, - SimStatsPacket.StatBlock[] ExtraStatsBlock, UUID pRUUID) + uint regionX, uint regionY, + uint regionSizeX, uint regionSizeY, + uint regionFlags, uint objectCapacity, + float[] values, + UUID pRUUID, string regionName) { - regionUUID = pRUUID; - m_regionX = regionX; - m_regionY = regionY; - m_regionFlags = regionFlags; - m_objectCapacity = objectCapacity; - m_regionBlock = regionBlock; - m_statsBlock = statsBlock; - m_extraStatsBlock = ExtraStatsBlock; + RegionUUID = pRUUID; + RegionName = regionName; + RegionX = regionX; + RegionY = regionY; + RegionSizeX = regionSizeX; + RegionSizeY = regionSizeY; + RegionFlags = regionFlags; + ObjectCapacity = objectCapacity; + m_statsValues = values; } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 47c54de967..e4137257fb 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5989,14 +5989,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UIntToBytesSafepos(stats.ObjectCapacity, data, 22); // 26 // stats - data[26] = (byte)stats.StatsBlock.Length; + data[26] = (byte)StatsIndex.ViewerArraySize; int pos = 27; - stats.StatsBlock[15].StatValue /= 1024; // unack is in KB - for (int i = 0; i< stats.StatsBlock.Length; ++i) + int i = 0; + for (; i < (int)StatsIndex.UnAckedBytes; ++i) { - Utils.UIntToBytesSafepos(stats.StatsBlock[i].StatID, data, pos); pos += 4; - Utils.FloatToBytesSafepos(stats.StatsBlock[i].StatValue, data, pos); pos += 4; + Utils.UIntToBytesSafepos(SimStats.StatsIndexID[i], data, pos); pos += 4; + Utils.FloatToBytesSafepos(stats.StatsValues[i], data, pos); pos += 4; + } + + // unack Bytes is in KB + Utils.UIntToBytesSafepos(SimStats.StatsIndexID[i], data, pos); pos += 4; + Utils.FloatToBytesSafepos(stats.StatsValues[i] / 1024, data, pos); pos += 4; + + ++i; + for (; i < (int)StatsIndex.ViewerArraySize; ++i) + { + Utils.UIntToBytesSafepos(SimStats.StatsIndexID[i], data, pos); pos += 4; + Utils.FloatToBytesSafepos(stats.StatsValues[i], data, pos); pos += 4; } //no PID diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index 949dbe64f7..64bf7111c4 100755 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs @@ -159,31 +159,31 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "TimeDilationMonitor", "Time Dilation", - m => m.Scene.StatsReporter.LastReportedSimStats[0], - m => m.GetValue().ToString())); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.TimeDilation], + m => m.GetValue().ToString("0.#"))); m_staticMonitors.Add( new GenericMonitor( m_scene, "SimFPSMonitor", "Sim FPS", - m => m.Scene.StatsReporter.LastReportedSimStats[1], - m => string.Format("{0}", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.SimFPS], + m => m.GetValue().ToString("0.#"))); m_staticMonitors.Add( new GenericMonitor( m_scene, "PhysicsFPSMonitor", "Physics FPS", - m => m.Scene.StatsReporter.LastReportedSimStats[2], - m => string.Format("{0}", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.PhysicsFPS], + m => m.GetValue().ToString("0.#"))); m_staticMonitors.Add( new GenericMonitor( m_scene, "AgentUpdatesPerSecondMonitor", "Agent Updates", - m => m.Scene.StatsReporter.LastReportedSimStats[3], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.AgentUpdates], m => string.Format("{0} per second", m.GetValue()))); m_staticMonitors.Add( @@ -191,23 +191,23 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "ActiveObjectCountMonitor", "Active Objects", - m => m.Scene.StatsReporter.LastReportedSimStats[7], - m => string.Format("{0}", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.ActivePrim], + m => m.GetValue().ToString("0."))); m_staticMonitors.Add( new GenericMonitor( m_scene, "ActiveScriptsMonitor", "Active Scripts", - m => m.Scene.StatsReporter.LastReportedSimStats[19], - m => string.Format("{0}", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.ActiveScripts], + m => m.GetValue().ToString("0."))); m_staticMonitors.Add( new GenericMonitor( m_scene, "ScriptEventsPerSecondMonitor", "Script Events", - m => m.Scene.StatsReporter.LastReportedSimStats[23], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.ScriptEps], m => string.Format("{0} per second", m.GetValue()))); m_staticMonitors.Add( @@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "InPacketsPerSecondMonitor", "In Packets", - m => m.Scene.StatsReporter.LastReportedSimStats[13], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.InPacketsPerSecond], m => string.Format("{0} per second", m.GetValue()))); m_staticMonitors.Add( @@ -223,7 +223,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "OutPacketsPerSecondMonitor", "Out Packets", - m => m.Scene.StatsReporter.LastReportedSimStats[14], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.OutPacketsPerSecond], m => string.Format("{0} per second", m.GetValue()))); m_staticMonitors.Add( @@ -231,7 +231,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "UnackedBytesMonitor", "Unacked Bytes", - m => m.Scene.StatsReporter.LastReportedSimStats[15], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.UnAckedBytes], m => string.Format("{0}", m.GetValue()))); m_staticMonitors.Add( @@ -239,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "PendingDownloadsMonitor", "Pending Downloads", - m => m.Scene.StatsReporter.LastReportedSimStats[17], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.PendingDownloads], m => string.Format("{0}", m.GetValue()))); m_staticMonitors.Add( @@ -247,7 +247,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "PendingUploadsMonitor", "Pending Uploads", - m => m.Scene.StatsReporter.LastReportedSimStats[18], + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.PendingUploads], m => string.Format("{0}", m.GetValue()))); m_staticMonitors.Add( @@ -255,56 +255,56 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring m_scene, "TotalFrameTimeMonitor", "Total Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[8], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.FrameMS], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_staticMonitors.Add( new GenericMonitor( m_scene, "NetFrameTimeMonitor", "Net Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[9], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.NetMS], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_staticMonitors.Add( new GenericMonitor( m_scene, "PhysicsFrameTimeMonitor", "Physics Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[10], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.PhysicsMS], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_staticMonitors.Add( new GenericMonitor( m_scene, "SimulationFrameTimeMonitor", "Simulation Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[12], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.FrameMS], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_staticMonitors.Add( new GenericMonitor( m_scene, "AgentFrameTimeMonitor", "Agent Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[16], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.AgentMS], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_staticMonitors.Add( new GenericMonitor( m_scene, "ImagesFrameTimeMonitor", "Images Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[11], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.ImageMS], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_staticMonitors.Add( new GenericMonitor( m_scene, "SpareFrameTimeMonitor", "Spare Frame Time", - m => m.Scene.StatsReporter.LastReportedSimStats[38], - m => string.Format("{0} ms", m.GetValue()))); + m => m.Scene.StatsReporter.LastReportedSimStats[(int)StatsIndex.SimSpareMs], + m => string.Format("{0:0.###} ms", m.GetValue()))); m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); @@ -409,22 +409,24 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring { MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); }); MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); }); + MakeStat("NPCs", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootNPCCount(); }); MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); }); MakeStat("ActivePrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetActiveObjectsCount(); }); MakeStat("ActiveScripts", "scripts", (s) => { s.Value = m_scene.SceneGraph.GetActiveScriptsCount(); }); - MakeStat("TimeDilation", "sec/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[0]; }); - MakeStat("SimFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[1]; }); - MakeStat("PhysicsFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[2]; }); - MakeStat("AgentUpdates", "updates/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[3]; }); - MakeStat("FrameTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[8]; }); - MakeStat("NetTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[9]; }); - MakeStat("OtherTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[12]; }); - MakeStat("PhysicsTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[10]; }); - MakeStat("AgentTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[16]; }); - MakeStat("ImageTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[11]; }); - MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; }); - MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; }); + float[] data = m_scene.StatsReporter.LastReportedSimStats; + MakeStat("TimeDilation", "", (s) => { s.Value = data[(int)StatsIndex.TimeDilation]; }); + MakeStat("SimFPS", "fps", (s) => { s.Value = data[(int)StatsIndex.SimFPS]; }); + MakeStat("PhysicsFPS", "fps", (s) => { s.Value = data[(int)StatsIndex.PhysicsFPS]; }); + MakeStat("AgentUpdates", "updates/sec", (s) => { s.Value = data[(int)StatsIndex.AgentUpdates]; }); + MakeStat("FrameTime", "ms", (s) => { s.Value = data[(int)StatsIndex.FrameMS]; }); + MakeStat("NetTime", "ms", (s) => { s.Value = data[(int)StatsIndex.NetMS]; }); + MakeStat("OtherTime", "ms", (s) => { s.Value = data[(int)StatsIndex.OtherMS]; }); + MakeStat("PhysicsTime", "ms", (s) => { s.Value = data[(int)StatsIndex.PhysicsMS]; }); + MakeStat("AgentTime", "ms", (s) => { s.Value = data[(int)StatsIndex.Agents]; }); + MakeStat("ImageTime", "ms", (s) => { s.Value = data[(int)StatsIndex.ImageMS]; }); + MakeStat("ScriptEPS", "Events/sec", (s) => { s.Value = data[(int)StatsIndex.ScriptEps]; }); + MakeStat("SimSpareMS", "ms", (s) => { s.Value = data[(int)StatsIndex.SimSpareMs]; }); } private void UnRegisterStatsManagerRegionStatistics() diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index b650635de3..a63f2c7666 100755 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -62,76 +62,8 @@ namespace OpenSim.Region.Framework.Scenes private YourStatsAreWrong handlerStatsIncorrect; - // Determines the size of the array that is used to collect StatBlocks - // for sending viewer compatible stats must be conform with sb array filling below - private const int m_statisticViewerArraySize = 38; // size of LastReportedSimFPS with extra stats. - private const int m_statisticExtraArraySize = (int)(Stats.SimExtraCountEnd - Stats.SimExtraCountStart); - - /// - /// These are the IDs of stats sent in the StatsPacket to the viewer. - /// - /// - /// Some of these are not relevant to OpenSimulator since it is architected differently to other simulators - /// (e.g. script instructions aren't executed as part of the frame loop so 'script time' is tricky). - /// - public enum Stats : uint - { -// viewers defined IDs - TimeDilation = 0, - SimFPS = 1, - PhysicsFPS = 2, - AgentUpdates = 3, - FrameMS = 4, - NetMS = 5, - OtherMS = 6, - PhysicsMS = 7, - AgentMS = 8, - ImageMS = 9, - ScriptMS = 10, - TotalPrim = 11, - ActivePrim = 12, - Agents = 13, - ChildAgents = 14, - ActiveScripts = 15, - LSLScriptLinesPerSecond = 16, // viewers don't like this anymore - InPacketsPerSecond = 17, - OutPacketsPerSecond = 18, - PendingDownloads = 19, - PendingUploads = 20, - VirtualSizeKb = 21, - ResidentSizeKb = 22, - PendingLocalUploads = 23, - UnAckedBytes = 24, - PhysicsPinnedTasks = 25, - PhysicsLodTasks = 26, - SimPhysicsStepMs = 27, - SimPhysicsShapeMs = 28, - SimPhysicsOtherMs = 29, - SimPhysicsMemory = 30, - ScriptEps = 31, - SimSpareMs = 32, - SimSleepMs = 33, - SimIoPumpTime = 34, - SimPCTSscriptsRun = 35, - SimRegionIdle = 36, // dataserver only - SimRegionIdlePossible = 37, // dataserver only - SimAIStepTimeMS = 38, - SimSkippedSillouet_PS = 39, - SimSkippedCharsPerC = 40, - -// extra stats IDs irrelevant, just far from viewer defined ones - SimExtraCountStart = 1000, - - internalLSLScriptLinesPerSecond = 1000, - FrameDilation2 = 1001, - UsersLoggingIn = 1002, - TotalGeoPrim = 1003, - TotalMesh = 1004, - ThreadCount = 1005, - - SimExtraCountEnd = 1006 - } + private const int m_statisticExtraArraySize = (int)(StatsIndex.ArraySize - StatsIndex.ViewerArraySize); /// /// This is for llGetRegionFPS @@ -201,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes private float m_targetFrameTime = 0.1f; // saved last reported value so there is something available for llGetRegionFPS private float lastReportedSimFPS; - private float[] lastReportedSimStats = new float[m_statisticExtraArraySize + m_statisticViewerArraySize]; + private float[] lastReportedSimStats = new float[(int)StatsIndex.ViewerArraySize]; private float m_pfps; /// @@ -342,10 +274,8 @@ namespace OpenSim.Region.Framework.Scenes if(Monitor.TryEnter(m_statsLock)) { // m_log.Debug("Firing Stats Heart Beat"); + float[] newvalues = new float[(int)StatsIndex.ArraySize]; - SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[m_statisticViewerArraySize]; - SimStatsPacket.StatBlock[] sbex = new SimStatsPacket.StatBlock[m_statisticExtraArraySize]; - SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); uint regionFlags = 0; try @@ -367,7 +297,6 @@ namespace OpenSim.Region.Framework.Scenes // factor to consider updates integration time float updateTimeFactor = 1.0f / updateElapsed; - // scene frame stats float reportedFPS; float physfps; @@ -463,178 +392,51 @@ namespace OpenSim.Region.Framework.Scenes // so that stat numbers are always consistent. CheckStatSanity(); - for (int i = 0; i < m_statisticViewerArraySize; i++) - { - sb[i] = new SimStatsPacket.StatBlock(); - } - - sb[0].StatID = (uint) Stats.TimeDilation; - sb[0].StatValue = (Single.IsNaN(timeDilation)) ? 0.0f : (float)Math.Round(timeDilation,3); - - sb[1].StatID = (uint) Stats.SimFPS; - sb[1].StatValue = (float)Math.Round(reportedFPS,1);; - - sb[2].StatID = (uint) Stats.PhysicsFPS; - sb[2].StatValue = (float)Math.Round(physfps,1); - - sb[3].StatID = (uint) Stats.AgentUpdates; - sb[3].StatValue = m_agentUpdates * updateTimeFactor; - - sb[4].StatID = (uint) Stats.Agents; - sb[4].StatValue = m_rootAgents; - - sb[5].StatID = (uint) Stats.ChildAgents; - sb[5].StatValue = m_childAgents; - - sb[6].StatID = (uint) Stats.TotalPrim; - sb[6].StatValue = m_numPrim; - - sb[7].StatID = (uint) Stats.ActivePrim; - sb[7].StatValue = m_activePrim; - - sb[8].StatID = (uint)Stats.FrameMS; - sb[8].StatValue = totalFrameTime; - - sb[9].StatID = (uint)Stats.NetMS; - sb[9].StatValue = m_netMS * perframefactor; - - sb[10].StatID = (uint)Stats.PhysicsMS; - sb[10].StatValue = physicsMS; - - sb[11].StatID = (uint)Stats.ImageMS ; - sb[11].StatValue = m_imageMS * perframefactor; - - sb[12].StatID = (uint)Stats.OtherMS; - sb[12].StatValue = otherMS; - - sb[13].StatID = (uint)Stats.InPacketsPerSecond; - sb[13].StatValue = (float)Math.Round(m_inPacketsPerSecond * updateTimeFactor); - - sb[14].StatID = (uint)Stats.OutPacketsPerSecond; - sb[14].StatValue = (float)Math.Round(m_outPacketsPerSecond * updateTimeFactor); - - sb[15].StatID = (uint)Stats.UnAckedBytes; - sb[15].StatValue = m_unAckedBytes; - - sb[16].StatID = (uint)Stats.AgentMS; - sb[16].StatValue = agentMS; - - sb[17].StatID = (uint)Stats.PendingDownloads; - sb[17].StatValue = m_pendingDownloads; - - sb[18].StatID = (uint)Stats.PendingUploads; - sb[18].StatValue = m_pendingUploads; - - sb[19].StatID = (uint)Stats.ActiveScripts; - sb[19].StatValue = m_activeScripts; - - sb[20].StatID = (uint)Stats.SimSleepMs; - sb[20].StatValue = sleeptime; - - sb[21].StatID = (uint)Stats.SimSpareMs; - sb[21].StatValue = sparetime; - - // this should came from phys engine - sb[22].StatID = (uint)Stats.SimPhysicsStepMs; - sb[22].StatValue = 20; - - // send the ones we dont have as zeros, to clean viewers state - // specially arriving from regions with wrond IDs in use - - sb[23].StatID = (uint)Stats.VirtualSizeKb; - sb[23].StatValue = 0; - - sb[24].StatID = (uint)Stats.ResidentSizeKb; - sb[24].StatValue = 0; - - sb[25].StatID = (uint)Stats.PendingLocalUploads; - sb[25].StatValue = 0; - - sb[26].StatID = (uint)Stats.PhysicsPinnedTasks; - sb[26].StatValue = 0; - - sb[27].StatID = (uint)Stats.PhysicsLodTasks; - sb[27].StatValue = 0; - - sb[28].StatID = (uint)Stats.ScriptEps; // we actually have this, but not messing array order AGAIN - sb[28].StatValue = (float)Math.Round(m_scriptEventsPerSecond * updateTimeFactor); - - sb[29].StatID = (uint)Stats.SimAIStepTimeMS; - sb[29].StatValue = 0; - - sb[30].StatID = (uint)Stats.SimIoPumpTime; - sb[30].StatValue = 0; - - sb[31].StatID = (uint)Stats.SimPCTSscriptsRun; - sb[31].StatValue = 0; - - sb[32].StatID = (uint)Stats.SimRegionIdle; - sb[32].StatValue = 0; - - sb[33].StatID = (uint)Stats.SimRegionIdlePossible; - sb[33].StatValue = 0; - - sb[34].StatID = (uint)Stats.SimSkippedSillouet_PS; - sb[34].StatValue = 0; - - sb[35].StatID = (uint)Stats.SimSkippedCharsPerC; - sb[35].StatValue = 0; - - sb[36].StatID = (uint)Stats.SimPhysicsMemory; - sb[36].StatValue = 0; - - sb[37].StatID = (uint)Stats.ScriptMS; - sb[37].StatValue = scriptTimeMS; - - for (int i = 0; i < m_statisticViewerArraySize; i++) - { - lastReportedSimStats[i] = sb[i].StatValue; - } - + newvalues[(int)StatsIndex.TimeDilation] = (Single.IsNaN(timeDilation)) ? 0.0f : (float)Math.Round(timeDilation, 3); + newvalues[(int)StatsIndex.SimFPS] = (float)Math.Round(reportedFPS, 1); + newvalues[(int)StatsIndex.PhysicsFPS] = (float)Math.Round(physfps, 1); + newvalues[(int)StatsIndex.AgentUpdates] = m_agentUpdates * updateTimeFactor; + newvalues[(int)StatsIndex.Agents] = m_rootAgents; + newvalues[(int)StatsIndex.ChildAgents] = m_childAgents; + newvalues[(int)StatsIndex.TotalPrim] = m_numPrim; + newvalues[(int)StatsIndex.ActivePrim] = m_activePrim; + newvalues[(int)StatsIndex.FrameMS] = totalFrameTime; + newvalues[(int)StatsIndex.NetMS] = (float)Math.Round(m_netMS * perframefactor, 3); + newvalues[(int)StatsIndex.PhysicsMS] = (float)Math.Round(physicsMS, 3); + newvalues[(int)StatsIndex.ImageMS] = (float)Math.Round(m_imageMS * perframefactor, 3); + newvalues[(int)StatsIndex.OtherMS] = (float)Math.Round(otherMS, 3); + newvalues[(int)StatsIndex.InPacketsPerSecond] = (float)Math.Round(m_inPacketsPerSecond * updateTimeFactor); + newvalues[(int)StatsIndex.OutPacketsPerSecond] = (float)Math.Round(m_outPacketsPerSecond * updateTimeFactor); + newvalues[(int)StatsIndex.UnAckedBytes] = m_unAckedBytes; + newvalues[(int)StatsIndex.AgentMS] = agentMS; + newvalues[(int)StatsIndex.PendingDownloads] = m_pendingDownloads; + newvalues[(int)StatsIndex.PendingUploads] = m_pendingUploads; + newvalues[(int)StatsIndex.ActiveScripts] = m_activeScripts; + newvalues[(int)StatsIndex.SimSleepMs] = (float)Math.Round(sleeptime, 3); + newvalues[(int)StatsIndex.SimSpareMs] = (float)Math.Round(sparetime, 3); + newvalues[(int)StatsIndex.SimPhysicsStepMs] = 20; // this should came from phys engine + newvalues[(int)StatsIndex.ScriptMS] = scriptTimeMS; // add extra stats for internal use + newvalues[(int)StatsIndex.LSLScriptLinesPerSecond] = (float)Math.Round(m_scriptLinesPerSecond * updateTimeFactor, 3); + newvalues[(int)StatsIndex.FrameDilation2] = (Single.IsNaN(timeDilation)) ? 0.1f : (float)Math.Round(timeDilation, 1); + newvalues[(int)StatsIndex.UsersLoggingIn] = m_usersLoggingIn; + newvalues[(int)StatsIndex.TotalGeoPrim] = m_numGeoPrim; + newvalues[(int)StatsIndex.TotalMesh] = m_numMesh; + newvalues[(int)StatsIndex.ScriptEngineThreadCount] = m_inUseThreads; - for (int i = 0; i < m_statisticExtraArraySize; i++) - { - sbex[i] = new SimStatsPacket.StatBlock(); - } + lastReportedSimStats = newvalues; - sbex[0].StatID = (uint)Stats.LSLScriptLinesPerSecond; - sbex[0].StatValue = m_scriptLinesPerSecond * updateTimeFactor; - lastReportedSimStats[38] = m_scriptLinesPerSecond * updateTimeFactor; + OnSendStatsResult?.Invoke(new SimStats( + ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, + ReportingRegion.RegionSizeX, ReportingRegion.RegionSizeY, + regionFlags, (uint)m_objectCapacity, + newvalues, + m_scene.RegionInfo.originRegionID, + m_scene.RegionInfo.RegionName) + ); - sbex[1].StatID = (uint)Stats.FrameDilation2; - sbex[1].StatValue = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation; - lastReportedSimStats[39] = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation; - - sbex[2].StatID = (uint)Stats.UsersLoggingIn; - sbex[2].StatValue = m_usersLoggingIn; - lastReportedSimStats[40] = m_usersLoggingIn; - - sbex[3].StatID = (uint)Stats.TotalGeoPrim; - sbex[3].StatValue = m_numGeoPrim; - lastReportedSimStats[41] = m_numGeoPrim; - - sbex[4].StatID = (uint)Stats.TotalMesh; - sbex[4].StatValue = m_numMesh; - lastReportedSimStats[42] = m_numMesh; - - sbex[5].StatID = (uint)Stats.ThreadCount; - sbex[5].StatValue = m_inUseThreads; - lastReportedSimStats[43] = m_inUseThreads; - - SimStats simStats - = new SimStats( - ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, - rb, sb, sbex, m_scene.RegionInfo.originRegionID); - - handlerSendStatResult = OnSendStatsResult; - if (handlerSendStatResult != null) - { - handlerSendStatResult(simStats); - } - - // Extra statistics that aren't currently sent to clients + // Extra statistics that aren't currently sent elsewhere if (m_scene.PhysicsScene != null) { lock (m_lastReportedExtraSimStats) diff --git a/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs b/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs index e2c3192d8f..e0fdf7c71c 100644 --- a/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs @@ -1177,27 +1177,27 @@ VALUES public void ConsumeSimStats(SimStats stats) { m_regionID = stats.RegionUUID; - m_timeDilation = stats.StatsBlock[0].StatValue; - m_simFps = stats.StatsBlock[1].StatValue; - m_physicsFps = stats.StatsBlock[2].StatValue; - m_agentUpdates = stats.StatsBlock[3].StatValue; - m_rootAgents = stats.StatsBlock[4].StatValue; - m_childAgents = stats.StatsBlock[5].StatValue; - m_totalPrims = stats.StatsBlock[6].StatValue; - m_activePrims = stats.StatsBlock[7].StatValue; - m_totalFrameTime = stats.StatsBlock[8].StatValue; - m_netFrameTime = stats.StatsBlock[9].StatValue; - m_physicsFrameTime = stats.StatsBlock[10].StatValue; - m_otherFrameTime = stats.StatsBlock[11].StatValue; - m_imageFrameTime = stats.StatsBlock[12].StatValue; - m_inPacketsPerSecond = stats.StatsBlock[13].StatValue; - m_outPacketsPerSecond = stats.StatsBlock[14].StatValue; - m_unackedBytes = stats.StatsBlock[15].StatValue; - m_agentFrameTime = stats.StatsBlock[16].StatValue; - m_pendingDownloads = stats.StatsBlock[17].StatValue; - m_pendingUploads = stats.StatsBlock[18].StatValue; - m_activeScripts = stats.StatsBlock[19].StatValue; - m_scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue; + m_timeDilation = stats.StatsValues[(int)StatsIndex.TimeDilation]; + m_simFps = stats.StatsValues[(int)StatsIndex.SimFPS]; + m_physicsFps = stats.StatsValues[(int)StatsIndex.PhysicsFPS]; + m_agentUpdates = stats.StatsValues[(int)StatsIndex.AgentUpdates]; + m_rootAgents = stats.StatsValues[(int)StatsIndex.Agents]; + m_childAgents = stats.StatsValues[(int)StatsIndex.ChildAgents]; + m_totalPrims = stats.StatsValues[(int)StatsIndex.TotalPrim]; + m_activePrims = stats.StatsValues[(int)StatsIndex.ActivePrim]; + m_totalFrameTime = stats.StatsValues[(int)StatsIndex.FrameMS]; + m_netFrameTime = stats.StatsValues[(int)StatsIndex.NetMS]; + m_physicsFrameTime = stats.StatsValues[(int)StatsIndex.PhysicsMS]; + m_otherFrameTime = stats.StatsValues[(int)StatsIndex.OtherMS]; + m_imageFrameTime = stats.StatsValues[(int)StatsIndex.ImageMS]; + m_inPacketsPerSecond = stats.StatsValues[(int)StatsIndex.InPacketsPerSecond]; + m_outPacketsPerSecond = stats.StatsValues[(int)StatsIndex.OutPacketsPerSecond]; + m_unackedBytes = stats.StatsValues[(int)StatsIndex.UnAckedBytes]; + m_agentFrameTime = stats.StatsValues[(int)StatsIndex.AgentMS]; + m_pendingDownloads = stats.StatsValues[(int)StatsIndex.PendingDownloads]; + m_pendingUploads = stats.StatsValues[(int)StatsIndex.PendingUploads]; + m_activeScripts = stats.StatsValues[(int)StatsIndex.ActiveScripts]; + m_scriptLinesPerSecond = stats.StatsValues[(int)StatsIndex.LSLScriptLinesPerSecond]; } } } \ No newline at end of file