WebStatsModule.cs 46 KB

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