aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring
diff options
context:
space:
mode:
authorMelanie2012-11-17 02:03:24 +0000
committerMelanie2012-11-17 02:03:24 +0000
commite4659a83f15acc85a7207a1ff60460cae0b86b78 (patch)
treed0fc79b1cbdb15ce9296f05aacf696c9ad43bc41 /OpenSim/Framework/Monitoring
parentMerge branch 'master' into careminster (diff)
parentRemove old InventoryService, which has for a long time been replaced by XInve... (diff)
downloadopensim-SC_OLD-e4659a83f15acc85a7207a1ff60460cae0b86b78.zip
opensim-SC_OLD-e4659a83f15acc85a7207a1ff60460cae0b86b78.tar.gz
opensim-SC_OLD-e4659a83f15acc85a7207a1ff60460cae0b86b78.tar.bz2
opensim-SC_OLD-e4659a83f15acc85a7207a1ff60460cae0b86b78.tar.xz
Merge branch 'master' into careminster
Diffstat (limited to 'OpenSim/Framework/Monitoring')
-rw-r--r--OpenSim/Framework/Monitoring/Stats/PercentageStat.cs88
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs238
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs185
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs4
4 files changed, 358 insertions, 157 deletions
diff --git a/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
new file mode 100644
index 0000000..60bed55
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
@@ -0,0 +1,88 @@
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
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32namespace OpenSim.Framework.Monitoring
33{
34 public class PercentageStat : Stat
35 {
36 public long Antecedent { get; set; }
37 public long Consequent { get; set; }
38
39 public override double Value
40 {
41 get
42 {
43 // Asking for an update here means that the updater cannot access this value without infinite recursion.
44 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
45 // called by the pull action and just return the value.
46 if (StatType == StatType.Pull)
47 PullAction(this);
48
49 long c = Consequent;
50
51 // Avoid any chance of a multi-threaded divide-by-zero
52 if (c == 0)
53 return 0;
54
55 return (double)Antecedent / c * 100;
56 }
57
58 set
59 {
60 throw new InvalidOperationException("Cannot set value on a PercentageStat");
61 }
62 }
63
64 public PercentageStat(
65 string shortName,
66 string name,
67 string description,
68 string category,
69 string container,
70 StatType type,
71 Action<Stat> pullAction,
72 StatVerbosity verbosity)
73 : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {}
74
75 public override string ToConsoleString()
76 {
77 StringBuilder sb = new StringBuilder();
78
79 sb.AppendFormat(
80 "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})",
81 Category, Container, ShortName, Value, UnitName, Antecedent, Consequent);
82
83 AppendMeasuresOfInterest(sb);
84
85 return sb.ToString();
86 }
87 }
88} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
new file mode 100644
index 0000000..f91251b
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -0,0 +1,238 @@
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
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32namespace OpenSim.Framework.Monitoring
33{
34 /// <summary>
35 /// Holds individual statistic details
36 /// </summary>
37 public class Stat
38 {
39 /// <summary>
40 /// Category of this stat (e.g. cache, scene, etc).
41 /// </summary>
42 public string Category { get; private set; }
43
44 /// <summary>
45 /// Containing name for this stat.
46 /// FIXME: In the case of a scene, this is currently the scene name (though this leaves
47 /// us with a to-be-resolved problem of non-unique region names).
48 /// </summary>
49 /// <value>
50 /// The container.
51 /// </value>
52 public string Container { get; private set; }
53
54 public StatType StatType { get; private set; }
55
56 public MeasuresOfInterest MeasuresOfInterest { get; private set; }
57
58 /// <summary>
59 /// Action used to update this stat when the value is requested if it's a pull type.
60 /// </summary>
61 public Action<Stat> PullAction { get; private set; }
62
63 public StatVerbosity Verbosity { get; private set; }
64 public string ShortName { get; private set; }
65 public string Name { get; private set; }
66 public string Description { get; private set; }
67 public virtual string UnitName { get; private set; }
68
69 public virtual double Value
70 {
71 get
72 {
73 // Asking for an update here means that the updater cannot access this value without infinite recursion.
74 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
75 // called by the pull action and just return the value.
76 if (StatType == StatType.Pull)
77 PullAction(this);
78
79 return m_value;
80 }
81
82 set
83 {
84 m_value = value;
85 }
86 }
87
88 private double m_value;
89
90 /// <summary>
91 /// Historical samples for calculating measures of interest average.
92 /// </summary>
93 /// <remarks>
94 /// Will be null if no measures of interest require samples.
95 /// </remarks>
96 private static Queue<double> m_samples;
97
98 /// <summary>
99 /// Maximum number of statistical samples.
100 /// </summary>
101 /// <remarks>
102 /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from
103 /// the main Watchdog.
104 /// </remarks>
105 private static int m_maxSamples = 24;
106
107 public Stat(
108 string shortName,
109 string name,
110 string description,
111 string unitName,
112 string category,
113 string container,
114 StatType type,
115 Action<Stat> pullAction,
116 StatVerbosity verbosity)
117 : this(
118 shortName,
119 name,
120 description,
121 unitName,
122 category,
123 container,
124 type,
125 MeasuresOfInterest.None,
126 pullAction,
127 verbosity)
128 {
129 }
130
131 /// <summary>
132 /// Constructor
133 /// </summary>
134 /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param>
135 /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param>
136 /// <param name='description'>Description of stat</param>
137 /// <param name='unitName'>
138 /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
139 /// e.g. " frames"
140 /// </param>
141 /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param>
142 /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param>
143 /// <param name='type'>Push or pull</param>
144 /// <param name='pullAction'>Pull stats need an action to update the stat on request. Push stats should set null here.</param>
145 /// <param name='moi'>Measures of interest</param>
146 /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param>
147 public Stat(
148 string shortName,
149 string name,
150 string description,
151 string unitName,
152 string category,
153 string container,
154 StatType type,
155 MeasuresOfInterest moi,
156 Action<Stat> pullAction,
157 StatVerbosity verbosity)
158 {
159 if (StatsManager.SubCommands.Contains(category))
160 throw new Exception(
161 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
162
163 ShortName = shortName;
164 Name = name;
165 Description = description;
166 UnitName = unitName;
167 Category = category;
168 Container = container;
169 StatType = type;
170
171 if (StatType == StatType.Push && pullAction != null)
172 throw new Exception("A push stat cannot have a pull action");
173 else
174 PullAction = pullAction;
175
176 MeasuresOfInterest = moi;
177
178 if ((moi & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
179 m_samples = new Queue<double>(m_maxSamples);
180
181 Verbosity = verbosity;
182 }
183
184 /// <summary>
185 /// Record a value in the sample set.
186 /// </summary>
187 /// <remarks>
188 /// Do not call this if MeasuresOfInterest.None
189 /// </remarks>
190 public void RecordValue()
191 {
192 double newValue = Value;
193
194 lock (m_samples)
195 {
196 if (m_samples.Count >= m_maxSamples)
197 m_samples.Dequeue();
198
199 m_samples.Enqueue(newValue);
200 }
201 }
202
203 public virtual string ToConsoleString()
204 {
205 StringBuilder sb = new StringBuilder();
206 sb.AppendFormat("{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
207
208 AppendMeasuresOfInterest(sb);
209
210 return sb.ToString();
211 }
212
213 protected void AppendMeasuresOfInterest(StringBuilder sb)
214 {
215 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
216 == MeasuresOfInterest.AverageChangeOverTime)
217 {
218 double totalChange = 0;
219 double? lastSample = null;
220
221 lock (m_samples)
222 {
223 foreach (double s in m_samples)
224 {
225 if (lastSample != null)
226 totalChange += s - (double)lastSample;
227
228 lastSample = s;
229 }
230 }
231
232 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
233
234 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
235 }
236 }
237 }
238} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index cebe905..0762b01 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text;
30 31
31namespace OpenSim.Framework.Monitoring 32namespace OpenSim.Framework.Monitoring
32{ 33{
@@ -246,6 +247,24 @@ namespace OpenSim.Framework.Monitoring
246 247
247 return false; 248 return false;
248 } 249 }
250
251 public static void RecordStats()
252 {
253 lock (RegisteredStats)
254 {
255 foreach (Dictionary<string, Dictionary<string, Stat>> category in RegisteredStats.Values)
256 {
257 foreach (Dictionary<string, Stat> container in category.Values)
258 {
259 foreach (Stat stat in container.Values)
260 {
261 if (stat.MeasuresOfInterest != MeasuresOfInterest.None)
262 stat.RecordValue();
263 }
264 }
265 }
266 }
267 }
249 } 268 }
250 269
251 /// <summary> 270 /// <summary>
@@ -262,6 +281,16 @@ namespace OpenSim.Framework.Monitoring
262 } 281 }
263 282
264 /// <summary> 283 /// <summary>
284 /// Measures of interest for this stat.
285 /// </summary>
286 [Flags]
287 public enum MeasuresOfInterest
288 {
289 None,
290 AverageChangeOverTime
291 }
292
293 /// <summary>
265 /// Verbosity of stat. 294 /// Verbosity of stat.
266 /// </summary> 295 /// </summary>
267 /// <remarks> 296 /// <remarks>
@@ -272,160 +301,4 @@ namespace OpenSim.Framework.Monitoring
272 Debug, 301 Debug,
273 Info 302 Info
274 } 303 }
275
276 /// <summary>
277 /// Holds individual static details
278 /// </summary>
279 public class Stat
280 {
281 /// <summary>
282 /// Category of this stat (e.g. cache, scene, etc).
283 /// </summary>
284 public string Category { get; private set; }
285
286 /// <summary>
287 /// Containing name for this stat.
288 /// FIXME: In the case of a scene, this is currently the scene name (though this leaves
289 /// us with a to-be-resolved problem of non-unique region names).
290 /// </summary>
291 /// <value>
292 /// The container.
293 /// </value>
294 public string Container { get; private set; }
295
296 public StatType StatType { get; private set; }
297
298 /// <summary>
299 /// Action used to update this stat when the value is requested if it's a pull type.
300 /// </summary>
301 public Action<Stat> PullAction { get; private set; }
302
303 public StatVerbosity Verbosity { get; private set; }
304 public string ShortName { get; private set; }
305 public string Name { get; private set; }
306 public string Description { get; private set; }
307 public virtual string UnitName { get; private set; }
308
309 public virtual double Value
310 {
311 get
312 {
313 // Asking for an update here means that the updater cannot access this value without infinite recursion.
314 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
315 // called by the pull action and just return the value.
316 if (StatType == StatType.Pull)
317 PullAction(this);
318
319 return m_value;
320 }
321
322 set
323 {
324 m_value = value;
325 }
326 }
327
328 private double m_value;
329
330 /// <summary>
331 /// Constructor
332 /// </summary>
333 /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param>
334 /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param>
335 /// <param name='description'>Description of stat</param>
336 /// <param name='unitName'>
337 /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
338 /// e.g. " frames"
339 /// </param>
340 /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param>
341 /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param>
342 /// <param name='type'>Push or pull</param>
343 /// <param name='pullAction'>Pull stats need an action to update the stat on request. Push stats should set null here.</param>
344 /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param>
345 public Stat(
346 string shortName,
347 string name,
348 string description,
349 string unitName,
350 string category,
351 string container,
352 StatType type,
353 Action<Stat> pullAction,
354 StatVerbosity verbosity)
355 {
356 if (StatsManager.SubCommands.Contains(category))
357 throw new Exception(
358 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
359
360 ShortName = shortName;
361 Name = name;
362 Description = description;
363 UnitName = unitName;
364 Category = category;
365 Container = container;
366 StatType = type;
367
368 if (StatType == StatType.Push && pullAction != null)
369 throw new Exception("A push stat cannot have a pull action");
370 else
371 PullAction = pullAction;
372
373 Verbosity = verbosity;
374 }
375
376 public virtual string ToConsoleString()
377 {
378 return string.Format(
379 "{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
380 }
381 }
382
383 public class PercentageStat : Stat
384 {
385 public long Antecedent { get; set; }
386 public long Consequent { get; set; }
387
388 public override double Value
389 {
390 get
391 {
392 // Asking for an update here means that the updater cannot access this value without infinite recursion.
393 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
394 // called by the pull action and just return the value.
395 if (StatType == StatType.Pull)
396 PullAction(this);
397
398 long c = Consequent;
399
400 // Avoid any chance of a multi-threaded divide-by-zero
401 if (c == 0)
402 return 0;
403
404 return (double)Antecedent / c * 100;
405 }
406
407 set
408 {
409 throw new InvalidOperationException("Cannot set value on a PercentageStat");
410 }
411 }
412
413 public PercentageStat(
414 string shortName,
415 string name,
416 string description,
417 string category,
418 string container,
419 StatType type,
420 Action<Stat> pullAction,
421 StatVerbosity verbosity)
422 : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {}
423
424 public override string ToConsoleString()
425 {
426 return string.Format(
427 "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})",
428 Category, Container, ShortName, Value, UnitName, Antecedent, Consequent);
429 }
430 }
431} \ No newline at end of file 304} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 28d6d5c..69d2db5 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Monitoring
39 public static class Watchdog 39 public static class Watchdog
40 { 40 {
41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary> 41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary>
42 const double WATCHDOG_INTERVAL_MS = 2500.0d; 42 public const double WATCHDOG_INTERVAL_MS = 2500.0d;
43 43
44 /// <summary>Default timeout in milliseconds before a thread is considered dead</summary> 44 /// <summary>Default timeout in milliseconds before a thread is considered dead</summary>
45 public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000; 45 public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000;
@@ -380,6 +380,8 @@ namespace OpenSim.Framework.Monitoring
380 if (MemoryWatchdog.Enabled) 380 if (MemoryWatchdog.Enabled)
381 MemoryWatchdog.Update(); 381 MemoryWatchdog.Update();
382 382
383 StatsManager.RecordStats();
384
383 m_watchdogTimer.Start(); 385 m_watchdogTimer.Start();
384 } 386 }
385 } 387 }