From 427ab219b8ecf7f039d03ed3067e183db1434fb2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 24 Jan 2013 10:44:57 -0800 Subject: Add JSONification of WebStats module. Adds a '?json' query parameter to the fetch URL to return the data in JSON format. Also adds a simple 'sim.html' that uses JavaScript to display the JSON data. Not pretty but an example. --- .../Region/UserStatistics/ActiveConnectionsAJAX.cs | 84 +++++++++++++++++++++- OpenSim/Region/UserStatistics/Clients_report.cs | 27 +++++++ OpenSim/Region/UserStatistics/Default_Report.cs | 27 +++++++ OpenSim/Region/UserStatistics/IStatsReport.cs | 1 + OpenSim/Region/UserStatistics/LogLinesAJAX.cs | 29 ++++++++ .../Region/UserStatistics/Prototype_distributor.cs | 31 +++++--- OpenSim/Region/UserStatistics/Sessions_Report.cs | 5 ++ OpenSim/Region/UserStatistics/SimStatsAJAX.cs | 59 +++++++++++++++ .../Region/UserStatistics/Updater_distributor.cs | 4 ++ OpenSim/Region/UserStatistics/WebStatsModule.cs | 25 ++++++- 10 files changed, 281 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs index 3243a9a..6a1112c 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 b2bb33b..4a6f7be 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 cdc615c..fabe3d4 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 e0ecce4..80c4487 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 74de46b..4d45b80 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 53ae557..6f8b2aa 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) + pResult["js"] = jsFileName; + return pResult; + } + + public string RenderView(Hashtable pModelResult) + { + string fileName = (string)pModelResult["js"]; + using (StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/" + fileName, FileMode.Open))) { - StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/prototype.js", FileMode.Open)); prototypejs = fs.ReadToEnd(); fs.Close(); - fs.Dispose(); } - pResult["js"] = prototypejs; - return pResult; + return prototypejs; } - public string RenderView(Hashtable pModelResult) + public string RenderJson(Hashtable pModelResult) { - return pModelResult["js"].ToString(); + return "{}"; } } diff --git a/OpenSim/Region/UserStatistics/Sessions_Report.cs b/OpenSim/Region/UserStatistics/Sessions_Report.cs index 1a2d460..0e94912 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 28051fb..ad848a1 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 9593cc9..601e06b 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 64cb577..438ef48 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; -- cgit v1.1