aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring
diff options
context:
space:
mode:
authorBlueWall2012-10-20 05:25:58 -0400
committerBlueWall2012-10-20 05:25:58 -0400
commit07f1d44174f5e2b4e3d5ffdec3619bb84f357af2 (patch)
tree83cc0442b2c1b89a5b3dd94cff23d5098415777e /OpenSim/Framework/Monitoring
parentMerge branch 'master' into connector_plugin (diff)
parentFix: invinite loading for Viewer3 : parcelinfo request of traffic-value (impl... (diff)
downloadopensim-SC_OLD-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.zip
opensim-SC_OLD-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.tar.gz
opensim-SC_OLD-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.tar.bz2
opensim-SC_OLD-07f1d44174f5e2b4e3d5ffdec3619bb84f357af2.tar.xz
Merge branch 'master' into connector_plugin
Diffstat (limited to 'OpenSim/Framework/Monitoring')
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs6
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs10
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs16
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs204
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs20
5 files changed, 228 insertions, 28 deletions
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 57a63ef..2903b6e 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -49,7 +49,11 @@ namespace OpenSim.Framework.Monitoring
49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
50 50
51 sb.AppendFormat( 51 sb.AppendFormat(
52 "OpenSim object memory churn : {0} MB/s\n", 52 "OpenSim last object memory churn : {0} MB/s\n",
53 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
54
55 sb.AppendFormat(
56 "OpenSim average object memory churn : {0} MB/s\n",
53 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); 57 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
54 58
55 sb.AppendFormat( 59 sb.AppendFormat(
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index a23cf1f..c6010cd 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Average memory churn in bytes per millisecond. 63 /// Last memory churn in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageMemoryChurn
66 { 66 {
@@ -68,6 +68,14 @@ namespace OpenSim.Framework.Monitoring
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond.
72 /// </summary>
73 public static double LastMemoryChurn
74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 }
77
78 /// <summary>
71 /// Maximum number of statistical samples. 79 /// Maximum number of statistical samples.
72 /// </summary> 80 /// </summary>
73 /// <remarks> 81 /// <remarks>
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index 8ac9090..aa86202 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -359,13 +359,19 @@ Asset service request failures: {3}" + Environment.NewLine,
359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, 359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); 360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
361 361
362 foreach (KeyValuePair<string, Stat> kvp in StatsManager.RegisteredStats) 362 Dictionary<string, Dictionary<string, Stat>> sceneStats;
363 {
364 Stat stat = kvp.Value;
365 363
366 if (stat.Category == "scene" && stat.Verbosity == StatVerbosity.Info) 364 if (StatsManager.TryGetStats("scene", out sceneStats))
365 {
366 foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats)
367 { 367 {
368 sb.AppendFormat("Slow frames ({0}): {1}\n", stat.Container, stat.Value); 368 foreach (Stat stat in kvp.Value.Values)
369 {
370 if (stat.Verbosity == StatVerbosity.Info)
371 {
372 sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName);
373 }
374 }
369 } 375 }
370 } 376 }
371 377
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index b5dc24f..31989e5 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -35,13 +35,23 @@ namespace OpenSim.Framework.Monitoring
35 /// </summary> 35 /// </summary>
36 public class StatsManager 36 public class StatsManager
37 { 37 {
38 // Subcommand used to list other stats.
39 public const string AllSubCommand = "all";
40
41 // Subcommand used to list other stats.
42 public const string ListSubCommand = "list";
43
44 // All subcommands
45 public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand };
46
38 /// <summary> 47 /// <summary>
39 /// Registered stats. 48 /// Registered stats categorized by category/container/shortname
40 /// </summary> 49 /// </summary>
41 /// <remarks> 50 /// <remarks>
42 /// Do not add or remove from this dictionary. 51 /// Do not add or remove directly from this dictionary.
43 /// </remarks> 52 /// </remarks>
44 public static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); 53 public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats
54 = new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>();
45 55
46 private static AssetStatsCollector assetStats; 56 private static AssetStatsCollector assetStats;
47 private static UserStatsCollector userStats; 57 private static UserStatsCollector userStats;
@@ -51,6 +61,75 @@ namespace OpenSim.Framework.Monitoring
51 public static UserStatsCollector UserStats { get { return userStats; } } 61 public static UserStatsCollector UserStats { get { return userStats; } }
52 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 62 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
53 63
64 public static void RegisterConsoleCommands(ICommandConsole console)
65 {
66 console.Commands.AddCommand(
67 "General",
68 false,
69 "show stats",
70 "show stats [list|all|<category>]",
71 "Show statistical information for this server",
72 "If no final argument is specified then legacy statistics information is currently shown.\n"
73 + "If list is specified then statistic categories are shown.\n"
74 + "If all is specified then all registered statistics are shown.\n"
75 + "If a category name is specified then only statistics from that category are shown.\n"
76 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
77 HandleShowStatsCommand);
78 }
79
80 public static void HandleShowStatsCommand(string module, string[] cmd)
81 {
82 ICommandConsole con = MainConsole.Instance;
83
84 if (cmd.Length > 2)
85 {
86 var categoryName = cmd[2];
87
88 if (categoryName == AllSubCommand)
89 {
90 foreach (var category in RegisteredStats.Values)
91 {
92 OutputCategoryStatsToConsole(con, category);
93 }
94 }
95 else if (categoryName == ListSubCommand)
96 {
97 con.Output("Statistic categories available are:");
98 foreach (string category in RegisteredStats.Keys)
99 con.OutputFormat(" {0}", category);
100 }
101 else
102 {
103 Dictionary<string, Dictionary<string, Stat>> category;
104 if (!RegisteredStats.TryGetValue(categoryName, out category))
105 {
106 con.OutputFormat("No such category as {0}", categoryName);
107 }
108 else
109 {
110 OutputCategoryStatsToConsole(con, category);
111 }
112 }
113 }
114 else
115 {
116 // Legacy
117 con.Output(SimExtraStats.Report());
118 }
119 }
120
121 private static void OutputCategoryStatsToConsole(
122 ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category)
123 {
124 foreach (var container in category.Values)
125 {
126 foreach (Stat stat in container.Values)
127 {
128 con.Output(stat.ToConsoleString());
129 }
130 }
131 }
132
54 /// <summary> 133 /// <summary>
55 /// Start collecting statistics related to assets. 134 /// Start collecting statistics related to assets.
56 /// Should only be called once. 135 /// Should only be called once.
@@ -73,43 +152,100 @@ namespace OpenSim.Framework.Monitoring
73 return userStats; 152 return userStats;
74 } 153 }
75 154
155 /// <summary>
156 /// Registers a statistic.
157 /// </summary>
158 /// <param name='stat'></param>
159 /// <returns></returns>
76 public static bool RegisterStat(Stat stat) 160 public static bool RegisterStat(Stat stat)
77 { 161 {
162 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
163 Dictionary<string, Stat> container = null, newContainer;
164
78 lock (RegisteredStats) 165 lock (RegisteredStats)
79 { 166 {
80 if (RegisteredStats.ContainsKey(stat.UniqueName)) 167 // Stat name is not unique across category/container/shortname key.
81 { 168 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
82 // XXX: For now just return false. This is to avoid problems in regression tests where all tests 169 // in a class are run in the same instance of the VM.
83 // in a class are run in the same instance of the VM. 170 if (TryGetStat(stat, out category, out container))
84 return false; 171 return false;
85 172
86// throw new Exception( 173 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
87// "StatsManager already contains stat with ShortName {0} in Category {1}", stat.ShortName, stat.Category); 174 // This means that we don't need to lock or copy them on iteration, which will be a much more
88 } 175 // common operation after startup.
176 if (container != null)
177 newContainer = new Dictionary<string, Stat>(container);
178 else
179 newContainer = new Dictionary<string, Stat>();
89 180
90 // We take a replace-on-write approach here so that we don't need to generate a new Dictionary 181 if (category != null)
91 Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); 182 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
92 newRegisteredStats[stat.UniqueName] = stat; 183 else
93 RegisteredStats = newRegisteredStats; 184 newCategory = new Dictionary<string, Dictionary<string, Stat>>();
185
186 newContainer[stat.ShortName] = stat;
187 newCategory[stat.Container] = newContainer;
188 RegisteredStats[stat.Category] = newCategory;
94 } 189 }
95 190
96 return true; 191 return true;
97 } 192 }
98 193
194 /// <summary>
195 /// Deregister a statistic
196 /// </summary>>
197 /// <param name='stat'></param>
198 /// <returns></returns
99 public static bool DeregisterStat(Stat stat) 199 public static bool DeregisterStat(Stat stat)
100 { 200 {
201 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
202 Dictionary<string, Stat> container = null, newContainer;
203
101 lock (RegisteredStats) 204 lock (RegisteredStats)
102 { 205 {
103 if (!RegisteredStats.ContainsKey(stat.UniqueName)) 206 if (!TryGetStat(stat, out category, out container))
104 return false; 207 return false;
105 208
106 Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); 209 newContainer = new Dictionary<string, Stat>(container);
107 newRegisteredStats.Remove(stat.UniqueName); 210 newContainer.Remove(stat.UniqueName);
108 RegisteredStats = newRegisteredStats; 211
212 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
213 newCategory.Remove(stat.Container);
214
215 newCategory[stat.Container] = newContainer;
216 RegisteredStats[stat.Category] = newCategory;
109 217
110 return true; 218 return true;
111 } 219 }
112 } 220 }
221
222 public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats)
223 {
224 return RegisteredStats.TryGetValue(category, out stats);
225 }
226
227 public static bool TryGetStat(
228 Stat stat,
229 out Dictionary<string, Dictionary<string, Stat>> category,
230 out Dictionary<string, Stat> container)
231 {
232 category = null;
233 container = null;
234
235 lock (RegisteredStats)
236 {
237 if (RegisteredStats.TryGetValue(stat.Category, out category))
238 {
239 if (category.TryGetValue(stat.Container, out container))
240 {
241 if (container.ContainsKey(stat.ShortName))
242 return true;
243 }
244 }
245 }
246
247 return false;
248 }
113 } 249 }
114 250
115 /// <summary> 251 /// <summary>
@@ -157,9 +293,26 @@ namespace OpenSim.Framework.Monitoring
157 293
158 public virtual double Value { get; set; } 294 public virtual double Value { get; set; }
159 295
296 /// <summary>
297 /// Constructor
298 /// </summary>
299 /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param>
300 /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param>
301 /// <param name='unitName'>
302 /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
303 /// e.g. " frames"
304 /// </param>
305 /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param>
306 /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param>
307 /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param>
308 /// <param name='description'>Description of stat</param>
160 public Stat( 309 public Stat(
161 string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) 310 string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description)
162 { 311 {
312 if (StatsManager.SubCommands.Contains(category))
313 throw new Exception(
314 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
315
163 ShortName = shortName; 316 ShortName = shortName;
164 Name = name; 317 Name = name;
165 UnitName = unitName; 318 UnitName = unitName;
@@ -175,6 +328,12 @@ namespace OpenSim.Framework.Monitoring
175 { 328 {
176 return string.Format("{0}+{1}+{2}", container, category, shortName); 329 return string.Format("{0}+{1}+{2}", container, category, shortName);
177 } 330 }
331
332 public virtual string ToConsoleString()
333 {
334 return string.Format(
335 "{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
336 }
178 } 337 }
179 338
180 public class PercentageStat : Stat 339 public class PercentageStat : Stat
@@ -192,7 +351,7 @@ namespace OpenSim.Framework.Monitoring
192 if (c == 0) 351 if (c == 0)
193 return 0; 352 return 0;
194 353
195 return (double)Antecedent / c; 354 return (double)Antecedent / c * 100;
196 } 355 }
197 356
198 set 357 set
@@ -203,8 +362,13 @@ namespace OpenSim.Framework.Monitoring
203 362
204 public PercentageStat( 363 public PercentageStat(
205 string shortName, string name, string category, string container, StatVerbosity verbosity, string description) 364 string shortName, string name, string category, string container, StatVerbosity verbosity, string description)
206 : base(shortName, name, " %", category, container, verbosity, description) 365 : base(shortName, name, "%", category, container, verbosity, description) {}
366
367 public override string ToConsoleString()
207 { 368 {
369 return string.Format(
370 "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})",
371 Category, Container, ShortName, Value, UnitName, Antecedent, Consequent);
208 } 372 }
209 } 373 }
210} \ No newline at end of file 374} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 7964f28..a20326d 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -231,7 +231,25 @@ namespace OpenSim.Framework.Monitoring
231 private static bool RemoveThread(int threadID) 231 private static bool RemoveThread(int threadID)
232 { 232 {
233 lock (m_threads) 233 lock (m_threads)
234 return m_threads.Remove(threadID); 234 {
235 ThreadWatchdogInfo twi;
236 if (m_threads.TryGetValue(threadID, out twi))
237 {
238 m_log.DebugFormat(
239 "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
240
241 m_threads.Remove(threadID);
242
243 return true;
244 }
245 else
246 {
247 m_log.WarnFormat(
248 "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID);
249
250 return false;
251 }
252 }
235 } 253 }
236 254
237 public static bool AbortThread(int threadID) 255 public static bool AbortThread(int threadID)