aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorTeravus Ovares2009-01-05 04:09:04 +0000
committerTeravus Ovares2009-01-05 04:09:04 +0000
commite4a8cc192dd16930718ff18838aa82e6187741bf (patch)
treea41492dc43a435fcd8a9395fb1f6aff8ae03b702
parent* Another minor GenericMessage fix - If we assume the method names are case-i... (diff)
downloadopensim-SC-e4a8cc192dd16930718ff18838aa82e6187741bf.zip
opensim-SC-e4a8cc192dd16930718ff18838aa82e6187741bf.tar.gz
opensim-SC-e4a8cc192dd16930718ff18838aa82e6187741bf.tar.bz2
opensim-SC-e4a8cc192dd16930718ff18838aa82e6187741bf.tar.xz
* Adds an active log to the WebStats console. for an example of it in use as it is right now see http://wmcv.com:9000/SStats/
* It still isn't quite ready to be used mainstream. * A couple of things to note, it doesn't keep track of the logs if nobody is looking at the stats. * It doesn't read the whole log file. Just the last 10 lines of the stream. Tested to 1GB+ logfiles with no noticeable performance issues.
-rw-r--r--OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs13
-rw-r--r--OpenSim/Region/UserStatistics/Default_Report.cs16
-rw-r--r--OpenSim/Region/UserStatistics/LogLinesAJAX.cs98
-rw-r--r--OpenSim/Region/UserStatistics/SimStatsAJAX.cs3
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs66
5 files changed, 185 insertions, 11 deletions
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
index 2dcd2b8..ed8fc40 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
@@ -14,6 +14,7 @@ namespace OpenSim.Region.UserStatistics
14 { 14 {
15 #region IStatsController Members 15 #region IStatsController Members
16 16
17 private Vector3 DefaultNeighborPosition = new Vector3(128, 128, 70);
17 public Hashtable ProcessModel(Hashtable pParams) 18 public Hashtable ProcessModel(Hashtable pParams)
18 { 19 {
19 20
@@ -50,10 +51,20 @@ namespace OpenSim.Region.UserStatistics
50 output.Append(av.Name); 51 output.Append(av.Name);
51 output.Append("      "); 52 output.Append("      ");
52 output.Append((av.IsChildAgent ? "Child" : "Root")); 53 output.Append((av.IsChildAgent ? "Child" : "Root"));
53 54 if (av.AbsolutePosition == DefaultNeighborPosition)
55 {
56 output.Append("<br />Position: ?");
57 }
58 else
59 {
60 output.Append(string.Format("<br /><NOBR>Position: <{0},{1},{2}></NOBR>", (int)av.AbsolutePosition.X,
61 (int) av.AbsolutePosition.Y,
62 (int) av.AbsolutePosition.Z));
63 }
54 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1)); 64 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
55 65
56 HTMLUtil.UL_O(ref output, ""); 66 HTMLUtil.UL_O(ref output, "");
67
57 foreach (string throttlename in throttles.Keys) 68 foreach (string throttlename in throttles.Keys)
58 { 69 {
59 HTMLUtil.LI_O(ref output, ""); 70 HTMLUtil.LI_O(ref output, "");
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs
index 02b15ad..eac4a7e 100644
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ b/OpenSim/Region/UserStatistics/Default_Report.cs
@@ -76,9 +76,9 @@ TD.align_top { vertical-align: top; }
76 HTMLUtil.HtmlHeaders_O(ref output); 76 HTMLUtil.HtmlHeaders_O(ref output);
77 77
78 HTMLUtil.InsertProtoTypeAJAX(ref output); 78 HTMLUtil.InsertProtoTypeAJAX(ref output);
79 string[] ajaxUpdaterDivs = new string[2]; 79 string[] ajaxUpdaterDivs = new string[3];
80 int[] ajaxUpdaterSeconds = new int[2]; 80 int[] ajaxUpdaterSeconds = new int[3];
81 string[] ajaxUpdaterReportFragments = new string[2]; 81 string[] ajaxUpdaterReportFragments = new string[3];
82 82
83 ajaxUpdaterDivs[0] = "activeconnections"; 83 ajaxUpdaterDivs[0] = "activeconnections";
84 ajaxUpdaterSeconds[0] = 10; 84 ajaxUpdaterSeconds[0] = 10;
@@ -88,6 +88,10 @@ TD.align_top { vertical-align: top; }
88 ajaxUpdaterSeconds[1] = 20; 88 ajaxUpdaterSeconds[1] = 20;
89 ajaxUpdaterReportFragments[1] = "simstatsajax.ajax"; 89 ajaxUpdaterReportFragments[1] = "simstatsajax.ajax";
90 90
91 ajaxUpdaterDivs[2] = "activelog";
92 ajaxUpdaterSeconds[2] = 5;
93 ajaxUpdaterReportFragments[2] = "activelogajax.ajax";
94
91 HTMLUtil.InsertPeriodicUpdaters(ref output, ajaxUpdaterDivs, ajaxUpdaterSeconds, ajaxUpdaterReportFragments); 95 HTMLUtil.InsertPeriodicUpdaters(ref output, ajaxUpdaterDivs, ajaxUpdaterSeconds, ajaxUpdaterReportFragments);
92 96
93 output.Append(STYLESHEET); 97 output.Append(STYLESHEET);
@@ -152,11 +156,11 @@ TD.align_top { vertical-align: top; }
152 HTMLUtil.TABLE_O(ref output, ""); 156 HTMLUtil.TABLE_O(ref output, "");
153 HTMLUtil.TR_O(ref output, ""); 157 HTMLUtil.TR_O(ref output, "");
154 HTMLUtil.TD_O(ref output, "align_top"); 158 HTMLUtil.TD_O(ref output, "align_top");
155 output.Append("<DIV id=\"activeconnections\">loading...</DIV>"); 159 output.Append("<DIV id=\"activeconnections\">Active Connections loading...</DIV>");
156 HTMLUtil.TD_C(ref output); 160 HTMLUtil.TD_C(ref output);
157 HTMLUtil.TD_O(ref output, "align_top"); 161 HTMLUtil.TD_O(ref output, "align_top");
158 output.Append("<DIV id=\"activesimstats\">loading...</DIV>"); 162 output.Append("<DIV id=\"activesimstats\">SimStats loading...</DIV>");
159 163 output.Append("<DIV id=\"activelog\">ActiveLog loading...</DIV>");
160 HTMLUtil.TD_C(ref output); 164 HTMLUtil.TD_C(ref output);
161 HTMLUtil.TR_C(ref output); 165 HTMLUtil.TR_C(ref output);
162 HTMLUtil.TABLE_C(ref output); 166 HTMLUtil.TABLE_C(ref output);
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
new file mode 100644
index 0000000..9626c12
--- /dev/null
+++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
@@ -0,0 +1,98 @@
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Reflection;
5using System.Text;
6using System.Text.RegularExpressions;
7using Mono.Data.SqliteClient;
8using OpenMetaverse;
9using OpenSim.Region.Environment.Scenes;
10using OpenSim.Framework.Statistics;
11
12namespace OpenSim.Region.UserStatistics
13{
14 public class LogLinesAJAX : IStatsController
15 {
16 private Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline);
17
18 private Regex webFormat = new Regex(@"[^\s]*\s([^,]*),[^\s]*\s([A-Z]*)[^\s-][^\[]*\[([^\]]*)\]([^\n]*)",
19 RegexOptions.Singleline | RegexOptions.Compiled);
20 private Regex TitleColor = new Regex(@"[^\s]*\s(?:[^,]*),[^\s]*\s(?:[A-Z]*)[^\s-][^\[]*\[([^\]]*)\](?:[^\n]*)",
21 RegexOptions.Singleline | RegexOptions.Compiled);
22
23
24 #region IStatsController Members
25
26 public Hashtable ProcessModel(Hashtable pParams)
27 {
28 Hashtable nh = new Hashtable();
29 nh.Add("loglines", pParams["LogLines"]);
30 return nh;
31 }
32
33 public string RenderView(Hashtable pModelResult)
34 {
35 StringBuilder output = new StringBuilder();
36
37 HTMLUtil.HR(ref output, "");
38 output.Append("<H3>ActiveLog</H3>\n");
39
40 string tmp = normalizeEndLines.Replace(pModelResult["loglines"].ToString(), "\n");
41
42 string[] result = Regex.Split(tmp, "\n");
43
44 string formatopen = "";
45 string formatclose = "";
46
47 for (int i = 0; i < result.Length;i++ )
48 {
49 if (result[i].Length >= 30)
50 {
51 string logtype = result[i].Substring(24, 6);
52 switch (logtype)
53 {
54 case "WARN ":
55 formatopen = "<font color=\"#7D7C00\">";
56 formatclose = "</font>";
57 break;
58
59 case "ERROR ":
60 formatopen = "<font color=\"#FF0000\">";
61 formatclose = "</font>";
62 break;
63
64 default:
65 formatopen = "";
66 formatclose = "";
67 break;
68
69 }
70 }
71 StringBuilder replaceStr = new StringBuilder();
72 //string titlecolorresults =
73
74 string formatresult = Regex.Replace(TitleColor.Replace(result[i], "$1"), "[^ABCDEFabcdef0-9]", "");
75 if (formatresult.Length > 6)
76 {
77 formatresult = formatresult.Substring(0, 6);
78
79 }
80 for (int j = formatresult.Length; j <= 5; j++)
81 formatresult += "0";
82 replaceStr.Append("$1 - [<font color=\"#");
83 replaceStr.Append(formatresult);
84 replaceStr.Append("\">$3</font>] $4<br />");
85 string repstr = replaceStr.ToString();
86
87 output.Append(formatopen);
88 output.Append(webFormat.Replace(result[i], repstr));
89 output.Append(formatclose);
90 }
91
92
93 return output.ToString();
94 }
95
96 #endregion
97 }
98}
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
index f6dd1d6..26fe3d4 100644
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
@@ -21,7 +21,6 @@ namespace OpenSim.Region.UserStatistics
21 Hashtable nh = new Hashtable(); 21 Hashtable nh = new Hashtable();
22 nh.Add("hdata", m_scene); 22 nh.Add("hdata", m_scene);
23 nh.Add("simstats", pParams["SimStats"]); 23 nh.Add("simstats", pParams["SimStats"]);
24
25 return nh; 24 return nh;
26 } 25 }
27 26
@@ -181,7 +180,9 @@ namespace OpenSim.Region.UserStatistics
181 HTMLUtil.TD_C(ref output); 180 HTMLUtil.TD_C(ref output);
182 HTMLUtil.TR_C(ref output); 181 HTMLUtil.TR_C(ref output);
183 HTMLUtil.TABLE_C(ref output); 182 HTMLUtil.TABLE_C(ref output);
183
184 } 184 }
185
185 return output.ToString(); 186 return output.ToString();
186 } 187 }
187 188
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index 4eb8cb7..832c763 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -1,8 +1,11 @@
1using System; 1using System;
2using System.Collections; 2using System.Collections;
3using System.Collections.Generic; 3using System.Collections.Generic;
4using System.IO;
4using System.Net; // to be used for REST-->Grid shortly 5using System.Net; // to be used for REST-->Grid shortly
5using System.Reflection; 6using System.Reflection;
7using System.Text;
8using System.Threading;
6using log4net; 9using log4net;
7using Nini.Config; 10using Nini.Config;
8using OpenMetaverse; 11using OpenMetaverse;
@@ -25,14 +28,19 @@ namespace OpenSim.Region.UserStatistics
25 { 28 {
26 private static readonly ILog m_log = 29 private static readonly ILog m_log =
27 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 30 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
31
28 private static SqliteConnection dbConn; 32 private static SqliteConnection dbConn;
29 private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>(); 33 private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>();
30 private List<Scene> m_scene = new List<Scene>(); 34 private List<Scene> m_scene = new List<Scene>();
31 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); 35 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
32 private Dictionary<UUID, USimStatsData> m_simstatsCounters = new Dictionary<UUID, USimStatsData>(); 36 private Dictionary<UUID, USimStatsData> m_simstatsCounters = new Dictionary<UUID, USimStatsData>();
33 private const int updateStatsMod = 6; 37 private const int updateStatsMod = 6;
38 private int updateLogMod = 1;
39 private volatile int updateLogCounter = 0;
34 private volatile int concurrencyCounter = 0; 40 private volatile int concurrencyCounter = 0;
35 private bool enabled = false; 41 private bool enabled = false;
42 private string m_loglines = String.Empty;
43 private volatile int lastHit = 12000;
36 44
37 45
38 public virtual void Initialise(Scene scene, IConfigSource config) 46 public virtual void Initialise(Scene scene, IConfigSource config)
@@ -42,7 +50,8 @@ namespace OpenSim.Region.UserStatistics
42 { 50 {
43 cnfg = config.Configs["WebStats"]; 51 cnfg = config.Configs["WebStats"];
44 enabled = cnfg.GetBoolean("enabled", false); 52 enabled = cnfg.GetBoolean("enabled", false);
45 53
54
46 } 55 }
47 catch (Exception) 56 catch (Exception)
48 { 57 {
@@ -68,12 +77,14 @@ namespace OpenSim.Region.UserStatistics
68 Updater_distributor updatedep = new Updater_distributor(); 77 Updater_distributor updatedep = new Updater_distributor();
69 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX(); 78 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX();
70 SimStatsAJAX ajSimStats = new SimStatsAJAX(); 79 SimStatsAJAX ajSimStats = new SimStatsAJAX();
80 LogLinesAJAX ajLogLines = new LogLinesAJAX();
71 reports.Add("", rep); 81 reports.Add("", rep);
72 reports.Add("index.aspx", rep); 82 reports.Add("index.aspx", rep);
73 reports.Add("prototype.js", protodep); 83 reports.Add("prototype.js", protodep);
74 reports.Add("updater.js", updatedep); 84 reports.Add("updater.js", updatedep);
75 reports.Add("activeconnectionsajax.ajax", ajConnections); 85 reports.Add("activeconnectionsajax.ajax", ajConnections);
76 reports.Add("simstatsajax.ajax", ajSimStats); 86 reports.Add("simstatsajax.ajax", ajSimStats);
87 reports.Add("activelogajax.ajax", ajLogLines);
77 88
78 scene.CommsManager.HttpServer.AddHTTPHandler("/SStats/", HandleStatsRequest); 89 scene.CommsManager.HttpServer.AddHTTPHandler("/SStats/", HandleStatsRequest);
79 90
@@ -95,10 +106,17 @@ namespace OpenSim.Region.UserStatistics
95 106
96 try 107 try
97 { 108 {
98 109 // Ignore the update if there's a report running right now
99 if (concurrencyCounter > 0) 110 // ignore the update if there hasn't been a hit in 30 seconds.
111 if (concurrencyCounter > 0 && System.Environment.TickCount - lastHit < 30000)
100 return; 112 return;
101 113
114 if ((updateLogCounter++ % updateLogMod) == 0)
115 {
116 m_loglines = readLogLines(10);
117 if (updateLogCounter > 10000) updateLogCounter = 1;
118 }
119
102 USimStatsData ss = m_simstatsCounters[stats.RegionUUID]; 120 USimStatsData ss = m_simstatsCounters[stats.RegionUUID];
103 121
104 if ((++ss.StatsCounter % updateStatsMod) == 0) 122 if ((++ss.StatsCounter % updateStatsMod) == 0)
@@ -114,6 +132,7 @@ namespace OpenSim.Region.UserStatistics
114 132
115 public Hashtable HandleStatsRequest(Hashtable request) 133 public Hashtable HandleStatsRequest(Hashtable request)
116 { 134 {
135 lastHit = System.Environment.TickCount;
117 Hashtable responsedata = new Hashtable(); 136 Hashtable responsedata = new Hashtable();
118 string regpath = request["uri"].ToString(); 137 string regpath = request["uri"].ToString();
119 int response_code = 404; 138 int response_code = 404;
@@ -130,6 +149,7 @@ namespace OpenSim.Region.UserStatistics
130 repParams["DatabaseConnection"] = dbConn; 149 repParams["DatabaseConnection"] = dbConn;
131 repParams["Scenes"] = m_scene; 150 repParams["Scenes"] = m_scene;
132 repParams["SimStats"] = m_simstatsCounters; 151 repParams["SimStats"] = m_simstatsCounters;
152 repParams["LogLines"] = m_loglines;
133 153
134 concurrencyCounter++; 154 concurrencyCounter++;
135 155
@@ -245,6 +265,7 @@ namespace OpenSim.Region.UserStatistics
245 { 265 {
246 lock (m_scene) 266 lock (m_scene)
247 { 267 {
268 updateLogMod = m_scene.Count * 2;
248 foreach (Scene scene in m_scene) 269 foreach (Scene scene in m_scene)
249 { 270 {
250 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 271 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
@@ -315,6 +336,45 @@ namespace OpenSim.Region.UserStatistics
315 336
316 } 337 }
317 338
339 public string readLogLines( int amount)
340 {
341 Encoding encoding = Encoding.ASCII;
342 int sizeOfChar = encoding.GetByteCount("\n");
343 byte[] buffer = encoding.GetBytes("\n");
344 string logfile = Util.logDir() + "/" + "OpenSim.log";
345 FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
346 Int64 tokenCount = 0;
347 Int64 endPosition = fs.Length / sizeOfChar;
348
349 for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar)
350 {
351 fs.Seek(-position, SeekOrigin.End);
352 fs.Read(buffer, 0, buffer.Length);
353
354 if (encoding.GetString(buffer) == "\n")
355 {
356 tokenCount++;
357 if (tokenCount == amount)
358 {
359 byte[] returnBuffer = new byte[fs.Length - fs.Position];
360 fs.Read(returnBuffer, 0, returnBuffer.Length);
361 fs.Close();
362 fs.Dispose();
363 return encoding.GetString(returnBuffer);
364 }
365 }
366 }
367
368 // handle case where number of tokens in file is less than numberOfTokens
369 fs.Seek(0, SeekOrigin.Begin);
370 buffer = new byte[fs.Length];
371 fs.Read(buffer, 0, buffer.Length);
372 fs.Close();
373 fs.Dispose();
374 return encoding.GetString(buffer);
375
376 }
377
318 public UUID GetRegionUUIDFromHandle(ulong regionhandle) 378 public UUID GetRegionUUIDFromHandle(ulong regionhandle)
319 { 379 {
320 lock (m_scene) 380 lock (m_scene)