WebStatsModule.cs 49 KB

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