WebStatsModule.cs 48 KB

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