WebStatsModule.cs 48 KB

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