aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/UserStatistics/WebStatsModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/UserStatistics/WebStatsModule.cs')
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs1083
1 files changed, 1083 insertions, 0 deletions
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
new file mode 100644
index 0000000..4eb8cb7
--- /dev/null
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -0,0 +1,1083 @@
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Net; // to be used for REST-->Grid shortly
5using System.Reflection;
6using log4net;
7using Nini.Config;
8using OpenMetaverse;
9using OpenMetaverse.StructuredData;
10using OpenSim.Framework;
11using OpenSim.Framework.Servers;
12using OpenSim.Region.Environment.Interfaces;
13using OpenSim.Region.Environment.Scenes;
14using Mono.Data.SqliteClient;
15
16
17using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
18
19using OSD = OpenMetaverse.StructuredData.OSD;
20using OSDMap = OpenMetaverse.StructuredData.OSDMap;
21
22namespace OpenSim.Region.UserStatistics
23{
24 public class WebStatsModule : IRegionModule
25 {
26 private static readonly ILog m_log =
27 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
28 private static SqliteConnection dbConn;
29 private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>();
30 private List<Scene> m_scene = new List<Scene>();
31 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
32 private Dictionary<UUID, USimStatsData> m_simstatsCounters = new Dictionary<UUID, USimStatsData>();
33 private const int updateStatsMod = 6;
34 private volatile int concurrencyCounter = 0;
35 private bool enabled = false;
36
37
38 public virtual void Initialise(Scene scene, IConfigSource config)
39 {
40 IConfig cnfg;
41 try
42 {
43 cnfg = config.Configs["WebStats"];
44 enabled = cnfg.GetBoolean("enabled", false);
45
46 }
47 catch (Exception)
48 {
49 enabled = false;
50 }
51 if (!enabled)
52 {
53 return;
54 }
55
56 lock (m_scene)
57 {
58 if (m_scene.Count == 0)
59 {
60 IConfig startupConfig = config.Configs["Startup"];
61
62 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3");
63 dbConn.Open();
64 CheckAndUpdateDatabase(dbConn);
65
66 Default_Report rep = new Default_Report();
67 Prototype_distributor protodep = new Prototype_distributor();
68 Updater_distributor updatedep = new Updater_distributor();
69 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX();
70 SimStatsAJAX ajSimStats = new SimStatsAJAX();
71 reports.Add("", rep);
72 reports.Add("index.aspx", rep);
73 reports.Add("prototype.js", protodep);
74 reports.Add("updater.js", updatedep);
75 reports.Add("activeconnectionsajax.ajax", ajConnections);
76 reports.Add("simstatsajax.ajax", ajSimStats);
77
78 scene.CommsManager.HttpServer.AddHTTPHandler("/SStats/", HandleStatsRequest);
79
80
81 }
82 m_scene.Add(scene);
83 m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID));
84 scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket;
85 }
86
87 }
88
89 public void ReceiveClassicSimStatsPacket(SimStats stats)
90 {
91 if (!enabled)
92 {
93 return;
94 }
95
96 try
97 {
98
99 if (concurrencyCounter > 0)
100 return;
101
102 USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
103
104 if ((++ss.StatsCounter % updateStatsMod) == 0)
105 {
106 ss.ConsumeSimStats(stats);
107 }
108 }
109 catch (KeyNotFoundException)
110 {
111
112 }
113 }
114
115 public Hashtable HandleStatsRequest(Hashtable request)
116 {
117 Hashtable responsedata = new Hashtable();
118 string regpath = request["uri"].ToString();
119 int response_code = 404;
120 string contenttype = "text/html";
121
122 string strOut = string.Empty;
123
124 regpath = regpath.Remove(0, 8);
125 if (reports.ContainsKey(regpath))
126 {
127 IStatsController rep = reports[regpath];
128 Hashtable repParams = new Hashtable();
129
130 repParams["DatabaseConnection"] = dbConn;
131 repParams["Scenes"] = m_scene;
132 repParams["SimStats"] = m_simstatsCounters;
133
134 concurrencyCounter++;
135
136 strOut = rep.RenderView(rep.ProcessModel(repParams));
137
138 if (regpath.EndsWith("js"))
139 {
140 contenttype = "text/javascript";
141 }
142
143 concurrencyCounter--;
144
145 response_code = 200;
146
147 }
148 else
149 {
150 strOut = m_scene[0].CommsManager.HttpServer.GetHTTP404("");
151 }
152
153
154 responsedata["int_response_code"] = response_code;
155 responsedata["content_type"] = contenttype;
156 responsedata["keepalive"] = false;
157 responsedata["str_response_string"] = strOut;
158
159 return responsedata;
160 }
161
162
163
164 public void CheckAndUpdateDatabase(SqliteConnection db)
165 {
166 lock (db)
167 {
168 // TODO: FIXME: implement stats migrations
169 const string SQL = @"SELECT * FROM migrations LIMIT 1";
170
171 SqliteCommand cmd = new SqliteCommand(SQL, db);
172
173 try
174 {
175 cmd.ExecuteNonQuery();
176 }
177 catch (SqliteSyntaxException)
178 {
179 CreateTables(db);
180 }
181 }
182
183 }
184
185 public void CreateTables(SqliteConnection db)
186 {
187 SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db);
188 createcmd.ExecuteNonQuery();
189
190 createcmd.CommandText = SQL_MIGRA_TABLE_CREATE;
191 createcmd.ExecuteNonQuery();
192 }
193
194
195
196 public virtual void PostInitialise()
197 {
198 if (!enabled)
199 {
200 return;
201 }
202 AddHandlers();
203 }
204
205 public virtual void Close()
206 {
207 if (!enabled)
208 {
209 return;
210 }
211 dbConn.Close();
212 dbConn.Dispose();
213 }
214
215 public virtual string Name
216 {
217 get { return "ViewerStatsModule"; }
218 }
219
220 public bool IsSharedModule
221 {
222 get { return true; }
223 }
224
225 public void OnRegisterCaps(UUID agentID, Caps caps)
226 {
227 m_log.DebugFormat("[VC]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
228 string capsPath = "/CAPS/VS/" + UUID.Random();
229 caps.RegisterHandler("ViewerStats",
230 new RestStreamHandler("POST", capsPath,
231 delegate(string request, string path, string param,
232 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
233 {
234 return ViewerStatsReport(request, path, param,
235 agentID, caps);
236 }));
237 }
238
239 public void OnDeRegisterCaps(UUID agentID, Caps caps)
240 {
241
242 }
243
244 protected virtual void AddHandlers()
245 {
246 lock (m_scene)
247 {
248 foreach (Scene scene in m_scene)
249 {
250 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
251 scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps;
252 scene.EventManager.OnClientClosed += OnClientClosed;
253 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
254 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
255 }
256 }
257 }
258
259 public void OnMakeRootAgent(ScenePresence agent)
260 {
261 UUID regionUUID = GetRegionUUIDFromHandle(agent.RegionHandle);
262
263 lock (m_sessions)
264 {
265 if (!m_sessions.ContainsKey(agent.UUID))
266 {
267 UserSessionData usd = UserSessionUtil.newUserSessionData();
268
269 UserSessionID uid = new UserSessionID();
270 uid.name_f = agent.Firstname;
271 uid.name_l = agent.Lastname;
272 uid.region_id = regionUUID;
273 uid.session_id = agent.ControllingClient.SessionId;
274 uid.session_data = usd;
275
276 m_sessions.Add(agent.UUID, uid);
277 }
278 else
279 {
280 UserSessionID uid = m_sessions[agent.UUID];
281 uid.region_id = regionUUID;
282 uid.session_id = agent.ControllingClient.SessionId;
283 m_sessions[agent.UUID] = uid;
284 }
285 }
286 }
287
288
289
290
291 public void OnMakeChildAgent(ScenePresence agent)
292 {
293 lock (m_sessions)
294 {
295 if (m_sessions.ContainsKey(agent.UUID))
296 {
297 if (m_sessions[agent.UUID].region_id == GetRegionUUIDFromHandle(agent.RegionHandle))
298 {
299 m_sessions.Remove(agent.UUID);
300 }
301 }
302 }
303 }
304
305
306 public void OnClientClosed(UUID agentID)
307 {
308 lock (m_sessions)
309 {
310 if (m_sessions.ContainsKey(agentID))
311 {
312 m_sessions.Remove(agentID);
313 }
314 }
315
316 }
317
318 public UUID GetRegionUUIDFromHandle(ulong regionhandle)
319 {
320 lock (m_scene)
321 {
322 foreach (Scene scene in m_scene)
323 {
324 if (scene.RegionInfo.RegionHandle == regionhandle)
325 return scene.RegionInfo.RegionID;
326 }
327 }
328 return UUID.Zero;
329 }
330 /// <summary>
331 /// Callback for a viewerstats cap
332 /// </summary>
333 /// <param name="request"></param>
334 /// <param name="path"></param>
335 /// <param name="param"></param>
336 /// <param name="agentID"></param>
337 /// <param name="caps"></param>
338 /// <returns></returns>
339 public string ViewerStatsReport(string request, string path, string param,
340 UUID agentID, Caps caps)
341 {
342 m_log.Debug(request);
343 UserSessionID uid;
344 UserSessionData usd;
345
346 lock (m_sessions)
347 {
348 if (!m_sessions.ContainsKey(agentID))
349 {
350 m_log.Warn("[VS]: no session for stat disclosure");
351 return string.Empty;
352 }
353 uid = m_sessions[agentID];
354 }
355
356 usd = uid.session_data;
357
358 OSD message = OSDParser.DeserializeLLSDXml(request);
359 if (message.Type != OSDType.Map)
360 return String.Empty;
361
362 OSDMap mmap = (OSDMap) message;
363 {
364 if (mmap["agent"].Type != OSDType.Map)
365 return String.Empty;
366 OSDMap agent_map = (OSDMap) mmap["agent"];
367 usd.agent_id = agentID;
368 usd.name_f = uid.name_f;
369 usd.name_l = uid.name_l;
370 usd.region_id = uid.region_id;
371 usd.a_language = agent_map["language"].AsString();
372 usd.mem_use = (float) agent_map["mem_use"].AsReal();
373 usd.meters_traveled = (float) agent_map["meters_traveled"].AsReal();
374 usd.regions_visited = agent_map["regions_visited"].AsInteger();
375 usd.run_time = (float) agent_map["run_time"].AsReal();
376 usd.start_time = (float) agent_map["start_time"].AsReal();
377 usd.client_version = agent_map["version"].AsString();
378
379 UserSessionUtil.UpdateMultiItems(ref usd, agent_map["agents_in_view"].AsInteger(),
380 (float) agent_map["ping"].AsReal(),
381 (float) agent_map["sim_fps"].AsReal(),
382 (float) agent_map["fps"].AsReal());
383
384 if (mmap["downloads"].Type != OSDType.Map)
385 return String.Empty;
386 OSDMap downloads_map = (OSDMap) mmap["downloads"];
387 usd.d_object_kb = (float) downloads_map["object_kbytes"].AsReal();
388 usd.d_texture_kb = (float) downloads_map["texture_kbytes"].AsReal();
389 usd.d_world_kb = (float) downloads_map["workd_kbytes"].AsReal();
390
391
392 usd.session_id = mmap["session_id"].AsUUID();
393
394 if (mmap["system"].Type != OSDType.Map)
395 return String.Empty;
396 OSDMap system_map = (OSDMap) mmap["system"];
397
398 usd.s_cpu = system_map["cpu"].AsString();
399 usd.s_gpu = system_map["gpu"].AsString();
400 usd.s_os = system_map["os"].AsString();
401 usd.s_ram = system_map["ram"].AsInteger();
402
403 if (mmap["stats"].Type != OSDType.Map)
404 return String.Empty;
405
406 OSDMap stats_map = (OSDMap) mmap["stats"];
407 {
408 if (mmap["failures"].Type != OSDType.Map)
409 return String.Empty;
410 OSDMap stats_failures = (OSDMap) stats_map["failures"];
411 usd.f_dropped = stats_failures["dropped"].AsInteger();
412 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
413 usd.f_invalid = stats_failures["invalid"].AsInteger();
414 usd.f_resent = stats_failures["resent"].AsInteger();
415 usd.f_send_packet = stats_failures["send_packet"].AsInteger();
416
417 if (mmap["net"].Type != OSDType.Map)
418 return String.Empty;
419 OSDMap stats_net = (OSDMap) stats_map["net"];
420 {
421 if (mmap["in"].Type != OSDType.Map)
422 return String.Empty;
423
424 OSDMap net_in = (OSDMap) stats_net["in"];
425 usd.n_in_kb = (float) net_in["kbytes"].AsReal();
426 usd.n_in_pk = net_in["packets"].AsInteger();
427
428 if (mmap["out"].Type != OSDType.Map)
429 return String.Empty;
430 OSDMap net_out = (OSDMap) stats_net["out"];
431
432 usd.n_out_kb = (float) net_out["kbytes"].AsReal();
433 usd.n_out_pk = net_out["packets"].AsInteger();
434 }
435
436
437 }
438 }
439
440 uid.session_data = usd;
441 m_sessions[agentID] = uid;
442 UpdateUserStats(uid, dbConn);
443
444 return String.Empty;
445 }
446
447 public void UpdateUserStats(UserSessionID uid, SqliteConnection db)
448 {
449 lock (db)
450 {
451 SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_UPDATE, db);
452 updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString()));
453 updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString()));
454 updatecmd.Parameters.Add(new SqliteParameter(":region_id", uid.session_data.region_id.ToString()));
455 updatecmd.Parameters.Add(new SqliteParameter(":last_updated", (int) uid.session_data.last_updated));
456 updatecmd.Parameters.Add(new SqliteParameter(":remote_ip", uid.session_data.remote_ip));
457 updatecmd.Parameters.Add(new SqliteParameter(":name_f", uid.session_data.name_f));
458 updatecmd.Parameters.Add(new SqliteParameter(":name_l", uid.session_data.name_l));
459 updatecmd.Parameters.Add(new SqliteParameter(":avg_agents_in_view", uid.session_data.avg_agents_in_view));
460 updatecmd.Parameters.Add(new SqliteParameter(":min_agents_in_view",
461 (int) uid.session_data.min_agents_in_view));
462 updatecmd.Parameters.Add(new SqliteParameter(":max_agents_in_view",
463 (int) uid.session_data.max_agents_in_view));
464 updatecmd.Parameters.Add(new SqliteParameter(":mode_agents_in_view",
465 (int) uid.session_data.mode_agents_in_view));
466 updatecmd.Parameters.Add(new SqliteParameter(":avg_fps", uid.session_data.avg_fps));
467 updatecmd.Parameters.Add(new SqliteParameter(":min_fps", uid.session_data.min_fps));
468 updatecmd.Parameters.Add(new SqliteParameter(":max_fps", uid.session_data.max_fps));
469 updatecmd.Parameters.Add(new SqliteParameter(":mode_fps", uid.session_data.mode_fps));
470 updatecmd.Parameters.Add(new SqliteParameter(":a_language", uid.session_data.a_language));
471 updatecmd.Parameters.Add(new SqliteParameter(":mem_use", uid.session_data.mem_use));
472 updatecmd.Parameters.Add(new SqliteParameter(":meters_traveled", uid.session_data.meters_traveled));
473 updatecmd.Parameters.Add(new SqliteParameter(":avg_ping", uid.session_data.avg_ping));
474 updatecmd.Parameters.Add(new SqliteParameter(":min_ping", uid.session_data.min_ping));
475 updatecmd.Parameters.Add(new SqliteParameter(":max_ping", uid.session_data.max_ping));
476 updatecmd.Parameters.Add(new SqliteParameter(":mode_ping", uid.session_data.mode_ping));
477 updatecmd.Parameters.Add(new SqliteParameter(":regions_visited", uid.session_data.regions_visited));
478 updatecmd.Parameters.Add(new SqliteParameter(":run_time", uid.session_data.run_time));
479 updatecmd.Parameters.Add(new SqliteParameter(":avg_sim_fps", uid.session_data.avg_sim_fps));
480 updatecmd.Parameters.Add(new SqliteParameter(":min_sim_fps", uid.session_data.min_sim_fps));
481 updatecmd.Parameters.Add(new SqliteParameter(":max_sim_fps", uid.session_data.max_sim_fps));
482 updatecmd.Parameters.Add(new SqliteParameter(":mode_sim_fps", uid.session_data.mode_sim_fps));
483 updatecmd.Parameters.Add(new SqliteParameter(":start_time", uid.session_data.start_time));
484 updatecmd.Parameters.Add(new SqliteParameter(":client_version", uid.session_data.client_version));
485 updatecmd.Parameters.Add(new SqliteParameter(":s_cpu", uid.session_data.s_cpu));
486 updatecmd.Parameters.Add(new SqliteParameter(":s_gpu", uid.session_data.s_gpu));
487 updatecmd.Parameters.Add(new SqliteParameter(":s_os", uid.session_data.s_os));
488 updatecmd.Parameters.Add(new SqliteParameter(":s_ram", uid.session_data.s_ram));
489 updatecmd.Parameters.Add(new SqliteParameter(":d_object_kb", uid.session_data.d_object_kb));
490 updatecmd.Parameters.Add(new SqliteParameter(":d_texture_kb", uid.session_data.d_texture_kb));
491 updatecmd.Parameters.Add(new SqliteParameter(":d_world_kb", uid.session_data.d_world_kb));
492 updatecmd.Parameters.Add(new SqliteParameter(":n_in_kb", uid.session_data.n_in_kb));
493 updatecmd.Parameters.Add(new SqliteParameter(":n_in_pk", uid.session_data.n_in_pk));
494 updatecmd.Parameters.Add(new SqliteParameter(":n_out_kb", uid.session_data.n_out_kb));
495 updatecmd.Parameters.Add(new SqliteParameter(":n_out_pk", uid.session_data.n_out_pk));
496 updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped));
497 updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends));
498 updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid));
499
500 updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit));
501 updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent));
502 updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet));
503
504 updatecmd.Parameters.Add(new SqliteParameter(":session_key", uid.session_data.session_id.ToString()));
505 updatecmd.Parameters.Add(new SqliteParameter(":agent_key", uid.session_data.agent_id.ToString()));
506 updatecmd.Parameters.Add(new SqliteParameter(":region_key", uid.session_data.region_id.ToString()));
507 m_log.Debug("UPDATE");
508
509 int result = updatecmd.ExecuteNonQuery();
510
511 if (result == 0)
512 {
513 m_log.Debug("INSERT");
514 updatecmd.CommandText = SQL_STATS_TABLE_INSERT;
515 updatecmd.ExecuteNonQuery();
516 }
517 }
518
519 }
520
521 #region SQL
522 private const string SQL_MIGRA_TABLE_CREATE = @"create table migrations(name varchar(100), version int)";
523
524 private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE stats_session_data (
525 session_id VARCHAR(36) NOT NULL PRIMARY KEY,
526 agent_id VARCHAR(36) NOT NULL DEFAULT '',
527 region_id VARCHAR(36) NOT NULL DEFAULT '',
528 last_updated INT NOT NULL DEFAULT '0',
529 remote_ip VARCHAR(16) NOT NULL DEFAULT '',
530 name_f VARCHAR(50) NOT NULL DEFAULT '',
531 name_l VARCHAR(50) NOT NULL DEFAULT '',
532 avg_agents_in_view FLOAT NOT NULL DEFAULT '0',
533 min_agents_in_view INT NOT NULL DEFAULT '0',
534 max_agents_in_view INT NOT NULL DEFAULT '0',
535 mode_agents_in_view INT NOT NULL DEFAULT '0',
536 avg_fps FLOAT NOT NULL DEFAULT '0',
537 min_fps FLOAT NOT NULL DEFAULT '0',
538 max_fps FLOAT NOT NULL DEFAULT '0',
539 mode_fps FLOAT NOT NULL DEFAULT '0',
540 a_language VARCHAR(25) NOT NULL DEFAULT '',
541 mem_use FLOAT NOT NULL DEFAULT '0',
542 meters_traveled FLOAT NOT NULL DEFAULT '0',
543 avg_ping FLOAT NOT NULL DEFAULT '0',
544 min_ping FLOAT NOT NULL DEFAULT '0',
545 max_ping FLOAT NOT NULL DEFAULT '0',
546 mode_ping FLOAT NOT NULL DEFAULT '0',
547 regions_visited INT NOT NULL DEFAULT '0',
548 run_time FLOAT NOT NULL DEFAULT '0',
549 avg_sim_fps FLOAT NOT NULL DEFAULT '0',
550 min_sim_fps FLOAT NOT NULL DEFAULT '0',
551 max_sim_fps FLOAT NOT NULL DEFAULT '0',
552 mode_sim_fps FLOAT NOT NULL DEFAULT '0',
553 start_time FLOAT NOT NULL DEFAULT '0',
554 client_version VARCHAR(255) NOT NULL DEFAULT '',
555 s_cpu VARCHAR(255) NOT NULL DEFAULT '',
556 s_gpu VARCHAR(255) NOT NULL DEFAULT '',
557 s_os VARCHAR(2255) NOT NULL DEFAULT '',
558 s_ram INT NOT NULL DEFAULT '0',
559 d_object_kb FLOAT NOT NULL DEFAULT '0',
560 d_texture_kb FLOAT NOT NULL DEFAULT '0',
561 d_world_kb FLOAT NOT NULL DEFAULT '0',
562 n_in_kb FLOAT NOT NULL DEFAULT '0',
563 n_in_pk INT NOT NULL DEFAULT '0',
564 n_out_kb FLOAT NOT NULL DEFAULT '0',
565 n_out_pk INT NOT NULL DEFAULT '0',
566 f_dropped INT NOT NULL DEFAULT '0',
567 f_failed_resends INT NOT NULL DEFAULT '0',
568 f_invalid INT NOT NULL DEFAULT '0',
569 f_off_circuit INT NOT NULL DEFAULT '0',
570 f_resent INT NOT NULL DEFAULT '0',
571 f_send_packet INT NOT NULL DEFAULT '0'
572 );";
573
574 private const string SQL_STATS_TABLE_INSERT = @"INSERT INTO stats_session_data (
575session_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,
576mode_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,
577regions_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,
578d_object_kb, d_texture_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_invalid, f_off_circuit,
579f_resent, f_send_packet
580)
581VALUES
582(
583: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,
584: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,
585: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,
586:d_object_kb, :d_texture_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_invalid, :f_off_circuit,
587:f_resent, :f_send_packet
588)
589";
590
591 private const string SQL_STATS_TABLE_UPDATE = @"
592UPDATE stats_session_data
593set session_id=:session_id,
594 agent_id=:agent_id,
595 region_id=:region_id,
596 last_updated=:last_updated,
597 remote_ip=:remote_ip,
598 name_f=:name_f,
599 name_l=:name_l,
600 avg_agents_in_view=:avg_agents_in_view,
601 min_agents_in_view=:min_agents_in_view,
602 max_agents_in_view=:max_agents_in_view,
603 mode_agents_in_view=:mode_agents_in_view,
604 avg_fps=:avg_fps,
605 min_fps=:min_fps,
606 max_fps=:max_fps,
607 mode_fps=:mode_fps,
608 a_language=:a_language,
609 mem_use=:mem_use,
610 meters_traveled=:meters_traveled,
611 avg_ping=:avg_ping,
612 min_ping=:min_ping,
613 max_ping=:max_ping,
614 mode_ping=:mode_ping,
615 regions_visited=:regions_visited,
616 run_time=:run_time,
617 avg_sim_fps=:avg_sim_fps,
618 min_sim_fps=:min_sim_fps,
619 max_sim_fps=:max_sim_fps,
620 mode_sim_fps=:mode_sim_fps,
621 start_time=:start_time,
622 client_version=:client_version,
623 s_cpu=:s_cpu,
624 s_gpu=:s_gpu,
625 s_os=:s_os,
626 s_ram=:s_ram,
627 d_object_kb=:d_object_kb,
628 d_texture_kb=:d_texture_kb,
629 d_world_kb=:d_world_kb,
630 n_in_kb=:n_in_kb,
631 n_in_pk=:n_in_pk,
632 n_out_kb=:n_out_kb,
633 n_out_pk=:n_out_pk,
634 f_dropped=:f_dropped,
635 f_failed_resends=:f_failed_resends,
636 f_invalid=:f_invalid,
637 f_off_circuit=:f_off_circuit,
638 f_resent=:f_resent,
639 f_send_packet=:f_send_packet
640WHERE session_id=:session_key AND agent_id=:agent_key AND region_id=:region_key";
641 #endregion
642 }
643 public static class UserSessionUtil
644 {
645 public static UserSessionData newUserSessionData()
646 {
647 UserSessionData obj = ZeroSession(new UserSessionData());
648 return obj;
649 }
650
651 public static void UpdateMultiItems(ref UserSessionData s, int agents_in_view, float ping, float sim_fps, float fps)
652 {
653 // don't insert zero values here or it'll skew the statistics.
654 if (agents_in_view == 0 && fps == 0 && sim_fps == 0 && ping == 0)
655 return;
656 s._agents_in_view.Add(agents_in_view);
657 s._fps.Add(fps);
658 s._sim_fps.Add(sim_fps);
659 s._ping.Add(ping);
660
661 int[] __agents_in_view = s._agents_in_view.ToArray();
662
663 s.avg_agents_in_view = ArrayAvg_i(__agents_in_view);
664 s.min_agents_in_view = ArrayMin_i(__agents_in_view);
665 s.max_agents_in_view = ArrayMax_i(__agents_in_view);
666 s.mode_agents_in_view = ArrayMode_i(__agents_in_view);
667
668 float[] __fps = s._fps.ToArray();
669 s.avg_fps = ArrayAvg_f(__fps);
670 s.min_fps = ArrayMin_f(__fps);
671 s.max_fps = ArrayMax_f(__fps);
672 s.mode_fps = ArrayMode_f(__fps);
673
674 float[] __sim_fps = s._sim_fps.ToArray();
675 s.avg_sim_fps = ArrayAvg_f(__sim_fps);
676 s.min_sim_fps = ArrayMin_f(__sim_fps);
677 s.max_sim_fps = ArrayMax_f(__sim_fps);
678 s.mode_sim_fps = ArrayMode_f(__sim_fps);
679
680 float[] __ping = s._ping.ToArray();
681 s.avg_ping = ArrayAvg_f(__ping);
682 s.min_ping = ArrayMin_f(__ping);
683 s.max_ping = ArrayMax_f(__ping);
684 s.mode_ping = ArrayMode_f(__ping);
685
686 }
687
688 #region Statistics
689
690 public static int ArrayMin_i(int[] arr)
691 {
692 int cnt = arr.Length;
693 if (cnt == 0)
694 return 0;
695
696 Array.Sort(arr);
697 return arr[0];
698 }
699
700 public static int ArrayMax_i(int[] arr)
701 {
702 int cnt = arr.Length;
703 if (cnt == 0)
704 return 0;
705
706 Array.Sort(arr);
707 return arr[cnt-1];
708 }
709
710 public static float ArrayMin_f(float[] arr)
711 {
712 int cnt = arr.Length;
713 if (cnt == 0)
714 return 0;
715
716 Array.Sort(arr);
717 return arr[0];
718 }
719
720 public static float ArrayMax_f(float[] arr)
721 {
722 int cnt = arr.Length;
723 if (cnt == 0)
724 return 0;
725
726 Array.Sort(arr);
727 return arr[cnt - 1];
728 }
729
730 public static float ArrayAvg_i(int[] arr)
731 {
732 int cnt = arr.Length;
733
734 if (cnt == 0)
735 return 0;
736
737 float result = arr[0];
738
739 for (int i = 1; i < cnt; i++)
740 result += arr[i];
741
742 return result / cnt;
743 }
744
745 public static float ArrayAvg_f(float[] arr)
746 {
747 int cnt = arr.Length;
748
749 if (cnt == 0)
750 return 0;
751
752 float result = arr[0];
753
754 for (int i = 1; i < cnt; i++)
755 result += arr[i];
756
757 return result / cnt;
758 }
759
760
761 public static float ArrayMode_f(float[] arr)
762 {
763 List<float> mode = new List<float>();
764
765 float[] srtArr = new float[arr.Length];
766 float[,] freq = new float[arr.Length, 2];
767 Array.Copy(arr, srtArr, arr.Length);
768 Array.Sort(srtArr);
769
770 float tmp = srtArr[0];
771 int index = 0;
772 int i = 0;
773 while (i < srtArr.Length)
774 {
775 freq[index, 0] = tmp;
776
777 while (tmp == srtArr[i])
778 {
779 freq[index, 1]++;
780 i++;
781
782 if (i > srtArr.Length - 1)
783 break;
784 }
785
786 if (i < srtArr.Length)
787 {
788 tmp = srtArr[i];
789 index++;
790 }
791
792 }
793
794 Array.Clear(srtArr, 0, srtArr.Length);
795
796 for (i = 0; i < srtArr.Length; i++)
797 srtArr[i] = freq[i, 1];
798
799 Array.Sort(srtArr);
800
801 if ((srtArr[srtArr.Length - 1]) == 0 || (srtArr[srtArr.Length - 1]) == 1)
802 return 0;
803
804 float freqtest = (float)freq.Length / freq.Rank;
805
806 for (i = 0; i < freqtest; i++)
807 {
808 if (freq[i, 1] == srtArr[index])
809 mode.Add(freq[i, 0]);
810
811 }
812
813 return mode.ToArray()[0];
814
815 }
816
817
818 public static int ArrayMode_i(int[] arr)
819 {
820 List<int> mode = new List<int>();
821
822 int[] srtArr = new int[arr.Length];
823 int[,] freq = new int[arr.Length, 2];
824 Array.Copy(arr, srtArr, arr.Length);
825 Array.Sort(srtArr);
826
827 int tmp = srtArr[0];
828 int index = 0;
829 int i = 0;
830 while (i < srtArr.Length)
831 {
832 freq[index, 0] = tmp;
833
834 while (tmp == srtArr[i])
835 {
836 freq[index, 1]++;
837 i++;
838
839 if (i > srtArr.Length - 1)
840 break;
841 }
842
843 if (i < srtArr.Length)
844 {
845 tmp = srtArr[i];
846 index++;
847 }
848
849 }
850
851 Array.Clear(srtArr, 0, srtArr.Length);
852
853 for (i = 0; i < srtArr.Length; i++)
854 srtArr[i] = freq[i, 1];
855
856 Array.Sort(srtArr);
857
858 if ((srtArr[srtArr.Length - 1]) == 0 || (srtArr[srtArr.Length - 1]) == 1)
859 return 0;
860
861 float freqtest = (float)freq.Length / freq.Rank;
862
863 for (i = 0; i < freqtest; i++)
864 {
865 if (freq[i, 1] == srtArr[index])
866 mode.Add(freq[i, 0]);
867
868 }
869
870 return mode.ToArray()[0];
871
872 }
873
874 #endregion
875
876 private static UserSessionData ZeroSession(UserSessionData s)
877 {
878 s.session_id = UUID.Zero;
879 s.agent_id = UUID.Zero;
880 s.region_id = UUID.Zero;
881 s.last_updated = Util.UnixTimeSinceEpoch();
882 s.remote_ip = "";
883 s.name_f = "";
884 s.name_l = "";
885 s.avg_agents_in_view = 0;
886 s.min_agents_in_view = 0;
887 s.max_agents_in_view = 0;
888 s.mode_agents_in_view = 0;
889 s.avg_fps = 0;
890 s.min_fps = 0;
891 s.max_fps = 0;
892 s.mode_fps = 0;
893 s.a_language = "";
894 s.mem_use = 0;
895 s.meters_traveled = 0;
896 s.avg_ping = 0;
897 s.min_ping = 0;
898 s.max_ping = 0;
899 s.mode_ping = 0;
900 s.regions_visited = 0;
901 s.run_time = 0;
902 s.avg_sim_fps = 0;
903 s.min_sim_fps = 0;
904 s.max_sim_fps = 0;
905 s.mode_sim_fps = 0;
906 s.start_time = 0;
907 s.client_version = "";
908 s.s_cpu = "";
909 s.s_gpu = "";
910 s.s_os = "";
911 s.s_ram = 0;
912 s.d_object_kb = 0;
913 s.d_texture_kb = 0;
914 s.d_world_kb = 0;
915 s.n_in_kb = 0;
916 s.n_in_pk = 0;
917 s.n_out_kb = 0;
918 s.n_out_pk = 0;
919 s.f_dropped = 0;
920 s.f_failed_resends = 0;
921 s.f_invalid = 0;
922 s.f_off_circuit = 0;
923 s.f_resent = 0;
924 s.f_send_packet = 0;
925 s._ping = new List<float>();
926 s._fps = new List<float>();
927 s._sim_fps = new List<float>();
928 s._agents_in_view = new List<int>();
929 return s;
930 }
931 }
932 #region structs
933
934 public struct UserSessionID
935 {
936 public UUID session_id;
937 public UUID region_id;
938 public string name_f;
939 public string name_l;
940 public UserSessionData session_data;
941 }
942
943 public struct UserSessionData
944 {
945 public UUID session_id;
946 public UUID agent_id;
947 public UUID region_id;
948 public float last_updated;
949 public string remote_ip;
950 public string name_f;
951 public string name_l;
952 public float avg_agents_in_view;
953 public float min_agents_in_view;
954 public float max_agents_in_view;
955 public float mode_agents_in_view;
956 public float avg_fps;
957 public float min_fps;
958 public float max_fps;
959 public float mode_fps;
960 public string a_language;
961 public float mem_use;
962 public float meters_traveled;
963 public float avg_ping;
964 public float min_ping;
965 public float max_ping;
966 public float mode_ping;
967 public int regions_visited;
968 public float run_time;
969 public float avg_sim_fps;
970 public float min_sim_fps;
971 public float max_sim_fps;
972 public float mode_sim_fps;
973 public float start_time;
974 public string client_version;
975 public string s_cpu;
976 public string s_gpu;
977 public string s_os;
978 public int s_ram;
979 public float d_object_kb;
980 public float d_texture_kb;
981 public float d_world_kb;
982 public float n_in_kb;
983 public int n_in_pk;
984 public float n_out_kb;
985 public int n_out_pk;
986 public int f_dropped;
987 public int f_failed_resends;
988 public int f_invalid;
989 public int f_off_circuit;
990 public int f_resent;
991 public int f_send_packet;
992 public List<float> _ping;
993 public List<float> _fps;
994 public List<float> _sim_fps;
995 public List<int> _agents_in_view;
996 }
997
998
999 #endregion
1000
1001 public class USimStatsData
1002 {
1003 private UUID m_regionID = UUID.Zero;
1004 private volatile int m_statcounter = 0;
1005 private volatile float m_timeDilation;
1006 private volatile float m_simFps;
1007 private volatile float m_physicsFps;
1008 private volatile float m_agentUpdates;
1009 private volatile float m_rootAgents;
1010 private volatile float m_childAgents;
1011 private volatile float m_totalPrims;
1012 private volatile float m_activePrims;
1013 private volatile float m_totalFrameTime;
1014 private volatile float m_netFrameTime;
1015 private volatile float m_physicsFrameTime;
1016 private volatile float m_otherFrameTime;
1017 private volatile float m_imageFrameTime;
1018 private volatile float m_inPacketsPerSecond;
1019 private volatile float m_outPacketsPerSecond;
1020 private volatile float m_unackedBytes;
1021 private volatile float m_agentFrameTime;
1022 private volatile float m_pendingDownloads;
1023 private volatile float m_pendingUploads;
1024 private volatile float m_activeScripts;
1025 private volatile float m_scriptLinesPerSecond;
1026
1027 public UUID RegionId { get { return m_regionID; } }
1028 public int StatsCounter { get { return m_statcounter; } set { m_statcounter = value;}}
1029 public float TimeDilation { get { return m_timeDilation; } }
1030 public float SimFps { get { return m_simFps; } }
1031 public float PhysicsFps { get { return m_physicsFps; } }
1032 public float AgentUpdates { get { return m_agentUpdates; } }
1033 public float RootAgents { get { return m_rootAgents; } }
1034 public float ChildAgents { get { return m_childAgents; } }
1035 public float TotalPrims { get { return m_totalPrims; } }
1036 public float ActivePrims { get { return m_activePrims; } }
1037 public float TotalFrameTime { get { return m_totalFrameTime; } }
1038 public float NetFrameTime { get { return m_netFrameTime; } }
1039 public float PhysicsFrameTime { get { return m_physicsFrameTime; } }
1040 public float OtherFrameTime { get { return m_otherFrameTime; } }
1041 public float ImageFrameTime { get { return m_imageFrameTime; } }
1042 public float InPacketsPerSecond { get { return m_inPacketsPerSecond; } }
1043 public float OutPacketsPerSecond { get { return m_outPacketsPerSecond; } }
1044 public float UnackedBytes { get { return m_unackedBytes; } }
1045 public float AgentFrameTime { get { return m_agentFrameTime; } }
1046 public float PendingDownloads { get { return m_pendingDownloads; } }
1047 public float PendingUploads { get { return m_pendingUploads; } }
1048 public float ActiveScripts { get { return m_activeScripts; } }
1049 public float ScriptLinesPerSecond { get { return m_scriptLinesPerSecond; } }
1050
1051 public USimStatsData(UUID pRegionID)
1052 {
1053 m_regionID = pRegionID;
1054 }
1055
1056 public void ConsumeSimStats(SimStats stats)
1057 {
1058 m_regionID = stats.RegionUUID;
1059 m_timeDilation = stats.StatsBlock[0].StatValue;
1060 m_simFps = stats.StatsBlock[1].StatValue;
1061 m_physicsFps = stats.StatsBlock[2].StatValue;
1062 m_agentUpdates = stats.StatsBlock[3].StatValue;
1063 m_rootAgents = stats.StatsBlock[4].StatValue;
1064 m_childAgents = stats.StatsBlock[5].StatValue;
1065 m_totalPrims = stats.StatsBlock[6].StatValue;
1066 m_activePrims = stats.StatsBlock[7].StatValue;
1067 m_totalFrameTime = stats.StatsBlock[8].StatValue;
1068 m_netFrameTime = stats.StatsBlock[9].StatValue;
1069 m_physicsFrameTime = stats.StatsBlock[10].StatValue;
1070 m_otherFrameTime = stats.StatsBlock[11].StatValue;
1071 m_imageFrameTime = stats.StatsBlock[12].StatValue;
1072 m_inPacketsPerSecond = stats.StatsBlock[13].StatValue;
1073 m_outPacketsPerSecond = stats.StatsBlock[14].StatValue;
1074 m_unackedBytes = stats.StatsBlock[15].StatValue;
1075 m_agentFrameTime = stats.StatsBlock[16].StatValue;
1076 m_pendingDownloads = stats.StatsBlock[17].StatValue;
1077 m_pendingUploads = stats.StatsBlock[18].StatValue;
1078 m_activeScripts = stats.StatsBlock[19].StatValue;
1079 m_scriptLinesPerSecond = stats.StatsBlock[20].StatValue;
1080 }
1081 }
1082
1083}