diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs index 3243a9a952..6a1112ce41 100644 --- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs +++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs @@ -32,6 +32,7 @@ using System.Reflection; using System.Text; using Mono.Data.SqliteClient; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Framework.Monitoring; @@ -51,7 +52,6 @@ namespace OpenSim.Region.UserStatistics public Hashtable ProcessModel(Hashtable pParams) { - List m_scene = (List)pParams["Scenes"]; Hashtable nh = new Hashtable(); @@ -129,6 +129,86 @@ namespace OpenSim.Region.UserStatistics return output.ToString(); } + /// + /// Convert active connections information to JSON string. Returns a structure: + ///
+        /// {"regionName": {
+        ///     "presenceName": {
+        ///         "name": "presenceName",
+        ///         "position": "",
+        ///         "isRoot": "false",
+        ///         "throttle": {
+        ///         },
+        ///         "queue": {
+        ///         }
+        ///     },
+        ///     ... // multiple presences in the scene
+        ///   },
+        ///   ...   // multiple regions in the sim
+        /// }
+        ///
+        /// 
+ ///
+ /// + /// + public string RenderJson(Hashtable pModelResult) + { + List all_scenes = (List) pModelResult["hdata"]; + + OSDMap regionInfo = new OSDMap(); + foreach (Scene scene in all_scenes) + { + OSDMap sceneInfo = new OpenMetaverse.StructuredData.OSDMap(); + List avatarInScene = scene.GetScenePresences(); + foreach (ScenePresence av in avatarInScene) + { + OSDMap presenceInfo = new OSDMap(); + presenceInfo.Add("Name", new OSDString(av.Name)); + + Dictionary queues = new Dictionary(); + if (av.ControllingClient is IStatsCollector) + { + IStatsCollector isClient = (IStatsCollector) av.ControllingClient; + queues = decodeQueueReport(isClient.Report()); + } + OSDMap queueInfo = new OpenMetaverse.StructuredData.OSDMap(); + foreach (KeyValuePair kvp in queues) { + queueInfo.Add(kvp.Key, new OSDString(kvp.Value)); + } + sceneInfo.Add("queues", queueInfo); + + if (av.IsChildAgent) + presenceInfo.Add("isRoot", new OSDString("false")); + else + presenceInfo.Add("isRoot", new OSDString("true")); + + if (av.AbsolutePosition == DefaultNeighborPosition) + { + presenceInfo.Add("position", new OSDString("<0, 0, 0>")); + } + else + { + presenceInfo.Add("position", new OSDString(string.Format("<{0},{1},{2}>", + (int)av.AbsolutePosition.X, + (int) av.AbsolutePosition.Y, + (int) av.AbsolutePosition.Z)) ); + } + + Dictionary throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1)); + OSDMap throttleInfo = new OpenMetaverse.StructuredData.OSDMap(); + foreach (string throttlename in throttles.Keys) + { + throttleInfo.Add(throttlename, new OSDString(throttles[throttlename].ToString())); + } + presenceInfo.Add("throttle", throttleInfo); + + sceneInfo.Add(av.Name, presenceInfo); + } + regionInfo.Add(scene.RegionInfo.RegionName, sceneInfo); + } + return regionInfo.ToString(); + } + public Dictionary DecodeClientThrottles(byte[] throttle) { Dictionary returndict = new Dictionary(); @@ -203,7 +283,7 @@ namespace OpenSim.Region.UserStatistics returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++; returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++; returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++; - returndic.Add("Asset", rep.Substring((7 * pos), 8)); + returndic.Add("Asset", rep.Substring((7 * pos), 8)); /* * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", SendQueue.Count(), diff --git a/OpenSim/Region/UserStatistics/Clients_report.cs b/OpenSim/Region/UserStatistics/Clients_report.cs index b2bb33bf84..4a6f7bea8d 100644 --- a/OpenSim/Region/UserStatistics/Clients_report.cs +++ b/OpenSim/Region/UserStatistics/Clients_report.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Text; using Mono.Data.SqliteClient; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.UserStatistics @@ -44,6 +45,32 @@ namespace OpenSim.Region.UserStatistics get { return "Client"; } } + /// + /// Return summar information in the form: + ///
+        /// {"totalUsers": "34",
+        ///  "totalSessions": "233",
+        ///  ...
+        /// }
+        /// 
+ ///
+ /// + /// + public string RenderJson(Hashtable pModelResult) { + stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"]; + + OSDMap summaryInfo = new OpenMetaverse.StructuredData.OSDMap(); + summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString())); + summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString())); + summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString())); + summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString())); + summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString())); + summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString())); + summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString())); + summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString())); + return summaryInfo.ToString(); + } + public Hashtable ProcessModel(Hashtable pParams) { SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"]; diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs index cdc615caff..fabe3d4632 100644 --- a/OpenSim/Region/UserStatistics/Default_Report.cs +++ b/OpenSim/Region/UserStatistics/Default_Report.cs @@ -32,6 +32,7 @@ using System.Reflection; using System.Text; using Mono.Data.SqliteClient; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Region.Framework.Scenes; using OpenSim.Framework.Monitoring; @@ -230,6 +231,31 @@ TD.align_top { vertical-align: top; } return returnstruct; } + /// + /// Return summar information in the form: + ///
+        /// {"totalUsers": "34",
+        ///  "totalSessions": "233",
+        ///  ...
+        /// }
+        /// 
+ ///
+ /// + /// + public string RenderJson(Hashtable pModelResult) { + stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"]; + + OSDMap summaryInfo = new OSDMap(); + summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString())); + summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString())); + summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString())); + summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString())); + summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString())); + summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString())); + summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString())); + summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString())); + return summaryInfo.ToString(); + } } public struct stats_default_page_values @@ -247,4 +273,5 @@ TD.align_top { vertical-align: top; } public Dictionary sim_stat_data; public Dictionary stats_reports; } + } diff --git a/OpenSim/Region/UserStatistics/IStatsReport.cs b/OpenSim/Region/UserStatistics/IStatsReport.cs index e0ecce4c5c..80c44874e9 100644 --- a/OpenSim/Region/UserStatistics/IStatsReport.cs +++ b/OpenSim/Region/UserStatistics/IStatsReport.cs @@ -34,5 +34,6 @@ namespace OpenSim.Region.UserStatistics string ReportName { get; } Hashtable ProcessModel(Hashtable pParams); string RenderView(Hashtable pModelResult); + string RenderJson(Hashtable pModelResult); } } diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs index 74de46b227..4d45b80b06 100644 --- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs +++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs @@ -33,6 +33,7 @@ using System.Text; using System.Text.RegularExpressions; using Mono.Data.SqliteClient; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Region.Framework.Scenes; using OpenSim.Framework.Monitoring; @@ -125,6 +126,34 @@ namespace OpenSim.Region.UserStatistics return output.ToString(); } + /// + /// Return the last log lines. Output in the format: + ///
+        /// {"logLines": [
+        /// "line1",
+        /// "line2",
+        /// ...
+        /// ]
+        /// }
+        /// 
+ ///
+ /// + /// + public string RenderJson(Hashtable pModelResult) + { + OSDMap logInfo = new OpenMetaverse.StructuredData.OSDMap(); + + OSDArray logLines = new OpenMetaverse.StructuredData.OSDArray(); + string tmp = normalizeEndLines.Replace(pModelResult["loglines"].ToString(), "\n"); + string[] result = Regex.Split(tmp, "\n"); + for (int i = 0; i < result.Length; i++) + { + logLines.Add(new OSDString(result[i])); + } + logInfo.Add("logLines", logLines); + return logInfo.ToString(); + } + #endregion } } diff --git a/OpenSim/Region/UserStatistics/Prototype_distributor.cs b/OpenSim/Region/UserStatistics/Prototype_distributor.cs index 53ae557769..6f8b2aa634 100644 --- a/OpenSim/Region/UserStatistics/Prototype_distributor.cs +++ b/OpenSim/Region/UserStatistics/Prototype_distributor.cs @@ -36,7 +36,18 @@ namespace OpenSim.Region.UserStatistics { public class Prototype_distributor : IStatsController { - private string prototypejs=string.Empty; + private string jsFileName = "prototype.js"; + private string prototypejs = string.Empty; + + public Prototype_distributor() + { + jsFileName = "prototype.js"; + } + + public Prototype_distributor(string jsName) + { + jsFileName = jsName; + } public string ReportName { @@ -45,20 +56,24 @@ namespace OpenSim.Region.UserStatistics public Hashtable ProcessModel(Hashtable pParams) { Hashtable pResult = new Hashtable(); - if (prototypejs.Length == 0) - { - StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/prototype.js", FileMode.Open)); - prototypejs = fs.ReadToEnd(); - fs.Close(); - fs.Dispose(); - } - pResult["js"] = prototypejs; + pResult["js"] = jsFileName; return pResult; } public string RenderView(Hashtable pModelResult) { - return pModelResult["js"].ToString(); + string fileName = (string)pModelResult["js"]; + using (StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/" + fileName, FileMode.Open))) + { + prototypejs = fs.ReadToEnd(); + fs.Close(); + } + return prototypejs; + } + + public string RenderJson(Hashtable pModelResult) + { + return "{}"; } } diff --git a/OpenSim/Region/UserStatistics/Sessions_Report.cs b/OpenSim/Region/UserStatistics/Sessions_Report.cs index 1a2d460c76..0e94912ee4 100644 --- a/OpenSim/Region/UserStatistics/Sessions_Report.cs +++ b/OpenSim/Region/UserStatistics/Sessions_Report.cs @@ -278,6 +278,11 @@ TD.align_top { vertical-align: top; } public DateTime start_time; } + public string RenderJson(Hashtable pModelResult) + { + return "{}"; + } #endregion } + } diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs index 28051fb674..ad848a1330 100644 --- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs +++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs @@ -32,6 +32,7 @@ using System.Reflection; using System.Text; using Mono.Data.SqliteClient; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Region.Framework.Scenes; using OpenSim.Framework.Monitoring; @@ -218,6 +219,64 @@ namespace OpenSim.Region.UserStatistics return output.ToString(); } + /// + /// Return stat information for all regions in the sim. Returns data of the form: + ///
+        /// {"REGIONNAME": {
+        ///     "region": "REGIONNAME",
+        ///     "timeDilation": "101", 
+        ///     ...     // the rest of the stat info
+        ///     },
+        ///  ...    // entries for each region
+        ///  }
+        /// 
+ ///
+ /// + /// + public string RenderJson(Hashtable pModelResult) + { + List all_scenes = (List) pModelResult["hdata"]; + Dictionary sdatadic = (Dictionary)pModelResult["simstats"]; + + OSDMap allStatsInfo = new OpenMetaverse.StructuredData.OSDMap(); + foreach (USimStatsData sdata in sdatadic.Values) + { + OSDMap statsInfo = new OpenMetaverse.StructuredData.OSDMap(); + string regionName = "unknown"; + foreach (Scene sn in all_scenes) + { + if (sn.RegionInfo.RegionID == sdata.RegionId) + { + regionName = sn.RegionInfo.RegionName; + break; + } + } + statsInfo.Add("region", new OSDString(regionName)); + statsInfo.Add("timeDilation", new OSDString(sdata.TimeDilation.ToString())); + statsInfo.Add("simFPS", new OSDString(sdata.SimFps.ToString())); + statsInfo.Add("physicsFPS", new OSDString(sdata.PhysicsFps.ToString())); + statsInfo.Add("agentUpdates", new OSDString(sdata.AgentUpdates.ToString())); + statsInfo.Add("rootAgents", new OSDString(sdata.RootAgents.ToString())); + statsInfo.Add("childAgents", new OSDString(sdata.ChildAgents.ToString())); + statsInfo.Add("totalPrims", new OSDString(sdata.TotalPrims.ToString())); + statsInfo.Add("activePrims", new OSDString(sdata.ActivePrims.ToString())); + statsInfo.Add("activeScripts", new OSDString(sdata.ActiveScripts.ToString())); + statsInfo.Add("scriptLinesPerSec", new OSDString(sdata.ScriptLinesPerSecond.ToString())); + statsInfo.Add("totalFrameTime", new OSDString(sdata.TotalFrameTime.ToString())); + statsInfo.Add("agentFrameTime", new OSDString(sdata.AgentFrameTime.ToString())); + statsInfo.Add("physicsFrameTime", new OSDString(sdata.PhysicsFrameTime.ToString())); + statsInfo.Add("otherFrameTime", new OSDString(sdata.OtherFrameTime.ToString())); + statsInfo.Add("outPacketsPerSec", new OSDString(sdata.OutPacketsPerSecond.ToString())); + statsInfo.Add("inPacketsPerSec", new OSDString(sdata.InPacketsPerSecond.ToString())); + statsInfo.Add("unackedByptes", new OSDString(sdata.UnackedBytes.ToString())); + statsInfo.Add("pendingDownloads", new OSDString(sdata.PendingDownloads.ToString())); + statsInfo.Add("pendingUploads", new OSDString(sdata.PendingUploads.ToString())); + + allStatsInfo.Add(regionName, statsInfo); + } + return allStatsInfo.ToString(); + } + #endregion } } diff --git a/OpenSim/Region/UserStatistics/Updater_distributor.cs b/OpenSim/Region/UserStatistics/Updater_distributor.cs index 9593cc915c..601e06b65c 100644 --- a/OpenSim/Region/UserStatistics/Updater_distributor.cs +++ b/OpenSim/Region/UserStatistics/Updater_distributor.cs @@ -62,5 +62,9 @@ namespace OpenSim.Region.UserStatistics return pModelResult["js"].ToString(); } + public string RenderJson(Hashtable pModelResult) { + return "{}"; + } + } } \ No newline at end of file diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index 64cb577350..438ef485ab 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -121,6 +121,10 @@ namespace OpenSim.Region.UserStatistics reports.Add("clients.report", clientReport); reports.Add("sessions.report", sessionsReport); + reports.Add("sim.css", new Prototype_distributor("sim.css")); + reports.Add("sim.html", new Prototype_distributor("sim.html")); + reports.Add("jquery.js", new Prototype_distributor("jquery.js")); + //// // Add Your own Reports here (Do Not Modify Lines here Devs!) //// @@ -255,9 +259,12 @@ namespace OpenSim.Region.UserStatistics string regpath = request["uri"].ToString(); int response_code = 404; string contenttype = "text/html"; + bool jsonFormatOutput = false; string strOut = string.Empty; + // The request patch should be "/SStats/reportName" where 'reportName' + // is one of the names added to the 'reports' hashmap. regpath = regpath.Remove(0, 8); if (regpath.Length == 0) regpath = "default.report"; if (reports.ContainsKey(regpath)) @@ -265,6 +272,9 @@ namespace OpenSim.Region.UserStatistics IStatsController rep = reports[regpath]; Hashtable repParams = new Hashtable(); + if (request.ContainsKey("json")) + jsonFormatOutput = true; + if (request.ContainsKey("requestvars")) repParams["RequestVars"] = request["requestvars"]; else @@ -284,13 +294,26 @@ namespace OpenSim.Region.UserStatistics concurrencyCounter++; - strOut = rep.RenderView(rep.ProcessModel(repParams)); + if (jsonFormatOutput) + { + strOut = rep.RenderJson(rep.ProcessModel(repParams)); + contenttype = "text/json"; + } + else + { + strOut = rep.RenderView(rep.ProcessModel(repParams)); + } if (regpath.EndsWith("js")) { contenttype = "text/javascript"; } + if (regpath.EndsWith("css")) + { + contenttype = "text/css"; + } + concurrencyCounter--; response_code = 200; diff --git a/bin/data/LICENSE-README-IMPORTANT.txt b/bin/data/LICENSE-README-IMPORTANT.txt index 86e401f302..a1ac20cf05 100644 --- a/bin/data/LICENSE-README-IMPORTANT.txt +++ b/bin/data/LICENSE-README-IMPORTANT.txt @@ -2,4 +2,4 @@ Not all of the files in this directory are licensed under the BSD license. Some These files are: -- avataranimations.xml (Derivative work of viewerart.ini, Creative Commons Attribution+Share-Alike v2.5 License) \ No newline at end of file +- avataranimations.xml (Derivative work of viewerart.ini, Creative Commons Attribution+Share-Alike v2.5 License) diff --git a/bin/data/sim.css b/bin/data/sim.css new file mode 100644 index 0000000000..e584a1ab44 --- /dev/null +++ b/bin/data/sim.css @@ -0,0 +1,85 @@ +body { + font-family: Veranda,Arial,Helvetica,sans-serif; + font-size: 12px; + background: #4A5F6D; + color: #EEEAD6; + padding: 0px; + margin: 0px; +} +.footer { + font-family: Veranda,Arial,Helvetica,sans-serif; + font-size: 10px; +} +td { + font-family: Veranda,Arial,Helvetica,sans-serif; + font-size: 12px; + padding: 4px; + margin: 4px; +} +blockquote { + font-family: Veranda,Arial,Helvetica,sans-serif; + font-style: italic; + font-size: 12px; +} +pre { + padding: 5px; + background-color: #8080B0; + color: #000000; + margin-left: 20px; + font-size: 11px; +} +:link { + color: #ffffff; +} +:visited { + color: #d0d0d0; +} +.SimSectionHeader { + font-size: 120%; +} +div.SimSectionContainer { + padding: 10px 0px 0px 20px; +} +/* SimStats ===================================== */ +#SimSimStats div { + margin-left: 20px; + background: #3A4F5D; +} +#SimSimStats table td { + text-align: right; + padding: 0px 0px 0px 5px; + margin: 0px 0px 0px 0px; +} +/* Region Stats ===================================== */ +#SimRegionStats div { + margin-left: 20px; + background: #3A4F5D; +} +#SimRegionStats table { + border: 1px; + border-style: solid; +} +#SimRegionStats table td { + text-align: right; + padding: 0px 0px 0px 5px; + margin: 0px 0px 0px 0px; +} +/* Session Stats ===================================== */ +#SimSessionStats div { + margin-left: 20px; + background: #3A4F5D; +} +#SimSessionStats table td { + text-align: right; + padding: 0px 0px 0px 5px; + margin: 0px 0px 0px 0px; +} +/* LogFile ===================================== */ +#SimLogFile div { + margin-left: 20px; +} +#SimLogFile table td { + text-align: right; + padding: 0px 0px 0px 5px; + margin: 0px 0px 0px 0px; +} diff --git a/bin/data/sim.html b/bin/data/sim.html new file mode 100644 index 0000000000..82d4789caa --- /dev/null +++ b/bin/data/sim.html @@ -0,0 +1,291 @@ + + + +Simulator statistics + + + + + + + + + +
+
+ + + + + +
+Region Stats +
+
+
+ + +
+Sessions +
+
+
+ + +
+Log File +
+
+
+ + +
+
+
+ +