aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/UserStatistics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/UserStatistics')
-rw-r--r--OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs308
-rw-r--r--OpenSim/Region/UserStatistics/Clients_report.cs329
-rw-r--r--OpenSim/Region/UserStatistics/Default_Report.cs277
-rw-r--r--OpenSim/Region/UserStatistics/HTMLUtil.cs263
-rw-r--r--OpenSim/Region/UserStatistics/IStatsReport.cs39
-rw-r--r--OpenSim/Region/UserStatistics/LogLinesAJAX.cs159
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/UserStatistics/Prototype_distributor.cs80
-rw-r--r--OpenSim/Region/UserStatistics/Sessions_Report.cs288
-rw-r--r--OpenSim/Region/UserStatistics/SimStatsAJAX.cs276
-rw-r--r--OpenSim/Region/UserStatistics/Updater_distributor.cs70
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs1206
12 files changed, 0 insertions, 3328 deletions
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
deleted file mode 100644
index 6a1112c..0000000
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ /dev/null
@@ -1,308 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Text;
33using Mono.Data.SqliteClient;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Monitoring;
39
40namespace OpenSim.Region.UserStatistics
41{
42 public class ActiveConnectionsAJAX : IStatsController
43 {
44 private Vector3 DefaultNeighborPosition = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 70);
45
46 #region IStatsController Members
47
48 public string ReportName
49 {
50 get { return ""; }
51 }
52
53 public Hashtable ProcessModel(Hashtable pParams)
54 {
55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
56
57 Hashtable nh = new Hashtable();
58 nh.Add("hdata", m_scene);
59
60 return nh;
61 }
62
63 public string RenderView(Hashtable pModelResult)
64 {
65 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
66
67 StringBuilder output = new StringBuilder();
68 HTMLUtil.OL_O(ref output, "");
69 foreach (Scene scene in all_scenes)
70 {
71 HTMLUtil.LI_O(ref output, String.Empty);
72 output.Append(scene.RegionInfo.RegionName);
73 HTMLUtil.OL_O(ref output, String.Empty);
74 scene.ForEachScenePresence(delegate(ScenePresence av)
75 {
76 Dictionary<string, string> queues = new Dictionary<string, string>();
77 if (av.ControllingClient is IStatsCollector)
78 {
79 IStatsCollector isClient = (IStatsCollector)av.ControllingClient;
80 queues = decodeQueueReport(isClient.Report());
81 }
82 HTMLUtil.LI_O(ref output, String.Empty);
83 output.Append(av.Name);
84 output.Append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
85 output.Append((av.IsChildAgent ? "Child" : "Root"));
86 if (av.AbsolutePosition == DefaultNeighborPosition)
87 {
88 output.Append("<br />Position: ?");
89 }
90 else
91 {
92 output.Append(string.Format("<br /><NOBR>Position: <{0},{1},{2}></NOBR>", (int)av.AbsolutePosition.X,
93 (int)av.AbsolutePosition.Y,
94 (int)av.AbsolutePosition.Z));
95 }
96 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
97
98 HTMLUtil.UL_O(ref output, String.Empty);
99
100 foreach (string throttlename in throttles.Keys)
101 {
102 HTMLUtil.LI_O(ref output, String.Empty);
103 output.Append(throttlename);
104 output.Append(":");
105 output.Append(throttles[throttlename].ToString());
106 if (queues.ContainsKey(throttlename))
107 {
108 output.Append("/");
109 output.Append(queues[throttlename]);
110 }
111 HTMLUtil.LI_C(ref output);
112 }
113 if (queues.ContainsKey("Incoming") && queues.ContainsKey("Outgoing"))
114 {
115 HTMLUtil.LI_O(ref output, "red");
116 output.Append("SEND:");
117 output.Append(queues["Outgoing"]);
118 output.Append("/");
119 output.Append(queues["Incoming"]);
120 HTMLUtil.LI_C(ref output);
121 }
122
123 HTMLUtil.UL_C(ref output);
124 HTMLUtil.LI_C(ref output);
125 });
126 HTMLUtil.OL_C(ref output);
127 }
128 HTMLUtil.OL_C(ref output);
129 return output.ToString();
130 }
131
132 /// <summary>
133 /// Convert active connections information to JSON string. Returns a structure:
134 /// <pre>
135 /// {"regionName": {
136 /// "presenceName": {
137 /// "name": "presenceName",
138 /// "position": "<x,y,z>",
139 /// "isRoot": "false",
140 /// "throttle": {
141 /// },
142 /// "queue": {
143 /// }
144 /// },
145 /// ... // multiple presences in the scene
146 /// },
147 /// ... // multiple regions in the sim
148 /// }
149 ///
150 /// </pre>
151 /// </summary>
152 /// <param name="pModelResult"></param>
153 /// <returns></returns>
154 public string RenderJson(Hashtable pModelResult)
155 {
156 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
157
158 OSDMap regionInfo = new OSDMap();
159 foreach (Scene scene in all_scenes)
160 {
161 OSDMap sceneInfo = new OpenMetaverse.StructuredData.OSDMap();
162 List<ScenePresence> avatarInScene = scene.GetScenePresences();
163 foreach (ScenePresence av in avatarInScene)
164 {
165 OSDMap presenceInfo = new OSDMap();
166 presenceInfo.Add("Name", new OSDString(av.Name));
167
168 Dictionary<string,string> queues = new Dictionary<string, string>();
169 if (av.ControllingClient is IStatsCollector)
170 {
171 IStatsCollector isClient = (IStatsCollector) av.ControllingClient;
172 queues = decodeQueueReport(isClient.Report());
173 }
174 OSDMap queueInfo = new OpenMetaverse.StructuredData.OSDMap();
175 foreach (KeyValuePair<string, string> kvp in queues) {
176 queueInfo.Add(kvp.Key, new OSDString(kvp.Value));
177 }
178 sceneInfo.Add("queues", queueInfo);
179
180 if (av.IsChildAgent)
181 presenceInfo.Add("isRoot", new OSDString("false"));
182 else
183 presenceInfo.Add("isRoot", new OSDString("true"));
184
185 if (av.AbsolutePosition == DefaultNeighborPosition)
186 {
187 presenceInfo.Add("position", new OSDString("<0, 0, 0>"));
188 }
189 else
190 {
191 presenceInfo.Add("position", new OSDString(string.Format("<{0},{1},{2}>",
192 (int)av.AbsolutePosition.X,
193 (int) av.AbsolutePosition.Y,
194 (int) av.AbsolutePosition.Z)) );
195 }
196
197 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
198 OSDMap throttleInfo = new OpenMetaverse.StructuredData.OSDMap();
199 foreach (string throttlename in throttles.Keys)
200 {
201 throttleInfo.Add(throttlename, new OSDString(throttles[throttlename].ToString()));
202 }
203 presenceInfo.Add("throttle", throttleInfo);
204
205 sceneInfo.Add(av.Name, presenceInfo);
206 }
207 regionInfo.Add(scene.RegionInfo.RegionName, sceneInfo);
208 }
209 return regionInfo.ToString();
210 }
211
212 public Dictionary<string, int> DecodeClientThrottles(byte[] throttle)
213 {
214 Dictionary<string, int> returndict = new Dictionary<string, int>();
215 // From mantis http://opensimulator.org/mantis/view.php?id=1374
216 // it appears that sometimes we are receiving empty throttle byte arrays.
217 // TODO: Investigate this behaviour
218 if (throttle.Length == 0)
219 {
220 return new Dictionary<string, int>();
221 }
222
223 int tResend = -1;
224 int tLand = -1;
225 int tWind = -1;
226 int tCloud = -1;
227 int tTask = -1;
228 int tTexture = -1;
229 int tAsset = -1;
230 int tall = -1;
231 const int singlefloat = 4;
232
233 //Agent Throttle Block contains 7 single floatingpoint values.
234 int j = 0;
235
236 // Some Systems may be big endian...
237 // it might be smart to do this check more often...
238 if (!BitConverter.IsLittleEndian)
239 for (int i = 0; i < 7; i++)
240 Array.Reverse(throttle, j + i * singlefloat, singlefloat);
241
242 // values gotten from OpenMetaverse.org/wiki/Throttle. Thanks MW_
243 // bytes
244 // Convert to integer, since.. the full fp space isn't used.
245 tResend = (int)BitConverter.ToSingle(throttle, j);
246 returndict.Add("Resend", tResend);
247 j += singlefloat;
248 tLand = (int)BitConverter.ToSingle(throttle, j);
249 returndict.Add("Land", tLand);
250 j += singlefloat;
251 tWind = (int)BitConverter.ToSingle(throttle, j);
252 returndict.Add("Wind", tWind);
253 j += singlefloat;
254 tCloud = (int)BitConverter.ToSingle(throttle, j);
255 returndict.Add("Cloud", tCloud);
256 j += singlefloat;
257 tTask = (int)BitConverter.ToSingle(throttle, j);
258 returndict.Add("Task", tTask);
259 j += singlefloat;
260 tTexture = (int)BitConverter.ToSingle(throttle, j);
261 returndict.Add("Texture", tTexture);
262 j += singlefloat;
263 tAsset = (int)BitConverter.ToSingle(throttle, j);
264 returndict.Add("Asset", tAsset);
265
266 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
267 returndict.Add("All", tall);
268
269 return returndict;
270 }
271 public Dictionary<string,string> decodeQueueReport(string rep)
272 {
273 Dictionary<string, string> returndic = new Dictionary<string, string>();
274 if (rep.Length == 79)
275 {
276 int pos = 1;
277 returndic.Add("All", rep.Substring((6 * pos), 8)); pos++;
278 returndic.Add("Incoming", rep.Substring((7 * pos), 8)); pos++;
279 returndic.Add("Outgoing", rep.Substring((7 * pos) , 8)); pos++;
280 returndic.Add("Resend", rep.Substring((7 * pos) , 8)); pos++;
281 returndic.Add("Land", rep.Substring((7 * pos) , 8)); pos++;
282 returndic.Add("Wind", rep.Substring((7 * pos) , 8)); pos++;
283 returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++;
284 returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++;
285 returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++;
286 returndic.Add("Asset", rep.Substring((7 * pos), 8));
287 /*
288 * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
289 SendQueue.Count(),
290 IncomingPacketQueue.Count,
291 OutgoingPacketQueue.Count,
292 ResendOutgoingPacketQueue.Count,
293 LandOutgoingPacketQueue.Count,
294 WindOutgoingPacketQueue.Count,
295 CloudOutgoingPacketQueue.Count,
296 TaskOutgoingPacketQueue.Count,
297 TextureOutgoingPacketQueue.Count,
298 AssetOutgoingPacketQueue.Count);
299 */
300 }
301
302
303
304 return returndic;
305 }
306 #endregion
307 }
308}
diff --git a/OpenSim/Region/UserStatistics/Clients_report.cs b/OpenSim/Region/UserStatistics/Clients_report.cs
deleted file mode 100644
index 4a6f7be..0000000
--- a/OpenSim/Region/UserStatistics/Clients_report.cs
+++ /dev/null
@@ -1,329 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Text;
32using Mono.Data.SqliteClient;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.UserStatistics
38{
39 public class Clients_report : IStatsController
40 {
41 #region IStatsController Members
42
43 public string ReportName
44 {
45 get { return "Client"; }
46 }
47
48 /// <summary>
49 /// Return summar information in the form:
50 /// <pre>
51 /// {"totalUsers": "34",
52 /// "totalSessions": "233",
53 /// ...
54 /// }
55 /// </pre>
56 /// </summary>
57 /// <param name="pModelResult"></param>
58 /// <returns></returns>
59 public string RenderJson(Hashtable pModelResult) {
60 stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"];
61
62 OSDMap summaryInfo = new OpenMetaverse.StructuredData.OSDMap();
63 summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString()));
64 summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString()));
65 summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString()));
66 summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString()));
67 summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString()));
68 summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString()));
69 summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString()));
70 summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString()));
71 return summaryInfo.ToString();
72 }
73
74 public Hashtable ProcessModel(Hashtable pParams)
75 {
76 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"];
77
78
79 List<ClientVersionData> clidata = new List<ClientVersionData>();
80 List<ClientVersionData> cliRegData = new List<ClientVersionData>();
81 Hashtable regionTotals = new Hashtable();
82
83 Hashtable modeldata = new Hashtable();
84 modeldata.Add("Scenes", pParams["Scenes"]);
85 modeldata.Add("Reports", pParams["Reports"]);
86 int totalclients = 0;
87 int totalregions = 0;
88
89 lock (dbConn)
90 {
91 string sql = "select count(distinct region_id) as regcnt from stats_session_data";
92
93 SqliteCommand cmd = new SqliteCommand(sql, dbConn);
94 SqliteDataReader sdr = cmd.ExecuteReader();
95 if (sdr.HasRows)
96 {
97 sdr.Read();
98 totalregions = Convert.ToInt32(sdr["regcnt"]);
99 }
100
101 sdr.Close();
102 sdr.Dispose();
103
104 sql =
105 "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;";
106
107 cmd = new SqliteCommand(sql, dbConn);
108 sdr = cmd.ExecuteReader();
109 if (sdr.HasRows)
110 {
111 while (sdr.Read())
112 {
113 ClientVersionData udata = new ClientVersionData();
114 udata.version = sdr["client_version"].ToString();
115 udata.count = Convert.ToInt32(sdr["cnt"]);
116 udata.fps = Convert.ToSingle(sdr["simfps"]);
117 clidata.Add(udata);
118 totalclients += udata.count;
119
120 }
121 }
122 sdr.Close();
123 sdr.Dispose();
124
125 if (totalregions > 1)
126 {
127 sql =
128 "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;";
129 cmd = new SqliteCommand(sql, dbConn);
130
131 sdr = cmd.ExecuteReader();
132
133 if (sdr.HasRows)
134 {
135 while (sdr.Read())
136 {
137 ClientVersionData udata = new ClientVersionData();
138 udata.version = sdr["client_version"].ToString();
139 udata.count = Convert.ToInt32(sdr["cnt"]);
140 udata.fps = Convert.ToSingle(sdr["simfps"]);
141 udata.region_id = UUID.Parse(sdr["region_id"].ToString());
142 cliRegData.Add(udata);
143 }
144 }
145 sdr.Close();
146 sdr.Dispose();
147
148
149 }
150
151 }
152
153 foreach (ClientVersionData cvd in cliRegData)
154 {
155
156 if (regionTotals.ContainsKey(cvd.region_id))
157 {
158 int regiontotal = (int)regionTotals[cvd.region_id];
159 regiontotal += cvd.count;
160 regionTotals[cvd.region_id] = regiontotal;
161 }
162 else
163 {
164 regionTotals.Add(cvd.region_id, cvd.count);
165 }
166
167
168
169 }
170
171 modeldata["ClientData"] = clidata;
172 modeldata["ClientRegionData"] = cliRegData;
173 modeldata["RegionTotals"] = regionTotals;
174 modeldata["Total"] = totalclients;
175
176 return modeldata;
177 }
178
179 public string RenderView(Hashtable pModelResult)
180 {
181 List<ClientVersionData> clidata = (List<ClientVersionData>) pModelResult["ClientData"];
182 int totalclients = (int)pModelResult["Total"];
183 Hashtable regionTotals = (Hashtable) pModelResult["RegionTotals"];
184 List<ClientVersionData> cliRegData = (List<ClientVersionData>) pModelResult["ClientRegionData"];
185 List<Scene> m_scenes = (List<Scene>)pModelResult["Scenes"];
186 Dictionary<string, IStatsController> reports = (Dictionary<string, IStatsController>)pModelResult["Reports"];
187
188 const string STYLESHEET =
189 @"
190<STYLE>
191body
192{
193 font-size:15px; font-family:Helvetica, Verdana; color:Black;
194}
195TABLE.defaultr { }
196TR.defaultr { padding: 5px; }
197TD.header { font-weight:bold; padding:5px; }
198TD.content {}
199TD.contentright { text-align: right; }
200TD.contentcenter { text-align: center; }
201TD.align_top { vertical-align: top; }
202</STYLE>
203";
204
205 StringBuilder output = new StringBuilder();
206 HTMLUtil.HtmlHeaders_O(ref output);
207 output.Append(STYLESHEET);
208 HTMLUtil.HtmlHeaders_C(ref output);
209
210 HTMLUtil.AddReportLinks(ref output, reports, "");
211
212 HTMLUtil.TABLE_O(ref output, "defaultr");
213 HTMLUtil.TR_O(ref output, "");
214 HTMLUtil.TD_O(ref output, "header");
215 output.Append("ClientVersion");
216 HTMLUtil.TD_C(ref output);
217 HTMLUtil.TD_O(ref output, "header");
218 output.Append("Count/%");
219 HTMLUtil.TD_C(ref output);
220 HTMLUtil.TD_O(ref output, "header");
221 output.Append("SimFPS");
222 HTMLUtil.TD_C(ref output);
223 HTMLUtil.TR_C(ref output);
224
225 foreach (ClientVersionData cvd in clidata)
226 {
227 HTMLUtil.TR_O(ref output, "");
228 HTMLUtil.TD_O(ref output, "content");
229 string linkhref = "sessions.report?VersionString=" + cvd.version;
230 HTMLUtil.A(ref output, cvd.version, linkhref, "");
231 HTMLUtil.TD_C(ref output);
232 HTMLUtil.TD_O(ref output, "content");
233 output.Append(cvd.count);
234 output.Append("/");
235 if (totalclients > 0)
236 output.Append((((float)cvd.count / (float)totalclients)*100).ToString());
237 else
238 output.Append(0);
239
240 output.Append("%");
241 HTMLUtil.TD_C(ref output);
242 HTMLUtil.TD_O(ref output, "content");
243 output.Append(cvd.fps);
244 HTMLUtil.TD_C(ref output);
245 HTMLUtil.TR_C(ref output);
246 }
247 HTMLUtil.TABLE_C(ref output);
248
249 if (cliRegData.Count > 0)
250 {
251 HTMLUtil.TABLE_O(ref output, "defaultr");
252 HTMLUtil.TR_O(ref output, "");
253 HTMLUtil.TD_O(ref output, "header");
254 output.Append("Region");
255 HTMLUtil.TD_C(ref output);
256 HTMLUtil.TD_O(ref output, "header");
257 output.Append("ClientVersion");
258 HTMLUtil.TD_C(ref output);
259 HTMLUtil.TD_O(ref output, "header");
260 output.Append("Count/%");
261 HTMLUtil.TD_C(ref output);
262 HTMLUtil.TD_O(ref output, "header");
263 output.Append("SimFPS");
264 HTMLUtil.TD_C(ref output);
265 HTMLUtil.TR_C(ref output);
266
267 foreach (ClientVersionData cvd in cliRegData)
268 {
269 HTMLUtil.TR_O(ref output, "");
270 HTMLUtil.TD_O(ref output, "content");
271 output.Append(regionNamefromUUID(m_scenes, cvd.region_id));
272 HTMLUtil.TD_C(ref output);
273 HTMLUtil.TD_O(ref output, "content");
274 output.Append(cvd.version);
275 HTMLUtil.TD_C(ref output);
276 HTMLUtil.TD_O(ref output, "content");
277 output.Append(cvd.count);
278 output.Append("/");
279 if ((int)regionTotals[cvd.region_id] > 0)
280 output.Append((((float)cvd.count / (float)((int)regionTotals[cvd.region_id])) * 100).ToString());
281 else
282 output.Append(0);
283
284 output.Append("%");
285 HTMLUtil.TD_C(ref output);
286 HTMLUtil.TD_O(ref output, "content");
287 output.Append(cvd.fps);
288 HTMLUtil.TD_C(ref output);
289 HTMLUtil.TR_C(ref output);
290 }
291 HTMLUtil.TABLE_C(ref output);
292
293 }
294
295 output.Append("</BODY>");
296 output.Append("</HTML>");
297 return output.ToString();
298 }
299 public string regionNamefromUUID(List<Scene> scenes, UUID region_id)
300 {
301 string returnstring = string.Empty;
302 foreach (Scene sn in scenes)
303 {
304 if (region_id == sn.RegionInfo.originRegionID)
305 {
306 returnstring = sn.RegionInfo.RegionName;
307 break;
308 }
309 }
310
311 if (returnstring.Length == 0)
312 {
313 returnstring = region_id.ToString();
314 }
315
316 return returnstring;
317 }
318
319 #endregion
320 }
321
322 public struct ClientVersionData
323 {
324 public UUID region_id;
325 public string version;
326 public int count;
327 public float fps;
328 }
329}
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs
deleted file mode 100644
index fabe3d4..0000000
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ /dev/null
@@ -1,277 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Text;
33using Mono.Data.SqliteClient;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Monitoring;
38
39
40namespace OpenSim.Region.UserStatistics
41{
42 public class Default_Report : IStatsController
43 {
44
45 public string ReportName
46 {
47 get { return "Home"; }
48 }
49
50 #region IStatsController Members
51
52 public Hashtable ProcessModel(Hashtable pParams)
53 {
54 SqliteConnection conn = (SqliteConnection)pParams["DatabaseConnection"];
55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
56
57 stats_default_page_values mData = rep_DefaultReport_data(conn, m_scene);
58 mData.sim_stat_data = (Dictionary<UUID,USimStatsData>)pParams["SimStats"];
59 mData.stats_reports = (Dictionary<string, IStatsController>) pParams["Reports"];
60
61 Hashtable nh = new Hashtable();
62 nh.Add("hdata", mData);
63 nh.Add("Reports", pParams["Reports"]);
64
65 return nh;
66 }
67
68 public string RenderView(Hashtable pModelResult)
69 {
70 stats_default_page_values mData = (stats_default_page_values) pModelResult["hdata"];
71 return rep_Default_report_view(mData);
72 }
73
74 #endregion
75
76 public string rep_Default_report_view(stats_default_page_values values)
77 {
78
79
80 StringBuilder output = new StringBuilder();
81
82
83
84 const string TableClass = "defaultr";
85 const string TRClass = "defaultr";
86 const string TDHeaderClass = "header";
87 const string TDDataClass = "content";
88 //const string TDDataClassRight = "contentright";
89 const string TDDataClassCenter = "contentcenter";
90
91 const string STYLESHEET =
92 @"
93<STYLE>
94body
95{
96 font-size:15px; font-family:Helvetica, Verdana; color:Black;
97}
98TABLE.defaultr { }
99TR.defaultr { padding: 5px; }
100TD.header { font-weight:bold; padding:5px; }
101TD.content {}
102TD.contentright { text-align: right; }
103TD.contentcenter { text-align: center; }
104TD.align_top { vertical-align: top; }
105</STYLE>
106";
107 HTMLUtil.HtmlHeaders_O(ref output);
108
109 HTMLUtil.InsertProtoTypeAJAX(ref output);
110 string[] ajaxUpdaterDivs = new string[3];
111 int[] ajaxUpdaterSeconds = new int[3];
112 string[] ajaxUpdaterReportFragments = new string[3];
113
114 ajaxUpdaterDivs[0] = "activeconnections";
115 ajaxUpdaterSeconds[0] = 10;
116 ajaxUpdaterReportFragments[0] = "activeconnectionsajax.html";
117
118 ajaxUpdaterDivs[1] = "activesimstats";
119 ajaxUpdaterSeconds[1] = 20;
120 ajaxUpdaterReportFragments[1] = "simstatsajax.html";
121
122 ajaxUpdaterDivs[2] = "activelog";
123 ajaxUpdaterSeconds[2] = 5;
124 ajaxUpdaterReportFragments[2] = "activelogajax.html";
125
126 HTMLUtil.InsertPeriodicUpdaters(ref output, ajaxUpdaterDivs, ajaxUpdaterSeconds, ajaxUpdaterReportFragments);
127
128 output.Append(STYLESHEET);
129 HTMLUtil.HtmlHeaders_C(ref output);
130 HTMLUtil.AddReportLinks(ref output, values.stats_reports, "");
131 HTMLUtil.TABLE_O(ref output, TableClass);
132 HTMLUtil.TR_O(ref output, TRClass);
133 HTMLUtil.TD_O(ref output, TDHeaderClass);
134 output.Append("# Users Total");
135 HTMLUtil.TD_C(ref output);
136 HTMLUtil.TD_O(ref output, TDHeaderClass);
137 output.Append("# Sessions Total");
138 HTMLUtil.TD_C(ref output);
139 HTMLUtil.TD_O(ref output, TDHeaderClass);
140 output.Append("Avg Client FPS");
141 HTMLUtil.TD_C(ref output);
142 HTMLUtil.TD_O(ref output, TDHeaderClass);
143 output.Append("Avg Client Mem Use");
144 HTMLUtil.TD_C(ref output);
145 HTMLUtil.TD_O(ref output, TDHeaderClass);
146 output.Append("Avg Sim FPS");
147 HTMLUtil.TD_C(ref output);
148 HTMLUtil.TD_O(ref output, TDHeaderClass);
149 output.Append("Avg Ping");
150 HTMLUtil.TD_C(ref output);
151 HTMLUtil.TD_O(ref output, TDHeaderClass);
152 output.Append("KB Out Total");
153 HTMLUtil.TD_C(ref output);
154 HTMLUtil.TD_O(ref output, TDHeaderClass);
155 output.Append("KB In Total");
156 HTMLUtil.TD_C(ref output);
157 HTMLUtil.TR_C(ref output);
158 HTMLUtil.TR_O(ref output, TRClass);
159 HTMLUtil.TD_O(ref output, TDDataClass);
160 output.Append(values.total_num_users);
161 HTMLUtil.TD_C(ref output);
162 HTMLUtil.TD_O(ref output, TDDataClass);
163 output.Append(values.total_num_sessions);
164 HTMLUtil.TD_C(ref output);
165 HTMLUtil.TD_O(ref output, TDDataClassCenter);
166 output.Append(values.avg_client_fps);
167 HTMLUtil.TD_C(ref output);
168 HTMLUtil.TD_O(ref output, TDDataClassCenter);
169 output.Append(values.avg_client_mem_use);
170 HTMLUtil.TD_C(ref output);
171 HTMLUtil.TD_O(ref output, TDDataClassCenter);
172 output.Append(values.avg_sim_fps);
173 HTMLUtil.TD_C(ref output);
174 HTMLUtil.TD_O(ref output, TDDataClassCenter);
175 output.Append(values.avg_ping);
176 HTMLUtil.TD_C(ref output);
177 HTMLUtil.TD_O(ref output, TDDataClassCenter);
178 output.Append(values.total_kb_out);
179 HTMLUtil.TD_C(ref output);
180 HTMLUtil.TD_O(ref output, TDDataClassCenter);
181 output.Append(values.total_kb_in);
182 HTMLUtil.TD_C(ref output);
183 HTMLUtil.TR_C(ref output);
184 HTMLUtil.TABLE_C(ref output);
185
186 HTMLUtil.HR(ref output, "");
187 HTMLUtil.TABLE_O(ref output, "");
188 HTMLUtil.TR_O(ref output, "");
189 HTMLUtil.TD_O(ref output, "align_top");
190 output.Append("<DIV id=\"activeconnections\">Active Connections loading...</DIV>");
191 HTMLUtil.TD_C(ref output);
192 HTMLUtil.TD_O(ref output, "align_top");
193 output.Append("<DIV id=\"activesimstats\">SimStats loading...</DIV>");
194 output.Append("<DIV id=\"activelog\">ActiveLog loading...</DIV>");
195 HTMLUtil.TD_C(ref output);
196 HTMLUtil.TR_C(ref output);
197 HTMLUtil.TABLE_C(ref output);
198 output.Append("</BODY></HTML>");
199 // TODO: FIXME: template
200 return output.ToString();
201 }
202
203
204
205 public stats_default_page_values rep_DefaultReport_data(SqliteConnection db, List<Scene> m_scene)
206 {
207 stats_default_page_values returnstruct = new stats_default_page_values();
208 returnstruct.all_scenes = m_scene.ToArray();
209 lock (db)
210 {
211 string SQL = @"SELECT COUNT(DISTINCT agent_id) as agents, COUNT(*) as sessions, AVG(avg_fps) as client_fps,
212 AVG(avg_sim_fps) as savg_sim_fps, AVG(avg_ping) as sav_ping, SUM(n_out_kb) as num_in_kb,
213 SUM(n_out_pk) as num_in_packets, SUM(n_in_kb) as num_out_kb, SUM(n_in_pk) as num_out_packets, AVG(mem_use) as sav_mem_use
214 FROM stats_session_data;";
215 SqliteCommand cmd = new SqliteCommand(SQL, db);
216 SqliteDataReader sdr = cmd.ExecuteReader();
217 if (sdr.HasRows)
218 {
219 sdr.Read();
220 returnstruct.total_num_users = Convert.ToInt32(sdr["agents"]);
221 returnstruct.total_num_sessions = Convert.ToInt32(sdr["sessions"]);
222 returnstruct.avg_client_fps = Convert.ToSingle(sdr["client_fps"]);
223 returnstruct.avg_sim_fps = Convert.ToSingle(sdr["savg_sim_fps"]);
224 returnstruct.avg_ping = Convert.ToSingle(sdr["sav_ping"]);
225 returnstruct.total_kb_out = Convert.ToSingle(sdr["num_out_kb"]);
226 returnstruct.total_kb_in = Convert.ToSingle(sdr["num_in_kb"]);
227 returnstruct.avg_client_mem_use = Convert.ToSingle(sdr["sav_mem_use"]);
228
229 }
230 }
231 return returnstruct;
232 }
233
234 /// <summary>
235 /// Return summar information in the form:
236 /// <pre>
237 /// {"totalUsers": "34",
238 /// "totalSessions": "233",
239 /// ...
240 /// }
241 /// </pre>
242 /// </summary>
243 /// <param name="pModelResult"></param>
244 /// <returns></returns>
245 public string RenderJson(Hashtable pModelResult) {
246 stats_default_page_values values = (stats_default_page_values) pModelResult["hdata"];
247
248 OSDMap summaryInfo = new OSDMap();
249 summaryInfo.Add("totalUsers", new OSDString(values.total_num_users.ToString()));
250 summaryInfo.Add("totalSessions", new OSDString(values.total_num_sessions.ToString()));
251 summaryInfo.Add("averageClientFPS", new OSDString(values.avg_client_fps.ToString()));
252 summaryInfo.Add("averageClientMem", new OSDString(values.avg_client_mem_use.ToString()));
253 summaryInfo.Add("averageSimFPS", new OSDString(values.avg_sim_fps.ToString()));
254 summaryInfo.Add("averagePingTime", new OSDString(values.avg_ping.ToString()));
255 summaryInfo.Add("totalKBOut", new OSDString(values.total_kb_out.ToString()));
256 summaryInfo.Add("totalKBIn", new OSDString(values.total_kb_in.ToString()));
257 return summaryInfo.ToString();
258 }
259 }
260
261 public struct stats_default_page_values
262 {
263 public int total_num_users;
264 public int total_num_sessions;
265 public float avg_client_fps;
266 public float avg_client_mem_use;
267 public float avg_sim_fps;
268 public float avg_ping;
269 public float total_kb_out;
270 public float total_kb_in;
271 public float avg_client_resends;
272 public Scene[] all_scenes;
273 public Dictionary<UUID, USimStatsData> sim_stat_data;
274 public Dictionary<string, IStatsController> stats_reports;
275 }
276
277}
diff --git a/OpenSim/Region/UserStatistics/HTMLUtil.cs b/OpenSim/Region/UserStatistics/HTMLUtil.cs
deleted file mode 100644
index c07619f..0000000
--- a/OpenSim/Region/UserStatistics/HTMLUtil.cs
+++ /dev/null
@@ -1,263 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32namespace OpenSim.Region.UserStatistics
33{
34 public static class HTMLUtil
35 {
36
37 public static void TR_O(ref StringBuilder o, string pclass)
38 {
39 o.Append("<tr");
40 if (pclass.Length > 0)
41 {
42 GenericClass(ref o, pclass);
43 }
44 o.Append(">\n\t");
45 }
46
47 public static void TR_C(ref StringBuilder o)
48 {
49 o.Append("</tr>\n");
50 }
51
52 public static void TD_O(ref StringBuilder o, string pclass)
53 {
54 TD_O(ref o, pclass, 0, 0);
55 }
56
57 public static void TD_O(ref StringBuilder o, string pclass, int rowspan, int colspan)
58 {
59 o.Append("<td");
60 if (pclass.Length > 0)
61 {
62 GenericClass(ref o, pclass);
63 }
64 if (rowspan > 1)
65 {
66 o.Append(" rowspan=\"");
67 o.Append(rowspan);
68 o.Append("\"");
69 }
70 if (colspan > 1)
71 {
72 o.Append(" colspan=\"");
73 o.Append(colspan);
74 o.Append("\"");
75 }
76 o.Append(">");
77 }
78
79 public static void TD_C(ref StringBuilder o)
80 {
81 o.Append("</td>");
82 }
83
84 public static void TABLE_O(ref StringBuilder o, string pclass)
85 {
86 o.Append("<table");
87 if (pclass.Length > 0)
88 {
89 GenericClass(ref o, pclass);
90 }
91 o.Append(">\n\t");
92 }
93
94 public static void TABLE_C(ref StringBuilder o)
95 {
96 o.Append("</table>\n");
97 }
98
99 public static void BLOCKQUOTE_O(ref StringBuilder o, string pclass)
100 {
101 o.Append("<blockquote");
102 if (pclass.Length > 0)
103 {
104 GenericClass(ref o, pclass);
105 }
106 o.Append(" />\n");
107 }
108
109 public static void BLOCKQUOTE_C(ref StringBuilder o)
110 {
111 o.Append("</blockquote>\n");
112 }
113
114 public static void BR(ref StringBuilder o)
115 {
116 o.Append("<br />\n");
117 }
118
119 public static void HR(ref StringBuilder o, string pclass)
120 {
121 o.Append("<hr");
122 if (pclass.Length > 0)
123 {
124 GenericClass(ref o, pclass);
125 }
126 o.Append(" />\n");
127 }
128
129 public static void UL_O(ref StringBuilder o, string pclass)
130 {
131 o.Append("<ul");
132 if (pclass.Length > 0)
133 {
134 GenericClass(ref o, pclass);
135 }
136 o.Append(" />\n");
137 }
138
139 public static void UL_C(ref StringBuilder o)
140 {
141 o.Append("</ul>\n");
142 }
143
144 public static void OL_O(ref StringBuilder o, string pclass)
145 {
146 o.Append("<ol");
147 if (pclass.Length > 0)
148 {
149 GenericClass(ref o, pclass);
150 }
151 o.Append(" />\n");
152 }
153
154 public static void OL_C(ref StringBuilder o)
155 {
156 o.Append("</ol>\n");
157 }
158
159 public static void LI_O(ref StringBuilder o, string pclass)
160 {
161 o.Append("<li");
162 if (pclass.Length > 0)
163 {
164 GenericClass(ref o, pclass);
165 }
166 o.Append(" />\n");
167 }
168
169 public static void LI_C(ref StringBuilder o)
170 {
171 o.Append("</li>\n");
172 }
173
174 public static void GenericClass(ref StringBuilder o, string pclass)
175 {
176 o.Append(" class=\"");
177 o.Append(pclass);
178 o.Append("\"");
179 }
180
181 public static void InsertProtoTypeAJAX(ref StringBuilder o)
182 {
183 o.Append("<script type=\"text/javascript\" src=\"prototype.js\"></script>\n");
184 o.Append("<script type=\"text/javascript\" src=\"updater.js\"></script>\n");
185 }
186
187 public static void InsertPeriodicUpdaters(ref StringBuilder o, string[] divID, int[] seconds, string[] reportfrag)
188 {
189 o.Append("<script type=\"text/javascript\">\n");
190 o.Append(
191 @"
192 // <![CDATA[
193 document.observe('dom:loaded', function() {
194 /*
195 first arg : div to update
196 second arg : interval to poll in seconds
197 third arg : file to get data
198 */
199");
200 for (int i = 0; i < divID.Length; i++)
201 {
202
203 o.Append("new updater('");
204 o.Append(divID[i]);
205 o.Append("', ");
206 o.Append(seconds[i]);
207 o.Append(", '");
208 o.Append(reportfrag[i]);
209 o.Append("');\n");
210 }
211
212 o.Append(@"
213 });
214 // ]]>
215 </script>");
216 }
217
218 public static void HtmlHeaders_O(ref StringBuilder o)
219 {
220 o.Append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n");
221 o.Append("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"nl\">");
222 o.Append("<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />");
223 }
224
225 public static void HtmlHeaders_C(ref StringBuilder o)
226 {
227 o.Append("</HEAD>");
228 o.Append("<BODY>");
229 }
230
231 public static void AddReportLinks(ref StringBuilder o, Dictionary<string, IStatsController> reports, string pClass)
232 {
233 int repcount = 0;
234 foreach (string str in reports.Keys)
235 {
236 if (reports[str].ReportName.Length > 0)
237 {
238 if (repcount > 0)
239 {
240 o.Append("|&nbsp;&nbsp;");
241 }
242 A(ref o, reports[str].ReportName, str, pClass);
243 o.Append("&nbsp;&nbsp;");
244 repcount++;
245 }
246 }
247 }
248
249 public static void A(ref StringBuilder o, string linktext, string linkhref, string pClass)
250 {
251 o.Append("<A");
252 if (pClass.Length > 0)
253 {
254 GenericClass(ref o, pClass);
255 }
256 o.Append(" href=\"");
257 o.Append(linkhref);
258 o.Append("\">");
259 o.Append(linktext);
260 o.Append("</A>");
261 }
262 }
263}
diff --git a/OpenSim/Region/UserStatistics/IStatsReport.cs b/OpenSim/Region/UserStatistics/IStatsReport.cs
deleted file mode 100644
index 80c4487..0000000
--- a/OpenSim/Region/UserStatistics/IStatsReport.cs
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections;
29
30namespace OpenSim.Region.UserStatistics
31{
32 public interface IStatsController
33 {
34 string ReportName { get; }
35 Hashtable ProcessModel(Hashtable pParams);
36 string RenderView(Hashtable pModelResult);
37 string RenderJson(Hashtable pModelResult);
38 }
39}
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
deleted file mode 100644
index 4d45b80..0000000
--- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
+++ /dev/null
@@ -1,159 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Text;
33using System.Text.RegularExpressions;
34using Mono.Data.SqliteClient;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Monitoring;
39
40namespace OpenSim.Region.UserStatistics
41{
42 public class LogLinesAJAX : IStatsController
43 {
44 private Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
45
46 private Regex webFormat = new Regex(@"[^\s]*\s([^,]*),[^\s]*\s([A-Z]*)[^\s-][^\[]*\[([^\]]*)\]([^\n]*)",
47 RegexOptions.Singleline | RegexOptions.Compiled);
48 private Regex TitleColor = new Regex(@"[^\s]*\s(?:[^,]*),[^\s]*\s(?:[A-Z]*)[^\s-][^\[]*\[([^\]]*)\](?:[^\n]*)",
49 RegexOptions.Singleline | RegexOptions.Compiled);
50
51
52 #region IStatsController Members
53
54 public string ReportName
55 {
56 get { return ""; }
57 }
58
59 public Hashtable ProcessModel(Hashtable pParams)
60 {
61 Hashtable nh = new Hashtable();
62 nh.Add("loglines", pParams["LogLines"]);
63 return nh;
64 }
65
66 public string RenderView(Hashtable pModelResult)
67 {
68 StringBuilder output = new StringBuilder();
69
70 HTMLUtil.HR(ref output, "");
71 output.Append("<H3>ActiveLog</H3>\n");
72
73 string tmp = normalizeEndLines.Replace(pModelResult["loglines"].ToString(), "\n");
74
75 string[] result = Regex.Split(tmp, "\n");
76
77 string formatopen = "";
78 string formatclose = "";
79
80 for (int i = 0; i < result.Length; i++)
81 {
82 if (result[i].Length >= 30)
83 {
84 string logtype = result[i].Substring(24, 6);
85 switch (logtype)
86 {
87 case "WARN ":
88 formatopen = "<font color=\"#7D7C00\">";
89 formatclose = "</font>";
90 break;
91
92 case "ERROR ":
93 formatopen = "<font color=\"#FF0000\">";
94 formatclose = "</font>";
95 break;
96
97 default:
98 formatopen = "";
99 formatclose = "";
100 break;
101
102 }
103 }
104 StringBuilder replaceStr = new StringBuilder();
105 //string titlecolorresults =
106
107 string formatresult = Regex.Replace(TitleColor.Replace(result[i], "$1"), "[^ABCDEFabcdef0-9]", "");
108 if (formatresult.Length > 6)
109 {
110 formatresult = formatresult.Substring(0, 6);
111
112 }
113 for (int j = formatresult.Length; j <= 5; j++)
114 formatresult += "0";
115 replaceStr.Append("$1 - [<font color=\"#");
116 replaceStr.Append(formatresult);
117 replaceStr.Append("\">$3</font>] $4<br />");
118 string repstr = replaceStr.ToString();
119
120 output.Append(formatopen);
121 output.Append(webFormat.Replace(result[i], repstr));
122 output.Append(formatclose);
123 }
124
125
126 return output.ToString();
127 }
128
129 /// <summary>
130 /// Return the last log lines. Output in the format:
131 /// <pre>
132 /// {"logLines": [
133 /// "line1",
134 /// "line2",
135 /// ...
136 /// ]
137 /// }
138 /// </pre>
139 /// </summary>
140 /// <param name="pModelResult"></param>
141 /// <returns></returns>
142 public string RenderJson(Hashtable pModelResult)
143 {
144 OSDMap logInfo = new OpenMetaverse.StructuredData.OSDMap();
145
146 OSDArray logLines = new OpenMetaverse.StructuredData.OSDArray();
147 string tmp = normalizeEndLines.Replace(pModelResult["loglines"].ToString(), "\n");
148 string[] result = Regex.Split(tmp, "\n");
149 for (int i = 0; i < result.Length; i++)
150 {
151 logLines.Add(new OSDString(result[i]));
152 }
153 logInfo.Add("logLines", logLines);
154 return logInfo.ToString();
155 }
156
157 #endregion
158 }
159}
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
deleted file mode 100644
index 9fac53e..0000000
--- a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.UserStatistics")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("42b28288-5fdd-478f-8903-8dccbbb2d5f9")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.8.2.*")]
33
diff --git a/OpenSim/Region/UserStatistics/Prototype_distributor.cs b/OpenSim/Region/UserStatistics/Prototype_distributor.cs
deleted file mode 100644
index 6f8b2aa..0000000
--- a/OpenSim/Region/UserStatistics/Prototype_distributor.cs
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Collections;
31using System.Collections.Generic;
32using System.Text;
33using OpenSim.Framework;
34
35namespace OpenSim.Region.UserStatistics
36{
37 public class Prototype_distributor : IStatsController
38 {
39 private string jsFileName = "prototype.js";
40 private string prototypejs = string.Empty;
41
42 public Prototype_distributor()
43 {
44 jsFileName = "prototype.js";
45 }
46
47 public Prototype_distributor(string jsName)
48 {
49 jsFileName = jsName;
50 }
51
52 public string ReportName
53 {
54 get { return ""; }
55 }
56 public Hashtable ProcessModel(Hashtable pParams)
57 {
58 Hashtable pResult = new Hashtable();
59 pResult["js"] = jsFileName;
60 return pResult;
61 }
62
63 public string RenderView(Hashtable pModelResult)
64 {
65 string fileName = (string)pModelResult["js"];
66 using (StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/" + fileName, FileMode.Open)))
67 {
68 prototypejs = fs.ReadToEnd();
69 fs.Close();
70 }
71 return prototypejs;
72 }
73
74 public string RenderJson(Hashtable pModelResult)
75 {
76 return "{}";
77 }
78
79 }
80}
diff --git a/OpenSim/Region/UserStatistics/Sessions_Report.cs b/OpenSim/Region/UserStatistics/Sessions_Report.cs
deleted file mode 100644
index 0e94912..0000000
--- a/OpenSim/Region/UserStatistics/Sessions_Report.cs
+++ /dev/null
@@ -1,288 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Text;
32using Mono.Data.SqliteClient;
33using OpenMetaverse;
34using OpenSim.Framework;
35
36namespace OpenSim.Region.UserStatistics
37{
38 public class Sessions_Report : IStatsController
39 {
40 #region IStatsController Members
41
42 public string ReportName
43 {
44 get { return "Sessions"; }
45 }
46
47 public Hashtable ProcessModel(Hashtable pParams)
48 {
49 Hashtable modeldata = new Hashtable();
50 modeldata.Add("Scenes", pParams["Scenes"]);
51 modeldata.Add("Reports", pParams["Reports"]);
52 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"];
53 List<SessionList> lstSessions = new List<SessionList>();
54 Hashtable requestvars = (Hashtable) pParams["RequestVars"];
55
56
57 string puserUUID = string.Empty;
58 string clientVersionString = string.Empty;
59 int queryparams = 0;
60
61 if (requestvars != null)
62 {
63 if (requestvars.ContainsKey("UserID"))
64 {
65 UUID testUUID = UUID.Zero;
66 if (UUID.TryParse(requestvars["UserID"].ToString(), out testUUID))
67 {
68 puserUUID = requestvars["UserID"].ToString();
69
70 }
71 }
72
73 if (requestvars.ContainsKey("VersionString"))
74 {
75 clientVersionString = requestvars["VersionString"].ToString();
76 }
77 }
78
79 lock (dbConn)
80 {
81 string sql =
82 "SELECT distinct a.name_f, a.name_l, a.Agent_ID, b.Session_ID, b.client_version, b.last_updated, b.start_time FROM stats_session_data a LEFT OUTER JOIN stats_session_data b ON a.Agent_ID = b.Agent_ID";
83
84 if (puserUUID.Length > 0)
85 {
86 if (queryparams == 0)
87 sql += " WHERE";
88 else
89 sql += " AND";
90
91 sql += " b.agent_id=:agent_id";
92 queryparams++;
93 }
94
95 if (clientVersionString.Length > 0)
96 {
97 if (queryparams == 0)
98 sql += " WHERE";
99 else
100 sql += " AND";
101
102 sql += " b.client_version=:client_version";
103 queryparams++;
104 }
105
106 sql += " ORDER BY a.name_f, a.name_l, b.last_updated;";
107
108 SqliteCommand cmd = new SqliteCommand(sql, dbConn);
109
110 if (puserUUID.Length > 0)
111 cmd.Parameters.Add(new SqliteParameter(":agent_id", puserUUID));
112 if (clientVersionString.Length > 0)
113 cmd.Parameters.Add(new SqliteParameter(":client_version", clientVersionString));
114
115 SqliteDataReader sdr = cmd.ExecuteReader();
116
117 if (sdr.HasRows)
118 {
119 UUID userUUID = UUID.Zero;
120
121 SessionList activeSessionList = new SessionList();
122 activeSessionList.user_id=UUID.Random();
123 while (sdr.Read())
124 {
125 UUID readUUID = UUID.Parse(sdr["agent_id"].ToString());
126 if (readUUID != userUUID)
127 {
128 activeSessionList = new SessionList();
129 activeSessionList.user_id = readUUID;
130 activeSessionList.firstname = sdr["name_f"].ToString();
131 activeSessionList.lastname = sdr["name_l"].ToString();
132 activeSessionList.sessions = new List<ShortSessionData>();
133 lstSessions.Add(activeSessionList);
134 }
135
136 ShortSessionData ssd = new ShortSessionData();
137
138 ssd.last_update = Utils.UnixTimeToDateTime((uint)Convert.ToInt32(sdr["last_updated"]));
139 ssd.start_time = Utils.UnixTimeToDateTime((uint)Convert.ToInt32(sdr["start_time"]));
140 ssd.session_id = UUID.Parse(sdr["session_id"].ToString());
141 ssd.client_version = sdr["client_version"].ToString();
142 activeSessionList.sessions.Add(ssd);
143
144 userUUID = activeSessionList.user_id;
145 }
146 }
147 sdr.Close();
148 sdr.Dispose();
149
150 }
151 modeldata["SessionData"] = lstSessions;
152 return modeldata;
153 }
154
155 public string RenderView(Hashtable pModelResult)
156 {
157 List<SessionList> lstSession = (List<SessionList>) pModelResult["SessionData"];
158 Dictionary<string, IStatsController> reports = (Dictionary<string, IStatsController>)pModelResult["Reports"];
159
160 const string STYLESHEET =
161 @"
162<STYLE>
163body
164{
165 font-size:15px; font-family:Helvetica, Verdana; color:Black;
166}
167TABLE.defaultr { }
168TR.defaultr { padding: 5px; }
169TD.header { font-weight:bold; padding:5px; }
170TD.content {}
171TD.contentright { text-align: right; }
172TD.contentcenter { text-align: center; }
173TD.align_top { vertical-align: top; }
174</STYLE>
175";
176
177 StringBuilder output = new StringBuilder();
178 HTMLUtil.HtmlHeaders_O(ref output);
179 output.Append(STYLESHEET);
180 HTMLUtil.HtmlHeaders_C(ref output);
181
182 HTMLUtil.AddReportLinks(ref output, reports, "");
183
184 HTMLUtil.TABLE_O(ref output, "defaultr");
185 HTMLUtil.TR_O(ref output, "defaultr");
186 HTMLUtil.TD_O(ref output, "header");
187 output.Append("FirstName");
188 HTMLUtil.TD_C(ref output);
189 HTMLUtil.TD_O(ref output, "header");
190 output.Append("LastName");
191 HTMLUtil.TD_C(ref output);
192 HTMLUtil.TD_O(ref output, "header");
193 output.Append("SessionEnd");
194 HTMLUtil.TD_C(ref output);
195 HTMLUtil.TD_O(ref output, "header");
196 output.Append("SessionLength");
197 HTMLUtil.TD_C(ref output);
198 HTMLUtil.TD_O(ref output, "header");
199 output.Append("Client");
200 HTMLUtil.TD_C(ref output);
201 HTMLUtil.TR_C(ref output);
202 if (lstSession.Count == 0)
203 {
204 HTMLUtil.TR_O(ref output, "");
205 HTMLUtil.TD_O(ref output, "align_top", 1, 5);
206 output.Append("No results for that query");
207 HTMLUtil.TD_C(ref output);
208 HTMLUtil.TR_C(ref output);
209 }
210 foreach (SessionList ssnlst in lstSession)
211 {
212 int cnt = 0;
213 foreach (ShortSessionData sesdata in ssnlst.sessions)
214 {
215 HTMLUtil.TR_O(ref output, "");
216 if (cnt++ == 0)
217 {
218 HTMLUtil.TD_O(ref output, "align_top", ssnlst.sessions.Count, 1);
219 output.Append(ssnlst.firstname);
220 HTMLUtil.TD_C(ref output);
221 HTMLUtil.TD_O(ref output, "align_top", ssnlst.sessions.Count, 1);
222 output.Append(ssnlst.lastname);
223 HTMLUtil.TD_C(ref output);
224 }
225 HTMLUtil.TD_O(ref output, "content");
226 output.Append(sesdata.last_update.ToShortDateString());
227 output.Append(" - ");
228 output.Append(sesdata.last_update.ToShortTimeString());
229 HTMLUtil.TD_C(ref output);
230 HTMLUtil.TD_O(ref output, "content");
231 TimeSpan dtlength = sesdata.last_update.Subtract(sesdata.start_time);
232 if (dtlength.Days > 0)
233 {
234 output.Append(dtlength.Days);
235 output.Append(" Days ");
236 }
237 if (dtlength.Hours > 0)
238 {
239 output.Append(dtlength.Hours);
240 output.Append(" Hours ");
241 }
242 if (dtlength.Minutes > 0)
243 {
244 output.Append(dtlength.Minutes);
245 output.Append(" Minutes");
246 }
247 HTMLUtil.TD_C(ref output);
248 HTMLUtil.TD_O(ref output, "content");
249 output.Append(sesdata.client_version);
250 HTMLUtil.TD_C(ref output);
251 HTMLUtil.TR_C(ref output);
252
253 }
254 HTMLUtil.TR_O(ref output, "");
255 HTMLUtil.TD_O(ref output, "align_top", 1, 5);
256 HTMLUtil.HR(ref output, "");
257 HTMLUtil.TD_C(ref output);
258 HTMLUtil.TR_C(ref output);
259 }
260 HTMLUtil.TABLE_C(ref output);
261 output.Append("</BODY>\n</HTML>");
262 return output.ToString();
263 }
264
265 public class SessionList
266 {
267 public string firstname;
268 public string lastname;
269 public UUID user_id;
270 public List<ShortSessionData> sessions;
271 }
272
273 public struct ShortSessionData
274 {
275 public UUID session_id;
276 public string client_version;
277 public DateTime last_update;
278 public DateTime start_time;
279 }
280
281 public string RenderJson(Hashtable pModelResult)
282 {
283 return "{}";
284 }
285 #endregion
286 }
287
288}
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
deleted file mode 100644
index 06d9e91..0000000
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ /dev/null
@@ -1,276 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Text;
33using Mono.Data.SqliteClient;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Monitoring;
38
39namespace OpenSim.Region.UserStatistics
40{
41 public class SimStatsAJAX : IStatsController
42 {
43 #region IStatsController Members
44
45 public string ReportName
46 {
47 get { return ""; }
48 }
49
50 public Hashtable ProcessModel(Hashtable pParams)
51 {
52 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
53
54 Hashtable nh = new Hashtable();
55 nh.Add("hdata", m_scene);
56 nh.Add("simstats", pParams["SimStats"]);
57 return nh;
58 }
59
60 public string RenderView(Hashtable pModelResult)
61 {
62 StringBuilder output = new StringBuilder();
63 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
64 Dictionary<UUID, USimStatsData> sdatadic = (Dictionary<UUID,USimStatsData>)pModelResult["simstats"];
65
66 const string TableClass = "defaultr";
67 const string TRClass = "defaultr";
68 const string TDHeaderClass = "header";
69 const string TDDataClass = "content";
70 //const string TDDataClassRight = "contentright";
71 const string TDDataClassCenter = "contentcenter";
72
73 foreach (USimStatsData sdata in sdatadic.Values)
74 {
75
76
77 foreach (Scene sn in all_scenes)
78 {
79 if (sn.RegionInfo.RegionID == sdata.RegionId)
80 {
81 output.Append("<H2>");
82 output.Append(sn.RegionInfo.RegionName);
83 output.Append("</H2>");
84 }
85 }
86 HTMLUtil.TABLE_O(ref output, TableClass);
87 HTMLUtil.TR_O(ref output, TRClass);
88 HTMLUtil.TD_O(ref output, TDHeaderClass);
89 output.Append("Dilatn");
90 HTMLUtil.TD_C(ref output);
91 HTMLUtil.TD_O(ref output, TDHeaderClass);
92 output.Append("SimFPS");
93 HTMLUtil.TD_C(ref output);
94 HTMLUtil.TD_O(ref output, TDHeaderClass);
95 output.Append("PhysFPS");
96 HTMLUtil.TD_C(ref output);
97 HTMLUtil.TD_O(ref output, TDHeaderClass);
98 output.Append("AgntUp");
99 HTMLUtil.TD_C(ref output);
100 HTMLUtil.TD_O(ref output, TDHeaderClass);
101 output.Append("RootAg");
102 HTMLUtil.TD_C(ref output);
103 HTMLUtil.TD_O(ref output, TDHeaderClass);
104 output.Append("ChldAg");
105 HTMLUtil.TD_C(ref output);
106 HTMLUtil.TD_O(ref output, TDHeaderClass);
107 output.Append("Prims");
108 HTMLUtil.TD_C(ref output);
109 HTMLUtil.TD_O(ref output, TDHeaderClass);
110 output.Append("ATvPrm");
111 HTMLUtil.TD_C(ref output);
112 HTMLUtil.TD_O(ref output, TDHeaderClass);
113 output.Append("AtvScr");
114 HTMLUtil.TD_C(ref output);
115 HTMLUtil.TD_O(ref output, TDHeaderClass);
116 output.Append("ScrLPS");
117 HTMLUtil.TD_C(ref output);
118 HTMLUtil.TR_C(ref output);
119 HTMLUtil.TR_O(ref output, TRClass);
120 HTMLUtil.TD_O(ref output, TDDataClass);
121 output.Append(sdata.TimeDilation);
122 HTMLUtil.TD_C(ref output);
123 HTMLUtil.TD_O(ref output, TDDataClass);
124 output.Append(sdata.SimFps);
125 HTMLUtil.TD_C(ref output);
126 HTMLUtil.TD_O(ref output, TDDataClassCenter);
127 output.Append(sdata.PhysicsFps);
128 HTMLUtil.TD_C(ref output);
129 HTMLUtil.TD_O(ref output, TDDataClassCenter);
130 output.Append(sdata.AgentUpdates);
131 HTMLUtil.TD_C(ref output);
132 HTMLUtil.TD_O(ref output, TDDataClassCenter);
133 output.Append(sdata.RootAgents);
134 HTMLUtil.TD_C(ref output);
135 HTMLUtil.TD_O(ref output, TDDataClassCenter);
136 output.Append(sdata.ChildAgents);
137 HTMLUtil.TD_C(ref output);
138 HTMLUtil.TD_O(ref output, TDDataClassCenter);
139 output.Append(sdata.TotalPrims);
140 HTMLUtil.TD_C(ref output);
141 HTMLUtil.TD_O(ref output, TDDataClassCenter);
142 output.Append(sdata.ActivePrims);
143 HTMLUtil.TD_C(ref output);
144 HTMLUtil.TD_O(ref output, TDDataClassCenter);
145 output.Append(sdata.ActiveScripts);
146 HTMLUtil.TD_C(ref output);
147 HTMLUtil.TD_O(ref output, TDDataClassCenter);
148 output.Append(sdata.ScriptLinesPerSecond);
149 HTMLUtil.TD_C(ref output);
150 HTMLUtil.TR_C(ref output);
151 HTMLUtil.TR_O(ref output, TRClass);
152 HTMLUtil.TD_O(ref output, TDHeaderClass);
153 output.Append("FrmMS");
154 HTMLUtil.TD_C(ref output);
155 HTMLUtil.TD_O(ref output, TDHeaderClass);
156 output.Append("AgtMS");
157 HTMLUtil.TD_C(ref output);
158 HTMLUtil.TD_O(ref output, TDHeaderClass);
159 output.Append("PhysMS");
160 HTMLUtil.TD_C(ref output);
161 HTMLUtil.TD_O(ref output, TDHeaderClass);
162 output.Append("OthrMS");
163 HTMLUtil.TD_C(ref output);
164 HTMLUtil.TD_O(ref output, TDHeaderClass);
165 output.Append("OutPPS");
166 HTMLUtil.TD_C(ref output);
167 HTMLUtil.TD_O(ref output, TDHeaderClass);
168 output.Append("InPPS");
169 HTMLUtil.TD_C(ref output);
170 HTMLUtil.TD_O(ref output, TDHeaderClass);
171 output.Append("NoAckKB");
172 HTMLUtil.TD_C(ref output);
173 HTMLUtil.TD_O(ref output, TDHeaderClass);
174 output.Append("PndDWN");
175 HTMLUtil.TD_C(ref output);
176 HTMLUtil.TD_O(ref output, TDHeaderClass);
177 output.Append("PndUP");
178 HTMLUtil.TD_C(ref output);
179 HTMLUtil.TR_C(ref output);
180 HTMLUtil.TR_O(ref output, TRClass);
181 HTMLUtil.TD_O(ref output, TDDataClass);
182 output.Append(sdata.TotalFrameTime);
183 HTMLUtil.TD_C(ref output);
184 HTMLUtil.TD_O(ref output, TDDataClass);
185 output.Append(sdata.AgentFrameTime);
186 HTMLUtil.TD_C(ref output);
187 HTMLUtil.TD_O(ref output, TDDataClassCenter);
188 output.Append(sdata.PhysicsFrameTime);
189 HTMLUtil.TD_C(ref output);
190 HTMLUtil.TD_O(ref output, TDDataClassCenter);
191 output.Append(sdata.OtherFrameTime);
192 HTMLUtil.TD_C(ref output);
193 HTMLUtil.TD_O(ref output, TDDataClassCenter);
194 output.Append(sdata.OutPacketsPerSecond);
195 HTMLUtil.TD_C(ref output);
196 HTMLUtil.TD_O(ref output, TDDataClassCenter);
197 output.Append(sdata.InPacketsPerSecond);
198 HTMLUtil.TD_C(ref output);
199 HTMLUtil.TD_O(ref output, TDDataClassCenter);
200 output.Append(sdata.UnackedBytes);
201 HTMLUtil.TD_C(ref output);
202 HTMLUtil.TD_O(ref output, TDDataClassCenter);
203 output.Append(sdata.PendingDownloads);
204 HTMLUtil.TD_C(ref output);
205 HTMLUtil.TD_O(ref output, TDDataClassCenter);
206 output.Append(sdata.PendingUploads);
207 HTMLUtil.TD_C(ref output);
208 HTMLUtil.TR_C(ref output);
209 HTMLUtil.TABLE_C(ref output);
210
211 }
212
213 return output.ToString();
214 }
215
216 /// <summary>
217 /// Return stat information for all regions in the sim. Returns data of the form:
218 /// <pre>
219 /// {"REGIONNAME": {
220 /// "region": "REGIONNAME",
221 /// "timeDilation": "101",
222 /// ... // the rest of the stat info
223 /// },
224 /// ... // entries for each region
225 /// }
226 /// </pre>
227 /// </summary>
228 /// <param name="pModelResult"></param>
229 /// <returns></returns>
230 public string RenderJson(Hashtable pModelResult)
231 {
232 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
233 Dictionary<UUID, USimStatsData> sdatadic = (Dictionary<UUID,USimStatsData>)pModelResult["simstats"];
234
235 OSDMap allStatsInfo = new OpenMetaverse.StructuredData.OSDMap();
236 foreach (USimStatsData sdata in sdatadic.Values)
237 {
238 OSDMap statsInfo = new OpenMetaverse.StructuredData.OSDMap();
239 string regionName = "unknown";
240 foreach (Scene sn in all_scenes)
241 {
242 if (sn.RegionInfo.RegionID == sdata.RegionId)
243 {
244 regionName = sn.RegionInfo.RegionName;
245 break;
246 }
247 }
248 statsInfo.Add("region", new OSDString(regionName));
249 statsInfo.Add("timeDilation", new OSDString(sdata.TimeDilation.ToString()));
250 statsInfo.Add("simFPS", new OSDString(sdata.SimFps.ToString()));
251 statsInfo.Add("physicsFPS", new OSDString(sdata.PhysicsFps.ToString()));
252 statsInfo.Add("agentUpdates", new OSDString(sdata.AgentUpdates.ToString()));
253 statsInfo.Add("rootAgents", new OSDString(sdata.RootAgents.ToString()));
254 statsInfo.Add("childAgents", new OSDString(sdata.ChildAgents.ToString()));
255 statsInfo.Add("totalPrims", new OSDString(sdata.TotalPrims.ToString()));
256 statsInfo.Add("activePrims", new OSDString(sdata.ActivePrims.ToString()));
257 statsInfo.Add("activeScripts", new OSDString(sdata.ActiveScripts.ToString()));
258 statsInfo.Add("scriptLinesPerSec", new OSDString(sdata.ScriptLinesPerSecond.ToString()));
259 statsInfo.Add("totalFrameTime", new OSDString(sdata.TotalFrameTime.ToString()));
260 statsInfo.Add("agentFrameTime", new OSDString(sdata.AgentFrameTime.ToString()));
261 statsInfo.Add("physicsFrameTime", new OSDString(sdata.PhysicsFrameTime.ToString()));
262 statsInfo.Add("otherFrameTime", new OSDString(sdata.OtherFrameTime.ToString()));
263 statsInfo.Add("outPacketsPerSec", new OSDString(sdata.OutPacketsPerSecond.ToString()));
264 statsInfo.Add("inPacketsPerSec", new OSDString(sdata.InPacketsPerSecond.ToString()));
265 statsInfo.Add("unackedByptes", new OSDString(sdata.UnackedBytes.ToString()));
266 statsInfo.Add("pendingDownloads", new OSDString(sdata.PendingDownloads.ToString()));
267 statsInfo.Add("pendingUploads", new OSDString(sdata.PendingUploads.ToString()));
268
269 allStatsInfo.Add(regionName, statsInfo);
270 }
271 return allStatsInfo.ToString();
272 }
273
274 #endregion
275 }
276}
diff --git a/OpenSim/Region/UserStatistics/Updater_distributor.cs b/OpenSim/Region/UserStatistics/Updater_distributor.cs
deleted file mode 100644
index 601e06b..0000000
--- a/OpenSim/Region/UserStatistics/Updater_distributor.cs
+++ /dev/null
@@ -1,70 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Collections;
31using System.Collections.Generic;
32using System.Text;
33using OpenSim.Framework;
34
35namespace OpenSim.Region.UserStatistics
36{
37 public class Updater_distributor : IStatsController
38 {
39 private string updaterjs = string.Empty;
40
41 public string ReportName
42 {
43 get { return ""; }
44 }
45
46 public Hashtable ProcessModel(Hashtable pParams)
47 {
48 Hashtable pResult = new Hashtable();
49 if (updaterjs.Length == 0)
50 {
51 StreamReader fs = new StreamReader(new FileStream(Util.dataDir() + "/data/updater.js", FileMode.Open));
52 updaterjs = fs.ReadToEnd();
53 fs.Close();
54 fs.Dispose();
55 }
56 pResult["js"] = updaterjs;
57 return pResult;
58 }
59
60 public string RenderView(Hashtable pModelResult)
61 {
62 return pModelResult["js"].ToString();
63 }
64
65 public string RenderJson(Hashtable pModelResult) {
66 return "{}";
67 }
68
69 }
70} \ No newline at end of file
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
deleted file mode 100644
index 8ccb751..0000000
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ /dev/null
@@ -1,1206 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Net; // to be used for REST-->Grid shortly
33using System.Reflection;
34using System.Text;
35using System.Threading;
36using log4net;
37using Nini.Config;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using Mono.Data.SqliteClient;
46using Mono.Addins;
47
48using Caps = OpenSim.Framework.Capabilities.Caps;
49
50using OSD = OpenMetaverse.StructuredData.OSD;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52
53[assembly: Addin("WebStats", OpenSim.VersionInfo.VersionNumber)]
54[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
55
56namespace OpenSim.Region.UserStatistics
57{
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebStatsModule")]
59 public class WebStatsModule : ISharedRegionModule
60 {
61 private static readonly ILog m_log =
62 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
63
64 private static SqliteConnection dbConn;
65
66 /// <summary>
67 /// User statistics sessions keyed by agent ID
68 /// </summary>
69 private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>();
70
71 private List<Scene> m_scenes = new List<Scene>();
72 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
73 private Dictionary<UUID, USimStatsData> m_simstatsCounters = new Dictionary<UUID, USimStatsData>();
74 private const int updateStatsMod = 6;
75 private int updateLogMod = 1;
76 private volatile int updateLogCounter = 0;
77 private volatile int concurrencyCounter = 0;
78 private bool enabled = false;
79 private string m_loglines = String.Empty;
80 private volatile int lastHit = 12000;
81
82 #region ISharedRegionModule
83
84 public virtual void Initialise(IConfigSource config)
85 {
86 IConfig cnfg = config.Configs["WebStats"];
87
88 if (cnfg != null)
89 enabled = cnfg.GetBoolean("enabled", false);
90 }
91
92 public virtual void PostInitialise()
93 {
94 if (!enabled)
95 return;
96
97 if (Util.IsWindows())
98 Util.LoadArchSpecificWindowsDll("sqlite3.dll");
99
100 //IConfig startupConfig = config.Configs["Startup"];
101
102 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3");
103 dbConn.Open();
104 CreateTables(dbConn);
105
106 Prototype_distributor protodep = new Prototype_distributor();
107 Updater_distributor updatedep = new Updater_distributor();
108 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX();
109 SimStatsAJAX ajSimStats = new SimStatsAJAX();
110 LogLinesAJAX ajLogLines = new LogLinesAJAX();
111 Default_Report defaultReport = new Default_Report();
112 Clients_report clientReport = new Clients_report();
113 Sessions_Report sessionsReport = new Sessions_Report();
114
115 reports.Add("prototype.js", protodep);
116 reports.Add("updater.js", updatedep);
117 reports.Add("activeconnectionsajax.html", ajConnections);
118 reports.Add("simstatsajax.html", ajSimStats);
119 reports.Add("activelogajax.html", ajLogLines);
120 reports.Add("default.report", defaultReport);
121 reports.Add("clients.report", clientReport);
122 reports.Add("sessions.report", sessionsReport);
123
124 reports.Add("sim.css", new Prototype_distributor("sim.css"));
125 reports.Add("sim.html", new Prototype_distributor("sim.html"));
126 reports.Add("jquery.js", new Prototype_distributor("jquery.js"));
127
128 ////
129 // Add Your own Reports here (Do Not Modify Lines here Devs!)
130 ////
131
132 ////
133 // End Own reports section
134 ////
135
136 MainServer.Instance.AddHTTPHandler("/SStats/", HandleStatsRequest);
137 MainServer.Instance.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest);
138 }
139
140 public virtual void AddRegion(Scene scene)
141 {
142 if (!enabled)
143 return;
144
145 lock (m_scenes)
146 {
147 m_scenes.Add(scene);
148 updateLogMod = m_scenes.Count * 2;
149
150 m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID));
151
152 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
153 scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps;
154 scene.EventManager.OnClientClosed += OnClientClosed;
155 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
156 scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket;
157 }
158 }
159
160 public void RegionLoaded(Scene scene)
161 {
162 }
163
164 public void RemoveRegion(Scene scene)
165 {
166 if (!enabled)
167 return;
168
169 lock (m_scenes)
170 {
171 m_scenes.Remove(scene);
172 updateLogMod = m_scenes.Count * 2;
173 m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
174 }
175 }
176
177 public virtual void Close()
178 {
179 if (!enabled)
180 return;
181
182 dbConn.Close();
183 dbConn.Dispose();
184 m_sessions.Clear();
185 m_scenes.Clear();
186 reports.Clear();
187 m_simstatsCounters.Clear();
188 }
189
190 public virtual string Name
191 {
192 get { return "ViewerStatsModule"; }
193 }
194
195 public Type ReplaceableInterface
196 {
197 get { return null; }
198 }
199
200 #endregion
201
202 private void ReceiveClassicSimStatsPacket(SimStats stats)
203 {
204 if (!enabled)
205 return;
206
207 try
208 {
209 // Ignore the update if there's a report running right now
210 // ignore the update if there hasn't been a hit in 30 seconds.
211 if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000)
212 return;
213
214 // We will conduct this under lock so that fields such as updateLogCounter do not potentially get
215 // confused if a scene is removed.
216 // XXX: Possibly the scope of this lock could be reduced though it's not critical.
217 lock (m_scenes)
218 {
219 if (updateLogMod != 0 && updateLogCounter++ % updateLogMod == 0)
220 {
221 m_loglines = readLogLines(10);
222
223 if (updateLogCounter > 10000)
224 updateLogCounter = 1;
225 }
226
227 USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
228
229 if ((++ss.StatsCounter % updateStatsMod) == 0)
230 {
231 ss.ConsumeSimStats(stats);
232 }
233 }
234 }
235 catch (KeyNotFoundException)
236 {
237 }
238 }
239
240 private Hashtable HandleUnknownCAPSRequest(Hashtable request)
241 {
242 //string regpath = request["uri"].ToString();
243 int response_code = 200;
244 string contenttype = "text/html";
245 UpdateUserStats(ParseViewerStats(request["body"].ToString(), UUID.Zero), dbConn);
246 Hashtable responsedata = new Hashtable();
247
248 responsedata["int_response_code"] = response_code;
249 responsedata["content_type"] = contenttype;
250 responsedata["keepalive"] = false;
251 responsedata["str_response_string"] = string.Empty;
252 return responsedata;
253 }
254
255 private Hashtable HandleStatsRequest(Hashtable request)
256 {
257 lastHit = System.Environment.TickCount;
258 Hashtable responsedata = new Hashtable();
259 string regpath = request["uri"].ToString();
260 int response_code = 404;
261 string contenttype = "text/html";
262 bool jsonFormatOutput = false;
263
264 string strOut = string.Empty;
265
266 // The request patch should be "/SStats/reportName" where 'reportName'
267 // is one of the names added to the 'reports' hashmap.
268 regpath = regpath.Remove(0, 8);
269 if (regpath.Length == 0) regpath = "default.report";
270 if (reports.ContainsKey(regpath))
271 {
272 IStatsController rep = reports[regpath];
273 Hashtable repParams = new Hashtable();
274
275 if (request.ContainsKey("json"))
276 jsonFormatOutput = true;
277
278 if (request.ContainsKey("requestvars"))
279 repParams["RequestVars"] = request["requestvars"];
280 else
281 repParams["RequestVars"] = new Hashtable();
282
283 if (request.ContainsKey("querystringkeys"))
284 repParams["QueryStringKeys"] = request["querystringkeys"];
285 else
286 repParams["QueryStringKeys"] = new string[0];
287
288
289 repParams["DatabaseConnection"] = dbConn;
290 repParams["Scenes"] = m_scenes;
291 repParams["SimStats"] = m_simstatsCounters;
292 repParams["LogLines"] = m_loglines;
293 repParams["Reports"] = reports;
294
295 concurrencyCounter++;
296
297 if (jsonFormatOutput)
298 {
299 strOut = rep.RenderJson(rep.ProcessModel(repParams));
300 contenttype = "text/json";
301 }
302 else
303 {
304 strOut = rep.RenderView(rep.ProcessModel(repParams));
305 }
306
307 if (regpath.EndsWith("js"))
308 {
309 contenttype = "text/javascript";
310 }
311
312 if (regpath.EndsWith("css"))
313 {
314 contenttype = "text/css";
315 }
316
317 concurrencyCounter--;
318
319 response_code = 200;
320 }
321 else
322 {
323 strOut = MainServer.Instance.GetHTTP404("");
324 }
325
326 responsedata["int_response_code"] = response_code;
327 responsedata["content_type"] = contenttype;
328 responsedata["keepalive"] = false;
329 responsedata["str_response_string"] = strOut;
330
331 return responsedata;
332 }
333
334 private void CreateTables(SqliteConnection db)
335 {
336 using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db))
337 {
338 createcmd.ExecuteNonQuery();
339 }
340 }
341
342 private void OnRegisterCaps(UUID agentID, Caps caps)
343 {
344// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
345
346 string capsPath = "/CAPS/VS/" + UUID.Random();
347 caps.RegisterHandler(
348 "ViewerStats",
349 new RestStreamHandler(
350 "POST",
351 capsPath,
352 (request, path, param, httpRequest, httpResponse)
353 => ViewerStatsReport(request, path, param, agentID, caps),
354 "ViewerStats",
355 agentID.ToString()));
356 }
357
358 private void OnDeRegisterCaps(UUID agentID, Caps caps)
359 {
360 }
361
362 protected virtual void AddEventHandlers()
363 {
364 lock (m_scenes)
365 {
366 updateLogMod = m_scenes.Count * 2;
367 foreach (Scene scene in m_scenes)
368 {
369 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
370 scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps;
371 scene.EventManager.OnClientClosed += OnClientClosed;
372 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
373 }
374 }
375 }
376
377 private void OnMakeRootAgent(ScenePresence agent)
378 {
379// m_log.DebugFormat(
380// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}",
381// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name);
382
383 lock (m_sessions)
384 {
385 UserSession uid;
386
387 if (!m_sessions.ContainsKey(agent.UUID))
388 {
389 UserSessionData usd = UserSessionUtil.newUserSessionData();
390 uid = new UserSession();
391 uid.name_f = agent.Firstname;
392 uid.name_l = agent.Lastname;
393 uid.session_data = usd;
394
395 m_sessions.Add(agent.UUID, uid);
396 }
397 else
398 {
399 uid = m_sessions[agent.UUID];
400 }
401
402 uid.region_id = agent.Scene.RegionInfo.RegionID;
403 uid.session_id = agent.ControllingClient.SessionId;
404 }
405 }
406
407 private void OnClientClosed(UUID agentID, Scene scene)
408 {
409 lock (m_sessions)
410 {
411 if (m_sessions.ContainsKey(agentID) && m_sessions[agentID].region_id == scene.RegionInfo.RegionID)
412 {
413 m_sessions.Remove(agentID);
414 }
415 }
416 }
417
418 private string readLogLines(int amount)
419 {
420 Encoding encoding = Encoding.ASCII;
421 int sizeOfChar = encoding.GetByteCount("\n");
422 byte[] buffer = encoding.GetBytes("\n");
423 string logfile = Util.logFile();
424 FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
425 Int64 tokenCount = 0;
426 Int64 endPosition = fs.Length / sizeOfChar;
427
428 for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar)
429 {
430 fs.Seek(-position, SeekOrigin.End);
431 fs.Read(buffer, 0, buffer.Length);
432
433 if (encoding.GetString(buffer) == "\n")
434 {
435 tokenCount++;
436 if (tokenCount == amount)
437 {
438 byte[] returnBuffer = new byte[fs.Length - fs.Position];
439 fs.Read(returnBuffer, 0, returnBuffer.Length);
440 fs.Close();
441 fs.Dispose();
442 return encoding.GetString(returnBuffer);
443 }
444 }
445 }
446
447 // handle case where number of tokens in file is less than numberOfTokens
448 fs.Seek(0, SeekOrigin.Begin);
449 buffer = new byte[fs.Length];
450 fs.Read(buffer, 0, buffer.Length);
451 fs.Close();
452 fs.Dispose();
453 return encoding.GetString(buffer);
454 }
455
456 /// <summary>
457 /// Callback for a viewerstats cap
458 /// </summary>
459 /// <param name="request"></param>
460 /// <param name="path"></param>
461 /// <param name="param"></param>
462 /// <param name="agentID"></param>
463 /// <param name="caps"></param>
464 /// <returns></returns>
465 private string ViewerStatsReport(string request, string path, string param,
466 UUID agentID, Caps caps)
467 {
468// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID);
469
470 UpdateUserStats(ParseViewerStats(request, agentID), dbConn);
471
472 return String.Empty;
473 }
474
475 private UserSession ParseViewerStats(string request, UUID agentID)
476 {
477 UserSession uid = new UserSession();
478 UserSessionData usd;
479 OSD message = OSDParser.DeserializeLLSDXml(request);
480 OSDMap mmap;
481
482 lock (m_sessions)
483 {
484 if (agentID != UUID.Zero)
485 {
486 if (!m_sessions.ContainsKey(agentID))
487 {
488 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
489 return new UserSession();
490 }
491
492 uid = m_sessions[agentID];
493
494// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID);
495 }
496 else
497 {
498 // parse through the beginning to locate the session
499 if (message.Type != OSDType.Map)
500 return new UserSession();
501
502 mmap = (OSDMap)message;
503 {
504 UUID sessionID = mmap["session_id"].AsUUID();
505
506 if (sessionID == UUID.Zero)
507 return new UserSession();
508
509
510 // search through each session looking for the owner
511 foreach (UUID usersessionid in m_sessions.Keys)
512 {
513 // got it!
514 if (m_sessions[usersessionid].session_id == sessionID)
515 {
516 agentID = usersessionid;
517 uid = m_sessions[usersessionid];
518 break;
519 }
520
521 }
522
523 // can't find a session
524 if (agentID == UUID.Zero)
525 {
526 return new UserSession();
527 }
528 }
529 }
530 }
531
532 usd = uid.session_data;
533
534 if (message.Type != OSDType.Map)
535 return new UserSession();
536
537 mmap = (OSDMap)message;
538 {
539 if (mmap["agent"].Type != OSDType.Map)
540 return new UserSession();
541 OSDMap agent_map = (OSDMap)mmap["agent"];
542 usd.agent_id = agentID;
543 usd.name_f = uid.name_f;
544 usd.name_l = uid.name_l;
545 usd.region_id = uid.region_id;
546 usd.a_language = agent_map["language"].AsString();
547 usd.mem_use = (float)agent_map["mem_use"].AsReal();
548 usd.meters_traveled = (float)agent_map["meters_traveled"].AsReal();
549 usd.regions_visited = agent_map["regions_visited"].AsInteger();
550 usd.run_time = (float)agent_map["run_time"].AsReal();
551 usd.start_time = (float)agent_map["start_time"].AsReal();
552 usd.client_version = agent_map["version"].AsString();
553
554 UserSessionUtil.UpdateMultiItems(ref usd, agent_map["agents_in_view"].AsInteger(),
555 (float)agent_map["ping"].AsReal(),
556 (float)agent_map["sim_fps"].AsReal(),
557 (float)agent_map["fps"].AsReal());
558
559 if (mmap["downloads"].Type != OSDType.Map)
560 return new UserSession();
561 OSDMap downloads_map = (OSDMap)mmap["downloads"];
562 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
563 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
564 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
565
566// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID());
567
568 usd.session_id = mmap["session_id"].AsUUID();
569
570 if (mmap["system"].Type != OSDType.Map)
571 return new UserSession();
572 OSDMap system_map = (OSDMap)mmap["system"];
573
574 usd.s_cpu = system_map["cpu"].AsString();
575 usd.s_gpu = system_map["gpu"].AsString();
576 usd.s_os = system_map["os"].AsString();
577 usd.s_ram = system_map["ram"].AsInteger();
578
579 if (mmap["stats"].Type != OSDType.Map)
580 return new UserSession();
581
582 OSDMap stats_map = (OSDMap)mmap["stats"];
583 {
584
585 if (stats_map["failures"].Type != OSDType.Map)
586 return new UserSession();
587 OSDMap stats_failures = (OSDMap)stats_map["failures"];
588 usd.f_dropped = stats_failures["dropped"].AsInteger();
589 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
590 usd.f_invalid = stats_failures["invalid"].AsInteger();
591 usd.f_resent = stats_failures["resent"].AsInteger();
592 usd.f_send_packet = stats_failures["send_packet"].AsInteger();
593
594 if (stats_map["net"].Type != OSDType.Map)
595 return new UserSession();
596 OSDMap stats_net = (OSDMap)stats_map["net"];
597 {
598 if (stats_net["in"].Type != OSDType.Map)
599 return new UserSession();
600
601 OSDMap net_in = (OSDMap)stats_net["in"];
602 usd.n_in_kb = (float)net_in["kbytes"].AsReal();
603 usd.n_in_pk = net_in["packets"].AsInteger();
604
605 if (stats_net["out"].Type != OSDType.Map)
606 return new UserSession();
607 OSDMap net_out = (OSDMap)stats_net["out"];
608
609 usd.n_out_kb = (float)net_out["kbytes"].AsReal();
610 usd.n_out_pk = net_out["packets"].AsInteger();
611 }
612 }
613 }
614
615 uid.session_data = usd;
616 m_sessions[agentID] = uid;
617
618// m_log.DebugFormat(
619// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
620
621 return uid;
622 }
623
624 private void UpdateUserStats(UserSession uid, SqliteConnection db)
625 {
626// m_log.DebugFormat(
627// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
628
629 if (uid.session_id == UUID.Zero)
630 return;
631
632 lock (db)
633 {
634 using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_INSERT, db))
635 {
636 updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString()));
637 updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString()));
638 updatecmd.Parameters.Add(new SqliteParameter(":region_id", uid.session_data.region_id.ToString()));
639 updatecmd.Parameters.Add(new SqliteParameter(":last_updated", (int) uid.session_data.last_updated));
640 updatecmd.Parameters.Add(new SqliteParameter(":remote_ip", uid.session_data.remote_ip));
641 updatecmd.Parameters.Add(new SqliteParameter(":name_f", uid.session_data.name_f));
642 updatecmd.Parameters.Add(new SqliteParameter(":name_l", uid.session_data.name_l));
643 updatecmd.Parameters.Add(new SqliteParameter(":avg_agents_in_view", uid.session_data.avg_agents_in_view));
644 updatecmd.Parameters.Add(new SqliteParameter(":min_agents_in_view",
645 (int) uid.session_data.min_agents_in_view));
646 updatecmd.Parameters.Add(new SqliteParameter(":max_agents_in_view",
647 (int) uid.session_data.max_agents_in_view));
648 updatecmd.Parameters.Add(new SqliteParameter(":mode_agents_in_view",
649 (int) uid.session_data.mode_agents_in_view));
650 updatecmd.Parameters.Add(new SqliteParameter(":avg_fps", uid.session_data.avg_fps));
651 updatecmd.Parameters.Add(new SqliteParameter(":min_fps", uid.session_data.min_fps));
652 updatecmd.Parameters.Add(new SqliteParameter(":max_fps", uid.session_data.max_fps));
653 updatecmd.Parameters.Add(new SqliteParameter(":mode_fps", uid.session_data.mode_fps));
654 updatecmd.Parameters.Add(new SqliteParameter(":a_language", uid.session_data.a_language));
655 updatecmd.Parameters.Add(new SqliteParameter(":mem_use", uid.session_data.mem_use));
656 updatecmd.Parameters.Add(new SqliteParameter(":meters_traveled", uid.session_data.meters_traveled));
657 updatecmd.Parameters.Add(new SqliteParameter(":avg_ping", uid.session_data.avg_ping));
658 updatecmd.Parameters.Add(new SqliteParameter(":min_ping", uid.session_data.min_ping));
659 updatecmd.Parameters.Add(new SqliteParameter(":max_ping", uid.session_data.max_ping));
660 updatecmd.Parameters.Add(new SqliteParameter(":mode_ping", uid.session_data.mode_ping));
661 updatecmd.Parameters.Add(new SqliteParameter(":regions_visited", uid.session_data.regions_visited));
662 updatecmd.Parameters.Add(new SqliteParameter(":run_time", uid.session_data.run_time));
663 updatecmd.Parameters.Add(new SqliteParameter(":avg_sim_fps", uid.session_data.avg_sim_fps));
664 updatecmd.Parameters.Add(new SqliteParameter(":min_sim_fps", uid.session_data.min_sim_fps));
665 updatecmd.Parameters.Add(new SqliteParameter(":max_sim_fps", uid.session_data.max_sim_fps));
666 updatecmd.Parameters.Add(new SqliteParameter(":mode_sim_fps", uid.session_data.mode_sim_fps));
667 updatecmd.Parameters.Add(new SqliteParameter(":start_time", uid.session_data.start_time));
668 updatecmd.Parameters.Add(new SqliteParameter(":client_version", uid.session_data.client_version));
669 updatecmd.Parameters.Add(new SqliteParameter(":s_cpu", uid.session_data.s_cpu));
670 updatecmd.Parameters.Add(new SqliteParameter(":s_gpu", uid.session_data.s_gpu));
671 updatecmd.Parameters.Add(new SqliteParameter(":s_os", uid.session_data.s_os));
672 updatecmd.Parameters.Add(new SqliteParameter(":s_ram", uid.session_data.s_ram));
673 updatecmd.Parameters.Add(new SqliteParameter(":d_object_kb", uid.session_data.d_object_kb));
674 updatecmd.Parameters.Add(new SqliteParameter(":d_texture_kb", uid.session_data.d_texture_kb));
675 updatecmd.Parameters.Add(new SqliteParameter(":d_world_kb", uid.session_data.d_world_kb));
676 updatecmd.Parameters.Add(new SqliteParameter(":n_in_kb", uid.session_data.n_in_kb));
677 updatecmd.Parameters.Add(new SqliteParameter(":n_in_pk", uid.session_data.n_in_pk));
678 updatecmd.Parameters.Add(new SqliteParameter(":n_out_kb", uid.session_data.n_out_kb));
679 updatecmd.Parameters.Add(new SqliteParameter(":n_out_pk", uid.session_data.n_out_pk));
680 updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped));
681 updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends));
682 updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid));
683 updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit));
684 updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent));
685 updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet));
686
687// StringBuilder parameters = new StringBuilder();
688// SqliteParameterCollection spc = updatecmd.Parameters;
689// foreach (SqliteParameter sp in spc)
690// parameters.AppendFormat("{0}={1},", sp.ParameterName, sp.Value);
691//
692// m_log.DebugFormat("[WEB STATS MODULE]: Parameters {0}", parameters);
693
694// m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id);
695
696 updatecmd.ExecuteNonQuery();
697 }
698 }
699 }
700
701 #region SQL
702 private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE IF NOT EXISTS stats_session_data (
703 session_id VARCHAR(36) NOT NULL PRIMARY KEY,
704 agent_id VARCHAR(36) NOT NULL DEFAULT '',
705 region_id VARCHAR(36) NOT NULL DEFAULT '',
706 last_updated INT NOT NULL DEFAULT '0',
707 remote_ip VARCHAR(16) NOT NULL DEFAULT '',
708 name_f VARCHAR(50) NOT NULL DEFAULT '',
709 name_l VARCHAR(50) NOT NULL DEFAULT '',
710 avg_agents_in_view FLOAT NOT NULL DEFAULT '0',
711 min_agents_in_view INT NOT NULL DEFAULT '0',
712 max_agents_in_view INT NOT NULL DEFAULT '0',
713 mode_agents_in_view INT NOT NULL DEFAULT '0',
714 avg_fps FLOAT NOT NULL DEFAULT '0',
715 min_fps FLOAT NOT NULL DEFAULT '0',
716 max_fps FLOAT NOT NULL DEFAULT '0',
717 mode_fps FLOAT NOT NULL DEFAULT '0',
718 a_language VARCHAR(25) NOT NULL DEFAULT '',
719 mem_use FLOAT NOT NULL DEFAULT '0',
720 meters_traveled FLOAT NOT NULL DEFAULT '0',
721 avg_ping FLOAT NOT NULL DEFAULT '0',
722 min_ping FLOAT NOT NULL DEFAULT '0',
723 max_ping FLOAT NOT NULL DEFAULT '0',
724 mode_ping FLOAT NOT NULL DEFAULT '0',
725 regions_visited INT NOT NULL DEFAULT '0',
726 run_time FLOAT NOT NULL DEFAULT '0',
727 avg_sim_fps FLOAT NOT NULL DEFAULT '0',
728 min_sim_fps FLOAT NOT NULL DEFAULT '0',
729 max_sim_fps FLOAT NOT NULL DEFAULT '0',
730 mode_sim_fps FLOAT NOT NULL DEFAULT '0',
731 start_time FLOAT NOT NULL DEFAULT '0',
732 client_version VARCHAR(255) NOT NULL DEFAULT '',
733 s_cpu VARCHAR(255) NOT NULL DEFAULT '',
734 s_gpu VARCHAR(255) NOT NULL DEFAULT '',
735 s_os VARCHAR(2255) NOT NULL DEFAULT '',
736 s_ram INT NOT NULL DEFAULT '0',
737 d_object_kb FLOAT NOT NULL DEFAULT '0',
738 d_texture_kb FLOAT NOT NULL DEFAULT '0',
739 d_world_kb FLOAT NOT NULL DEFAULT '0',
740 n_in_kb FLOAT NOT NULL DEFAULT '0',
741 n_in_pk INT NOT NULL DEFAULT '0',
742 n_out_kb FLOAT NOT NULL DEFAULT '0',
743 n_out_pk INT NOT NULL DEFAULT '0',
744 f_dropped INT NOT NULL DEFAULT '0',
745 f_failed_resends INT NOT NULL DEFAULT '0',
746 f_invalid INT NOT NULL DEFAULT '0',
747 f_off_circuit INT NOT NULL DEFAULT '0',
748 f_resent INT NOT NULL DEFAULT '0',
749 f_send_packet INT NOT NULL DEFAULT '0'
750 );";
751
752 private const string SQL_STATS_TABLE_INSERT = @"INSERT OR REPLACE INTO stats_session_data (
753session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view,
754mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping,
755regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram,
756d_object_kb, d_texture_kb, d_world_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_off_circuit,
757f_resent, f_send_packet
758)
759VALUES
760(
761:session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view,
762:mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping,
763:regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram,
764:d_object_kb, :d_texture_kb, :d_world_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_off_circuit,
765:f_resent, :f_send_packet
766)
767";
768
769 #endregion
770
771 }
772
773 public static class UserSessionUtil
774 {
775 public static UserSessionData newUserSessionData()
776 {
777 UserSessionData obj = ZeroSession(new UserSessionData());
778 return obj;
779 }
780
781 public static void UpdateMultiItems(ref UserSessionData s, int agents_in_view, float ping, float sim_fps, float fps)
782 {
783 // don't insert zero values here or it'll skew the statistics.
784 if (agents_in_view == 0 && fps == 0 && sim_fps == 0 && ping == 0)
785 return;
786 s._agents_in_view.Add(agents_in_view);
787 s._fps.Add(fps);
788 s._sim_fps.Add(sim_fps);
789 s._ping.Add(ping);
790
791 int[] __agents_in_view = s._agents_in_view.ToArray();
792
793 s.avg_agents_in_view = ArrayAvg_i(__agents_in_view);
794 s.min_agents_in_view = ArrayMin_i(__agents_in_view);
795 s.max_agents_in_view = ArrayMax_i(__agents_in_view);
796 s.mode_agents_in_view = ArrayMode_i(__agents_in_view);
797
798 float[] __fps = s._fps.ToArray();
799 s.avg_fps = ArrayAvg_f(__fps);
800 s.min_fps = ArrayMin_f(__fps);
801 s.max_fps = ArrayMax_f(__fps);
802 s.mode_fps = ArrayMode_f(__fps);
803
804 float[] __sim_fps = s._sim_fps.ToArray();
805 s.avg_sim_fps = ArrayAvg_f(__sim_fps);
806 s.min_sim_fps = ArrayMin_f(__sim_fps);
807 s.max_sim_fps = ArrayMax_f(__sim_fps);
808 s.mode_sim_fps = ArrayMode_f(__sim_fps);
809
810 float[] __ping = s._ping.ToArray();
811 s.avg_ping = ArrayAvg_f(__ping);
812 s.min_ping = ArrayMin_f(__ping);
813 s.max_ping = ArrayMax_f(__ping);
814 s.mode_ping = ArrayMode_f(__ping);
815 }
816
817 #region Statistics
818
819 public static int ArrayMin_i(int[] arr)
820 {
821 int cnt = arr.Length;
822 if (cnt == 0)
823 return 0;
824
825 Array.Sort(arr);
826 return arr[0];
827 }
828
829 public static int ArrayMax_i(int[] arr)
830 {
831 int cnt = arr.Length;
832 if (cnt == 0)
833 return 0;
834
835 Array.Sort(arr);
836 return arr[cnt-1];
837 }
838
839 public static float ArrayMin_f(float[] arr)
840 {
841 int cnt = arr.Length;
842 if (cnt == 0)
843 return 0;
844
845 Array.Sort(arr);
846 return arr[0];
847 }
848
849 public static float ArrayMax_f(float[] arr)
850 {
851 int cnt = arr.Length;
852 if (cnt == 0)
853 return 0;
854
855 Array.Sort(arr);
856 return arr[cnt - 1];
857 }
858
859 public static float ArrayAvg_i(int[] arr)
860 {
861 int cnt = arr.Length;
862
863 if (cnt == 0)
864 return 0;
865
866 float result = arr[0];
867
868 for (int i = 1; i < cnt; i++)
869 result += arr[i];
870
871 return result / cnt;
872 }
873
874 public static float ArrayAvg_f(float[] arr)
875 {
876 int cnt = arr.Length;
877
878 if (cnt == 0)
879 return 0;
880
881 float result = arr[0];
882
883 for (int i = 1; i < cnt; i++)
884 result += arr[i];
885
886 return result / cnt;
887 }
888
889 public static float ArrayMode_f(float[] arr)
890 {
891 List<float> mode = new List<float>();
892
893 float[] srtArr = new float[arr.Length];
894 float[,] freq = new float[arr.Length, 2];
895 Array.Copy(arr, srtArr, arr.Length);
896 Array.Sort(srtArr);
897
898 float tmp = srtArr[0];
899 int index = 0;
900 int i = 0;
901 while (i < srtArr.Length)
902 {
903 freq[index, 0] = tmp;
904
905 while (tmp == srtArr[i])
906 {
907 freq[index, 1]++;
908 i++;
909
910 if (i > srtArr.Length - 1)
911 break;
912 }
913
914 if (i < srtArr.Length)
915 {
916 tmp = srtArr[i];
917 index++;
918 }
919
920 }
921
922 Array.Clear(srtArr, 0, srtArr.Length);
923
924 for (i = 0; i < srtArr.Length; i++)
925 srtArr[i] = freq[i, 1];
926
927 Array.Sort(srtArr);
928
929 if ((srtArr[srtArr.Length - 1]) == 0 || (srtArr[srtArr.Length - 1]) == 1)
930 return 0;
931
932 float freqtest = (float)freq.Length / freq.Rank;
933
934 for (i = 0; i < freqtest; i++)
935 {
936 if (freq[i, 1] == srtArr[index])
937 mode.Add(freq[i, 0]);
938
939 }
940
941 return mode.ToArray()[0];
942 }
943
944 public static int ArrayMode_i(int[] arr)
945 {
946 List<int> mode = new List<int>();
947
948 int[] srtArr = new int[arr.Length];
949 int[,] freq = new int[arr.Length, 2];
950 Array.Copy(arr, srtArr, arr.Length);
951 Array.Sort(srtArr);
952
953 int tmp = srtArr[0];
954 int index = 0;
955 int i = 0;
956 while (i < srtArr.Length)
957 {
958 freq[index, 0] = tmp;
959
960 while (tmp == srtArr[i])
961 {
962 freq[index, 1]++;
963 i++;
964
965 if (i > srtArr.Length - 1)
966 break;
967 }
968
969 if (i < srtArr.Length)
970 {
971 tmp = srtArr[i];
972 index++;
973 }
974
975 }
976
977 Array.Clear(srtArr, 0, srtArr.Length);
978
979 for (i = 0; i < srtArr.Length; i++)
980 srtArr[i] = freq[i, 1];
981
982 Array.Sort(srtArr);
983
984 if ((srtArr[srtArr.Length - 1]) == 0 || (srtArr[srtArr.Length - 1]) == 1)
985 return 0;
986
987 float freqtest = (float)freq.Length / freq.Rank;
988
989 for (i = 0; i < freqtest; i++)
990 {
991 if (freq[i, 1] == srtArr[index])
992 mode.Add(freq[i, 0]);
993
994 }
995
996 return mode.ToArray()[0];
997 }
998
999 #endregion
1000
1001 private static UserSessionData ZeroSession(UserSessionData s)
1002 {
1003 s.session_id = UUID.Zero;
1004 s.agent_id = UUID.Zero;
1005 s.region_id = UUID.Zero;
1006 s.last_updated = Util.UnixTimeSinceEpoch();
1007 s.remote_ip = "";
1008 s.name_f = "";
1009 s.name_l = "";
1010 s.avg_agents_in_view = 0;
1011 s.min_agents_in_view = 0;
1012 s.max_agents_in_view = 0;
1013 s.mode_agents_in_view = 0;
1014 s.avg_fps = 0;
1015 s.min_fps = 0;
1016 s.max_fps = 0;
1017 s.mode_fps = 0;
1018 s.a_language = "";
1019 s.mem_use = 0;
1020 s.meters_traveled = 0;
1021 s.avg_ping = 0;
1022 s.min_ping = 0;
1023 s.max_ping = 0;
1024 s.mode_ping = 0;
1025 s.regions_visited = 0;
1026 s.run_time = 0;
1027 s.avg_sim_fps = 0;
1028 s.min_sim_fps = 0;
1029 s.max_sim_fps = 0;
1030 s.mode_sim_fps = 0;
1031 s.start_time = 0;
1032 s.client_version = "";
1033 s.s_cpu = "";
1034 s.s_gpu = "";
1035 s.s_os = "";
1036 s.s_ram = 0;
1037 s.d_object_kb = 0;
1038 s.d_texture_kb = 0;
1039 s.d_world_kb = 0;
1040 s.n_in_kb = 0;
1041 s.n_in_pk = 0;
1042 s.n_out_kb = 0;
1043 s.n_out_pk = 0;
1044 s.f_dropped = 0;
1045 s.f_failed_resends = 0;
1046 s.f_invalid = 0;
1047 s.f_off_circuit = 0;
1048 s.f_resent = 0;
1049 s.f_send_packet = 0;
1050 s._ping = new List<float>();
1051 s._fps = new List<float>();
1052 s._sim_fps = new List<float>();
1053 s._agents_in_view = new List<int>();
1054 return s;
1055 }
1056 }
1057 #region structs
1058
1059 public class UserSession
1060 {
1061 public UUID session_id;
1062 public UUID region_id;
1063 public string name_f;
1064 public string name_l;
1065 public UserSessionData session_data;
1066 }
1067
1068 public struct UserSessionData
1069 {
1070 public UUID session_id;
1071 public UUID agent_id;
1072 public UUID region_id;
1073 public float last_updated;
1074 public string remote_ip;
1075 public string name_f;
1076 public string name_l;
1077 public float avg_agents_in_view;
1078 public float min_agents_in_view;
1079 public float max_agents_in_view;
1080 public float mode_agents_in_view;
1081 public float avg_fps;
1082 public float min_fps;
1083 public float max_fps;
1084 public float mode_fps;
1085 public string a_language;
1086 public float mem_use;
1087 public float meters_traveled;
1088 public float avg_ping;
1089 public float min_ping;
1090 public float max_ping;
1091 public float mode_ping;
1092 public int regions_visited;
1093 public float run_time;
1094 public float avg_sim_fps;
1095 public float min_sim_fps;
1096 public float max_sim_fps;
1097 public float mode_sim_fps;
1098 public float start_time;
1099 public string client_version;
1100 public string s_cpu;
1101 public string s_gpu;
1102 public string s_os;
1103 public int s_ram;
1104 public float d_object_kb;
1105 public float d_texture_kb;
1106 public float d_world_kb;
1107 public float n_in_kb;
1108 public int n_in_pk;
1109 public float n_out_kb;
1110 public int n_out_pk;
1111 public int f_dropped;
1112 public int f_failed_resends;
1113 public int f_invalid;
1114 public int f_off_circuit;
1115 public int f_resent;
1116 public int f_send_packet;
1117 public List<float> _ping;
1118 public List<float> _fps;
1119 public List<float> _sim_fps;
1120 public List<int> _agents_in_view;
1121 }
1122
1123 #endregion
1124
1125 public class USimStatsData
1126 {
1127 private UUID m_regionID = UUID.Zero;
1128 private volatile int m_statcounter = 0;
1129 private volatile float m_timeDilation;
1130 private volatile float m_simFps;
1131 private volatile float m_physicsFps;
1132 private volatile float m_agentUpdates;
1133 private volatile float m_rootAgents;
1134 private volatile float m_childAgents;
1135 private volatile float m_totalPrims;
1136 private volatile float m_activePrims;
1137 private volatile float m_totalFrameTime;
1138 private volatile float m_netFrameTime;
1139 private volatile float m_physicsFrameTime;
1140 private volatile float m_otherFrameTime;
1141 private volatile float m_imageFrameTime;
1142 private volatile float m_inPacketsPerSecond;
1143 private volatile float m_outPacketsPerSecond;
1144 private volatile float m_unackedBytes;
1145 private volatile float m_agentFrameTime;
1146 private volatile float m_pendingDownloads;
1147 private volatile float m_pendingUploads;
1148 private volatile float m_activeScripts;
1149 private volatile float m_scriptLinesPerSecond;
1150
1151 public UUID RegionId { get { return m_regionID; } }
1152 public int StatsCounter { get { return m_statcounter; } set { m_statcounter = value;}}
1153 public float TimeDilation { get { return m_timeDilation; } }
1154 public float SimFps { get { return m_simFps; } }
1155 public float PhysicsFps { get { return m_physicsFps; } }
1156 public float AgentUpdates { get { return m_agentUpdates; } }
1157 public float RootAgents { get { return m_rootAgents; } }
1158 public float ChildAgents { get { return m_childAgents; } }
1159 public float TotalPrims { get { return m_totalPrims; } }
1160 public float ActivePrims { get { return m_activePrims; } }
1161 public float TotalFrameTime { get { return m_totalFrameTime; } }
1162 public float NetFrameTime { get { return m_netFrameTime; } }
1163 public float PhysicsFrameTime { get { return m_physicsFrameTime; } }
1164 public float OtherFrameTime { get { return m_otherFrameTime; } }
1165 public float ImageFrameTime { get { return m_imageFrameTime; } }
1166 public float InPacketsPerSecond { get { return m_inPacketsPerSecond; } }
1167 public float OutPacketsPerSecond { get { return m_outPacketsPerSecond; } }
1168 public float UnackedBytes { get { return m_unackedBytes; } }
1169 public float AgentFrameTime { get { return m_agentFrameTime; } }
1170 public float PendingDownloads { get { return m_pendingDownloads; } }
1171 public float PendingUploads { get { return m_pendingUploads; } }
1172 public float ActiveScripts { get { return m_activeScripts; } }
1173 public float ScriptLinesPerSecond { get { return m_scriptLinesPerSecond; } }
1174
1175 public USimStatsData(UUID pRegionID)
1176 {
1177 m_regionID = pRegionID;
1178 }
1179
1180 public void ConsumeSimStats(SimStats stats)
1181 {
1182 m_regionID = stats.RegionUUID;
1183 m_timeDilation = stats.StatsBlock[0].StatValue;
1184 m_simFps = stats.StatsBlock[1].StatValue;
1185 m_physicsFps = stats.StatsBlock[2].StatValue;
1186 m_agentUpdates = stats.StatsBlock[3].StatValue;
1187 m_rootAgents = stats.StatsBlock[4].StatValue;
1188 m_childAgents = stats.StatsBlock[5].StatValue;
1189 m_totalPrims = stats.StatsBlock[6].StatValue;
1190 m_activePrims = stats.StatsBlock[7].StatValue;
1191 m_totalFrameTime = stats.StatsBlock[8].StatValue;
1192 m_netFrameTime = stats.StatsBlock[9].StatValue;
1193 m_physicsFrameTime = stats.StatsBlock[10].StatValue;
1194 m_otherFrameTime = stats.StatsBlock[11].StatValue;
1195 m_imageFrameTime = stats.StatsBlock[12].StatValue;
1196 m_inPacketsPerSecond = stats.StatsBlock[13].StatValue;
1197 m_outPacketsPerSecond = stats.StatsBlock[14].StatValue;
1198 m_unackedBytes = stats.StatsBlock[15].StatValue;
1199 m_agentFrameTime = stats.StatsBlock[16].StatValue;
1200 m_pendingDownloads = stats.StatsBlock[17].StatValue;
1201 m_pendingUploads = stats.StatsBlock[18].StatValue;
1202 m_activeScripts = stats.StatsBlock[19].StatValue;
1203 m_scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue;
1204 }
1205 }
1206} \ No newline at end of file