diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs index 9451932a94..bbaaf447e0 100644 --- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs +++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs @@ -39,9 +39,15 @@ namespace OpenSim.Region.UserStatistics { public class ActiveConnectionsAJAX : IStatsController { + private Vector3 DefaultNeighborPosition = new Vector3(128, 128, 70); + #region IStatsController Members - private Vector3 DefaultNeighborPosition = new Vector3(128, 128, 70); + public string ReportName + { + get { return ""; } + } + public Hashtable ProcessModel(Hashtable pParams) { diff --git a/OpenSim/Region/UserStatistics/Clients_report.cs b/OpenSim/Region/UserStatistics/Clients_report.cs new file mode 100644 index 0000000000..bc43e18ae8 --- /dev/null +++ b/OpenSim/Region/UserStatistics/Clients_report.cs @@ -0,0 +1,299 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.UserStatistics +{ + public class Clients_report : IStatsController + { + #region IStatsController Members + + public string ReportName + { + get { return "Client"; } + } + + public Hashtable ProcessModel(Hashtable pParams) + { + SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"]; + + + List clidata = new List(); + List cliRegData = new List(); + Hashtable regionTotals = new Hashtable(); + + Hashtable modeldata = new Hashtable(); + modeldata.Add("Scenes", pParams["Scenes"]); + modeldata.Add("Reports", pParams["Reports"]); + int totalclients = 0; + int totalregions = 0; + + lock (dbConn) + { + string sql = "select count(distinct region_id) as regcnt from stats_session_data"; + + SqliteCommand cmd = new SqliteCommand(sql, dbConn); + SqliteDataReader sdr = cmd.ExecuteReader(); + if (sdr.HasRows) + { + sdr.Read(); + totalregions = Convert.ToInt32(sdr["regcnt"]); + } + + + sql = + "select client_version, count(*) as cnt, avg(avg_sim_fps) as simfps from stats_session_data group by client_version order by count(*) desc LIMIT 10;"; + + cmd = new SqliteCommand(sql, dbConn); + sdr = cmd.ExecuteReader(); + if (sdr.HasRows) + { + while (sdr.Read()) + { + ClientVersionData udata = new ClientVersionData(); + udata.version = sdr["client_version"].ToString(); + udata.count = Convert.ToInt32(sdr["cnt"]); + udata.fps = Convert.ToSingle(sdr["simfps"]); + clidata.Add(udata); + totalclients += udata.count; + + } + } + sdr.Close(); + sdr.Dispose(); + + if (totalregions > 1) + { + sql = + "select region_id, client_version, count(*) as cnt, avg(avg_sim_fps) as simfps from stats_session_data group by region_id, client_version order by region_id, count(*) desc;"; + cmd = new SqliteCommand(sql, dbConn); + + sdr = cmd.ExecuteReader(); + + if (sdr.HasRows) + { + while (sdr.Read()) + { + ClientVersionData udata = new ClientVersionData(); + udata.version = sdr["client_version"].ToString(); + udata.count = Convert.ToInt32(sdr["cnt"]); + udata.fps = Convert.ToSingle(sdr["simfps"]); + udata.region_id = UUID.Parse(sdr["region_id"].ToString()); + cliRegData.Add(udata); + } + } + sdr.Close(); + sdr.Dispose(); + + + } + + } + + foreach (ClientVersionData cvd in cliRegData) + { + + if (regionTotals.ContainsKey(cvd.region_id)) + { + int regiontotal = (int)regionTotals[cvd.region_id]; + regiontotal += cvd.count; + regionTotals[cvd.region_id] = regiontotal; + } + else + { + regionTotals.Add(cvd.region_id, cvd.count); + } + + + + } + + modeldata["ClientData"] = clidata; + modeldata["ClientRegionData"] = cliRegData; + modeldata["RegionTotals"] = regionTotals; + modeldata["Total"] = totalclients; + + return modeldata; + } + + public string RenderView(Hashtable pModelResult) + { + List clidata = (List) pModelResult["ClientData"]; + int totalclients = (int)pModelResult["Total"]; + Hashtable regionTotals = (Hashtable) pModelResult["RegionTotals"]; + List cliRegData = (List) pModelResult["ClientRegionData"]; + List m_scenes = (List)pModelResult["Scenes"]; + Dictionary reports = (Dictionary)pModelResult["Reports"]; + + const string STYLESHEET = + @" + +"; + + StringBuilder output = new StringBuilder(); + HTMLUtil.HtmlHeaders_O(ref output); + output.Append(STYLESHEET); + HTMLUtil.HtmlHeaders_C(ref output); + + HTMLUtil.AddReportLinks(ref output, reports, ""); + + HTMLUtil.TABLE_O(ref output, "defaultr"); + HTMLUtil.TR_O(ref output, ""); + HTMLUtil.TD_O(ref output, "header"); + output.Append("ClientVersion"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "header"); + output.Append("Count/%"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "header"); + output.Append("SimFPS"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TR_C(ref output); + + foreach (ClientVersionData cvd in clidata) + { + HTMLUtil.TR_O(ref output, ""); + HTMLUtil.TD_O(ref output, "content"); + output.Append(cvd.version); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "content"); + output.Append(cvd.count); + output.Append("/"); + if (totalclients > 0) + output.Append((((float)cvd.count / (float)totalclients)*100).ToString()); + else + output.Append(0); + + output.Append("%"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "content"); + output.Append(cvd.fps); + HTMLUtil.TD_C(ref output); + HTMLUtil.TR_C(ref output); + } + HTMLUtil.TABLE_C(ref output); + + if (cliRegData.Count > 0) + { + HTMLUtil.TABLE_O(ref output, "defaultr"); + HTMLUtil.TR_O(ref output, ""); + HTMLUtil.TD_O(ref output, "header"); + output.Append("Region"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "header"); + output.Append("ClientVersion"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "header"); + output.Append("Count/%"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "header"); + output.Append("SimFPS"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TR_C(ref output); + + foreach (ClientVersionData cvd in cliRegData) + { + HTMLUtil.TR_O(ref output, ""); + HTMLUtil.TD_O(ref output, "content"); + output.Append(regionNamefromUUID(m_scenes, cvd.region_id)); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "content"); + output.Append(cvd.version); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "content"); + output.Append(cvd.count); + output.Append("/"); + if ((int)regionTotals[cvd.region_id] > 0) + output.Append((((float)cvd.count / (float)((int)regionTotals[cvd.region_id])) * 100).ToString()); + else + output.Append(0); + + output.Append("%"); + HTMLUtil.TD_C(ref output); + HTMLUtil.TD_O(ref output, "content"); + output.Append(cvd.fps); + HTMLUtil.TD_C(ref output); + HTMLUtil.TR_C(ref output); + } + HTMLUtil.TABLE_C(ref output); + + } + + output.Append(""); + output.Append(""); + return output.ToString(); + } + public string regionNamefromUUID(List scenes, UUID region_id) + { + string returnstring = string.Empty; + foreach (Scene sn in scenes) + { + if (region_id == sn.RegionInfo.originRegionID) + { + returnstring = sn.RegionInfo.RegionName; + break; + } + } + + if (returnstring.Length == 0) + { + returnstring = region_id.ToString(); + } + + return returnstring; + } + + #endregion + } + + public struct ClientVersionData + { + public UUID region_id; + public string version; + public int count; + public float fps; + } +} diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs index 5d4cfc0579..55cb45413e 100644 --- a/OpenSim/Region/UserStatistics/Default_Report.cs +++ b/OpenSim/Region/UserStatistics/Default_Report.cs @@ -41,9 +41,9 @@ namespace OpenSim.Region.UserStatistics public class Default_Report : IStatsController { - public Default_Report() + public string ReportName { - + get { return "Home"; } } #region IStatsController Members @@ -55,9 +55,11 @@ namespace OpenSim.Region.UserStatistics stats_default_page_values mData = rep_DefaultReport_data(conn, m_scene); mData.sim_stat_data = (Dictionary)pParams["SimStats"]; + mData.stats_reports = (Dictionary) pParams["Reports"]; Hashtable nh = new Hashtable(); nh.Add("hdata", mData); + nh.Add("Reports", pParams["Reports"]); return nh; } @@ -73,6 +75,7 @@ namespace OpenSim.Region.UserStatistics public string rep_Default_report_view(stats_default_page_values values) { + StringBuilder output = new StringBuilder(); @@ -123,7 +126,7 @@ TD.align_top { vertical-align: top; } output.Append(STYLESHEET); HTMLUtil.HtmlHeaders_C(ref output); - + HTMLUtil.AddReportLinks(ref output, values.stats_reports, ""); HTMLUtil.TABLE_O(ref output, TableClass); HTMLUtil.TR_O(ref output, TRClass); HTMLUtil.TD_O(ref output, TDHeaderClass); @@ -242,5 +245,6 @@ TD.align_top { vertical-align: top; } public float avg_client_resends; public Scene[] all_scenes; public Dictionary sim_stat_data; + public Dictionary stats_reports; } } diff --git a/OpenSim/Region/UserStatistics/HTMLUtil.cs b/OpenSim/Region/UserStatistics/HTMLUtil.cs index bc21c55d6c..173f75e292 100644 --- a/OpenSim/Region/UserStatistics/HTMLUtil.cs +++ b/OpenSim/Region/UserStatistics/HTMLUtil.cs @@ -208,5 +208,33 @@ namespace OpenSim.Region.UserStatistics o.Append(""); o.Append(""); } + + public static void AddReportLinks( ref StringBuilder o, Dictionary reports, string pClass) + { + int repcount = 0; + foreach (string str in reports.Keys) + { + if (reports[str].ReportName.Length > 0) + { + if (repcount > 0) + { + o.Append("|  "); + } + + o.Append(" 0) + { + GenericClass(ref o, pClass); + + } + o.Append(" href=\""); + o.Append(str); + o.Append("\">"); + o.Append(reports[str].ReportName); + o.Append("  "); + repcount++; + } + } + } } } diff --git a/OpenSim/Region/UserStatistics/IStatsReport.cs b/OpenSim/Region/UserStatistics/IStatsReport.cs index effe66e949..e0ecce4c5c 100644 --- a/OpenSim/Region/UserStatistics/IStatsReport.cs +++ b/OpenSim/Region/UserStatistics/IStatsReport.cs @@ -31,6 +31,7 @@ namespace OpenSim.Region.UserStatistics { public interface IStatsController { + string ReportName { get; } Hashtable ProcessModel(Hashtable pParams); string RenderView(Hashtable pModelResult); } diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs index 0ffe9f699b..1f55d512af 100644 --- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs +++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs @@ -50,6 +50,11 @@ namespace OpenSim.Region.UserStatistics #region IStatsController Members + public string ReportName + { + get { return ""; } + } + public Hashtable ProcessModel(Hashtable pParams) { Hashtable nh = new Hashtable(); diff --git a/OpenSim/Region/UserStatistics/Prototype_distributor.cs b/OpenSim/Region/UserStatistics/Prototype_distributor.cs index 749831e5d2..53ae557769 100644 --- a/OpenSim/Region/UserStatistics/Prototype_distributor.cs +++ b/OpenSim/Region/UserStatistics/Prototype_distributor.cs @@ -38,7 +38,10 @@ namespace OpenSim.Region.UserStatistics { private string prototypejs=string.Empty; - + public string ReportName + { + get { return ""; } + } public Hashtable ProcessModel(Hashtable pParams) { Hashtable pResult = new Hashtable(); diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs index 25fd5200a3..be213aa9f5 100644 --- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs +++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs @@ -41,6 +41,11 @@ namespace OpenSim.Region.UserStatistics { #region IStatsController Members + public string ReportName + { + get { return ""; } + } + public Hashtable ProcessModel(Hashtable pParams) { List m_scene = (List)pParams["Scenes"]; diff --git a/OpenSim/Region/UserStatistics/Updater_distributor.cs b/OpenSim/Region/UserStatistics/Updater_distributor.cs index 663adc9336..9593cc915c 100644 --- a/OpenSim/Region/UserStatistics/Updater_distributor.cs +++ b/OpenSim/Region/UserStatistics/Updater_distributor.cs @@ -38,6 +38,10 @@ namespace OpenSim.Region.UserStatistics { private string updaterjs = string.Empty; + public string ReportName + { + get { return ""; } + } public Hashtable ProcessModel(Hashtable pParams) { diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index 09c23a270d..8a640d051e 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -105,13 +105,15 @@ namespace OpenSim.Region.UserStatistics ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX(); SimStatsAJAX ajSimStats = new SimStatsAJAX(); LogLinesAJAX ajLogLines = new LogLinesAJAX(); + Clients_report clientReport = new Clients_report(); + reports.Add("", rep); - reports.Add("index.aspx", rep); reports.Add("prototype.js", protodep); reports.Add("updater.js", updatedep); reports.Add("activeconnectionsajax.ajax", ajConnections); reports.Add("simstatsajax.ajax", ajSimStats); reports.Add("activelogajax.ajax", ajLogLines); + reports.Add("clients.report", clientReport); scene.CommsManager.HttpServer.AddHTTPHandler("/SStats/", HandleStatsRequest); scene.CommsManager.HttpServer.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest); @@ -192,6 +194,7 @@ namespace OpenSim.Region.UserStatistics repParams["Scenes"] = m_scene; repParams["SimStats"] = m_simstatsCounters; repParams["LogLines"] = m_loglines; + repParams["Reports"] = reports; concurrencyCounter++;