1
0

WebStatsModule.cs 48 KB

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