clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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  
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Reflection;
32 using log4net;
33 using Nini.Config;
34 using OpenMetaverse;
35 using OpenSim.Framework;
36 using OpenSim.Framework.Monitoring;
37 using OpenSim.Framework.Servers;
38 using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts;
39 using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors;
40 using OpenSim.Region.Framework.Interfaces;
41 using OpenSim.Region.Framework.Scenes;
42 using Mono.Addins;
43  
44 namespace OpenSim.Region.CoreModules.Framework.Monitoring
45 {
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MonitorModule")]
47 public class MonitorModule : INonSharedRegionModule
48 {
49 /// <summary>
50 /// Is this module enabled?
51 /// </summary>
52 public bool Enabled { get; private set; }
53  
54 private Scene m_scene;
55  
56 /// <summary>
57 /// These are monitors where we know the static details in advance.
58 /// </summary>
59 /// <remarks>
60 /// Dynamic monitors also exist (we don't know any of the details of what stats we get back here)
61 /// but these are currently hardcoded.
62 /// </remarks>
63 private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>();
64  
65 private readonly List<IAlert> m_alerts = new List<IAlert>();
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67  
68 public MonitorModule()
69 {
70 Enabled = true;
71 }
72  
73 #region Implementation of INonSharedRegionModule
74  
75 public void Initialise(IConfigSource source)
76 {
77 IConfig cnfg = source.Configs["Monitoring"];
78  
79 if (cnfg != null)
80 Enabled = cnfg.GetBoolean("Enabled", true);
81  
82 if (!Enabled)
83 return;
84  
85 }
86  
87 public void AddRegion(Scene scene)
88 {
89 if (!Enabled)
90 return;
91  
92 m_scene = scene;
93  
94 m_scene.AddCommand("General", this, "monitor report",
95 "monitor report",
96 "Returns a variety of statistics about the current region and/or simulator",
97 DebugMonitors);
98  
99 MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID, StatsPage);
100 MainServer.Instance.AddHTTPHandler(
101 "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage);
102  
103 AddMonitors();
104 RegisterStatsManagerRegionStatistics();
105 }
106  
107 public void RemoveRegion(Scene scene)
108 {
109 if (!Enabled)
110 return;
111  
112 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID);
113 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName));
114  
115 UnRegisterStatsManagerRegionStatistics();
116  
117 m_scene = null;
118 }
119  
120 public void Close()
121 {
122 }
123  
124 public string Name
125 {
126 get { return "Region Health Monitoring Module"; }
127 }
128  
129 public void RegionLoaded(Scene scene)
130 {
131 }
132  
133 public Type ReplaceableInterface
134 {
135 get { return null; }
136 }
137  
138 #endregion
139  
140 public void AddMonitors()
141 {
142 m_staticMonitors.Add(new AgentCountMonitor(m_scene));
143 m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
144 m_staticMonitors.Add(new GCMemoryMonitor());
145 m_staticMonitors.Add(new ObjectCountMonitor(m_scene));
146 m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene));
147 m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
148 m_staticMonitors.Add(new PWSMemoryMonitor());
149 m_staticMonitors.Add(new ThreadCountMonitor());
150 m_staticMonitors.Add(new TotalFrameMonitor(m_scene));
151 m_staticMonitors.Add(new EventFrameMonitor(m_scene));
152 m_staticMonitors.Add(new LandFrameMonitor(m_scene));
153 m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
154  
155 m_staticMonitors.Add(
156 new GenericMonitor(
157 m_scene,
158 "TimeDilationMonitor",
159 "Time Dilation",
160 m => m.Scene.StatsReporter.LastReportedSimStats[0],
161 m => m.GetValue().ToString()));
162  
163 m_staticMonitors.Add(
164 new GenericMonitor(
165 m_scene,
166 "SimFPSMonitor",
167 "Sim FPS",
168 m => m.Scene.StatsReporter.LastReportedSimStats[1],
169 m => string.Format("{0}", m.GetValue())));
170  
171 m_staticMonitors.Add(
172 new GenericMonitor(
173 m_scene,
174 "PhysicsFPSMonitor",
175 "Physics FPS",
176 m => m.Scene.StatsReporter.LastReportedSimStats[2],
177 m => string.Format("{0}", m.GetValue())));
178  
179 m_staticMonitors.Add(
180 new GenericMonitor(
181 m_scene,
182 "AgentUpdatesPerSecondMonitor",
183 "Agent Updates",
184 m => m.Scene.StatsReporter.LastReportedSimStats[3],
185 m => string.Format("{0} per second", m.GetValue())));
186  
187 m_staticMonitors.Add(
188 new GenericMonitor(
189 m_scene,
190 "ActiveObjectCountMonitor",
191 "Active Objects",
192 m => m.Scene.StatsReporter.LastReportedSimStats[7],
193 m => string.Format("{0}", m.GetValue())));
194  
195 m_staticMonitors.Add(
196 new GenericMonitor(
197 m_scene,
198 "ActiveScriptsMonitor",
199 "Active Scripts",
200 m => m.Scene.StatsReporter.LastReportedSimStats[19],
201 m => string.Format("{0}", m.GetValue())));
202  
203 m_staticMonitors.Add(
204 new GenericMonitor(
205 m_scene,
206 "ScriptEventsPerSecondMonitor",
207 "Script Events",
208 m => m.Scene.StatsReporter.LastReportedSimStats[20],
209 m => string.Format("{0} per second", m.GetValue())));
210  
211 m_staticMonitors.Add(
212 new GenericMonitor(
213 m_scene,
214 "InPacketsPerSecondMonitor",
215 "In Packets",
216 m => m.Scene.StatsReporter.LastReportedSimStats[13],
217 m => string.Format("{0} per second", m.GetValue())));
218  
219 m_staticMonitors.Add(
220 new GenericMonitor(
221 m_scene,
222 "OutPacketsPerSecondMonitor",
223 "Out Packets",
224 m => m.Scene.StatsReporter.LastReportedSimStats[14],
225 m => string.Format("{0} per second", m.GetValue())));
226  
227 m_staticMonitors.Add(
228 new GenericMonitor(
229 m_scene,
230 "UnackedBytesMonitor",
231 "Unacked Bytes",
232 m => m.Scene.StatsReporter.LastReportedSimStats[15],
233 m => string.Format("{0}", m.GetValue())));
234  
235 m_staticMonitors.Add(
236 new GenericMonitor(
237 m_scene,
238 "PendingDownloadsMonitor",
239 "Pending Downloads",
240 m => m.Scene.StatsReporter.LastReportedSimStats[17],
241 m => string.Format("{0}", m.GetValue())));
242  
243 m_staticMonitors.Add(
244 new GenericMonitor(
245 m_scene,
246 "PendingUploadsMonitor",
247 "Pending Uploads",
248 m => m.Scene.StatsReporter.LastReportedSimStats[18],
249 m => string.Format("{0}", m.GetValue())));
250  
251 m_staticMonitors.Add(
252 new GenericMonitor(
253 m_scene,
254 "TotalFrameTimeMonitor",
255 "Total Frame Time",
256 m => m.Scene.StatsReporter.LastReportedSimStats[8],
257 m => string.Format("{0} ms", m.GetValue())));
258  
259 m_staticMonitors.Add(
260 new GenericMonitor(
261 m_scene,
262 "NetFrameTimeMonitor",
263 "Net Frame Time",
264 m => m.Scene.StatsReporter.LastReportedSimStats[9],
265 m => string.Format("{0} ms", m.GetValue())));
266  
267 m_staticMonitors.Add(
268 new GenericMonitor(
269 m_scene,
270 "PhysicsFrameTimeMonitor",
271 "Physics Frame Time",
272 m => m.Scene.StatsReporter.LastReportedSimStats[10],
273 m => string.Format("{0} ms", m.GetValue())));
274  
275 m_staticMonitors.Add(
276 new GenericMonitor(
277 m_scene,
278 "SimulationFrameTimeMonitor",
279 "Simulation Frame Time",
280 m => m.Scene.StatsReporter.LastReportedSimStats[12],
281 m => string.Format("{0} ms", m.GetValue())));
282  
283 m_staticMonitors.Add(
284 new GenericMonitor(
285 m_scene,
286 "AgentFrameTimeMonitor",
287 "Agent Frame Time",
288 m => m.Scene.StatsReporter.LastReportedSimStats[16],
289 m => string.Format("{0} ms", m.GetValue())));
290  
291 m_staticMonitors.Add(
292 new GenericMonitor(
293 m_scene,
294 "ImagesFrameTimeMonitor",
295 "Images Frame Time",
296 m => m.Scene.StatsReporter.LastReportedSimStats[11],
297 m => string.Format("{0} ms", m.GetValue())));
298  
299 m_staticMonitors.Add(
300 new GenericMonitor(
301 m_scene,
302 "SpareFrameTimeMonitor",
303 "Spare Frame Time",
304 m => m.Scene.StatsReporter.LastReportedSimStats[21],
305 m => string.Format("{0} ms", m.GetValue())));
306  
307 m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
308  
309 foreach (IAlert alert in m_alerts)
310 {
311 alert.OnTriggerAlert += OnTriggerAlert;
312 }
313 }
314  
315 public void DebugMonitors(string module, string[] args)
316 {
317 foreach (IMonitor monitor in m_staticMonitors)
318 {
319 MainConsole.Instance.OutputFormat(
320 "[MONITOR MODULE]: {0} reports {1} = {2}",
321 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
322 }
323  
324 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
325 {
326 MainConsole.Instance.OutputFormat(
327 "[MONITOR MODULE]: {0} reports {1} = {2}",
328 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
329 }
330 }
331  
332 public void TestAlerts()
333 {
334 foreach (IAlert alert in m_alerts)
335 {
336 alert.Test();
337 }
338 }
339  
340 public Hashtable StatsPage(Hashtable request)
341 {
342 // If request was for a specific monitor
343 // eg url/?monitor=Monitor.Name
344 if (request.ContainsKey("monitor"))
345 {
346 string monID = (string) request["monitor"];
347  
348 foreach (IMonitor monitor in m_staticMonitors)
349 {
350 string elemName = monitor.ToString();
351 if (elemName.StartsWith(monitor.GetType().Namespace))
352 elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
353  
354 if (elemName == monID || monitor.ToString() == monID)
355 {
356 Hashtable ereply3 = new Hashtable();
357  
358 ereply3["int_response_code"] = 404; // 200 OK
359 ereply3["str_response_string"] = monitor.GetValue().ToString();
360 ereply3["content_type"] = "text/plain";
361  
362 return ereply3;
363 }
364 }
365  
366 // FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
367 // is even doing. Why are we inspecting the type of the monitor???
368  
369 // No monitor with that name
370 Hashtable ereply2 = new Hashtable();
371  
372 ereply2["int_response_code"] = 404; // 200 OK
373 ereply2["str_response_string"] = "No such monitor";
374 ereply2["content_type"] = "text/plain";
375  
376 return ereply2;
377 }
378  
379 string xml = "<data>";
380 foreach (IMonitor monitor in m_staticMonitors)
381 {
382 string elemName = monitor.GetName();
383 xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
384 // m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
385 }
386  
387 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
388 {
389 xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
390 }
391  
392 xml += "</data>";
393  
394 Hashtable ereply = new Hashtable();
395  
396 ereply["int_response_code"] = 200; // 200 OK
397 ereply["str_response_string"] = xml;
398 ereply["content_type"] = "text/xml";
399  
400 return ereply;
401 }
402  
403 void OnTriggerAlert(System.Type reporter, string reason, bool fatal)
404 {
405 m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")");
406 }
407  
408 private List<Stat> registeredStats = new List<Stat>();
409 private void MakeStat(string pName, string pUnitName, Action<Stat> act)
410 {
411 Stat tempStat = new Stat(pName, pName, pName, pUnitName, "scene", m_scene.RegionInfo.RegionName, StatType.Pull, act, StatVerbosity.Info);
412 StatsManager.RegisterStat(tempStat);
413 registeredStats.Add(tempStat);
414 }
415 private void RegisterStatsManagerRegionStatistics()
416 {
417 MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); });
418 MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); });
419 MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); });
420 MakeStat("ActivePrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetActiveObjectsCount(); });
421 MakeStat("ActiveScripts", "scripts", (s) => { s.Value = m_scene.SceneGraph.GetActiveScriptsCount(); });
422  
423 MakeStat("TimeDilation", "sec/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[0]; });
424 MakeStat("SimFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[1]; });
425 MakeStat("PhysicsFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[2]; });
426 MakeStat("AgentUpdates", "updates/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[3]; });
427 MakeStat("FrameTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[8]; });
428 MakeStat("NetTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[9]; });
429 MakeStat("OtherTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[12]; });
430 MakeStat("PhysicsTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[10]; });
431 MakeStat("AgentTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[16]; });
432 MakeStat("ImageTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[11]; });
433 MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; });
434 MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; });
435 }
436  
437 private void UnRegisterStatsManagerRegionStatistics()
438 {
439 foreach (Stat stat in registeredStats)
440 {
441 StatsManager.DeregisterStat(stat);
442 stat.Dispose();
443 }
444 registeredStats.Clear();
445 }
446  
447 }
448 }