diff options
-rw-r--r-- | OpenSim/Framework/Monitoring/StatsManager.cs | 139 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/Watchdog.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 1 |
3 files changed, 140 insertions, 4 deletions
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index cebe905..eae7505 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Text; | ||
30 | 31 | ||
31 | namespace OpenSim.Framework.Monitoring | 32 | namespace 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> |
@@ -295,6 +324,8 @@ namespace OpenSim.Framework.Monitoring | |||
295 | 324 | ||
296 | public StatType StatType { get; private set; } | 325 | public StatType StatType { get; private set; } |
297 | 326 | ||
327 | public MeasuresOfInterest MeasuresOfInterest { get; private set; } | ||
328 | |||
298 | /// <summary> | 329 | /// <summary> |
299 | /// Action used to update this stat when the value is requested if it's a pull type. | 330 | /// Action used to update this stat when the value is requested if it's a pull type. |
300 | /// </summary> | 331 | /// </summary> |
@@ -328,6 +359,47 @@ namespace OpenSim.Framework.Monitoring | |||
328 | private double m_value; | 359 | private double m_value; |
329 | 360 | ||
330 | /// <summary> | 361 | /// <summary> |
362 | /// Historical samples for calculating measures of interest average. | ||
363 | /// </summary> | ||
364 | /// <remarks> | ||
365 | /// Will be null if no measures of interest require samples. | ||
366 | /// </remarks> | ||
367 | private static Queue<double> m_samples; | ||
368 | |||
369 | /// <summary> | ||
370 | /// Maximum number of statistical samples. | ||
371 | /// </summary> | ||
372 | /// <remarks> | ||
373 | /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from | ||
374 | /// the main Watchdog. | ||
375 | /// </remarks> | ||
376 | private static int m_maxSamples = 24; | ||
377 | |||
378 | public Stat( | ||
379 | string shortName, | ||
380 | string name, | ||
381 | string description, | ||
382 | string unitName, | ||
383 | string category, | ||
384 | string container, | ||
385 | StatType type, | ||
386 | Action<Stat> pullAction, | ||
387 | StatVerbosity verbosity) | ||
388 | : this( | ||
389 | shortName, | ||
390 | name, | ||
391 | description, | ||
392 | unitName, | ||
393 | category, | ||
394 | container, | ||
395 | type, | ||
396 | MeasuresOfInterest.None, | ||
397 | pullAction, | ||
398 | verbosity) | ||
399 | { | ||
400 | } | ||
401 | |||
402 | /// <summary> | ||
331 | /// Constructor | 403 | /// Constructor |
332 | /// </summary> | 404 | /// </summary> |
333 | /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param> | 405 | /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param> |
@@ -341,6 +413,7 @@ namespace OpenSim.Framework.Monitoring | |||
341 | /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param> | 413 | /// <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> | 414 | /// <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> | 415 | /// <param name='pullAction'>Pull stats need an action to update the stat on request. Push stats should set null here.</param> |
416 | /// <param name='moi'>Measures of interest</param> | ||
344 | /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param> | 417 | /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param> |
345 | public Stat( | 418 | public Stat( |
346 | string shortName, | 419 | string shortName, |
@@ -350,6 +423,7 @@ namespace OpenSim.Framework.Monitoring | |||
350 | string category, | 423 | string category, |
351 | string container, | 424 | string container, |
352 | StatType type, | 425 | StatType type, |
426 | MeasuresOfInterest moi, | ||
353 | Action<Stat> pullAction, | 427 | Action<Stat> pullAction, |
354 | StatVerbosity verbosity) | 428 | StatVerbosity verbosity) |
355 | { | 429 | { |
@@ -370,13 +444,66 @@ namespace OpenSim.Framework.Monitoring | |||
370 | else | 444 | else |
371 | PullAction = pullAction; | 445 | PullAction = pullAction; |
372 | 446 | ||
447 | MeasuresOfInterest = moi; | ||
448 | |||
449 | if ((moi & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime) | ||
450 | m_samples = new Queue<double>(m_maxSamples); | ||
451 | |||
373 | Verbosity = verbosity; | 452 | Verbosity = verbosity; |
374 | } | 453 | } |
375 | 454 | ||
455 | /// <summary> | ||
456 | /// Record a value in the sample set. | ||
457 | /// </summary> | ||
458 | /// <remarks> | ||
459 | /// Do not call this if MeasuresOfInterest.None | ||
460 | /// </remarks> | ||
461 | public void RecordValue() | ||
462 | { | ||
463 | double newValue = Value; | ||
464 | |||
465 | lock (m_samples) | ||
466 | { | ||
467 | if (m_samples.Count >= m_maxSamples) | ||
468 | m_samples.Dequeue(); | ||
469 | |||
470 | m_samples.Enqueue(newValue); | ||
471 | } | ||
472 | } | ||
473 | |||
376 | public virtual string ToConsoleString() | 474 | public virtual string ToConsoleString() |
377 | { | 475 | { |
378 | return string.Format( | 476 | StringBuilder sb = new StringBuilder(); |
379 | "{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName); | 477 | sb.AppendFormat("{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName); |
478 | |||
479 | AppendMeasuresOfInterest(sb); | ||
480 | |||
481 | return sb.ToString(); | ||
482 | } | ||
483 | |||
484 | protected void AppendMeasuresOfInterest(StringBuilder sb) | ||
485 | { | ||
486 | if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) | ||
487 | == MeasuresOfInterest.AverageChangeOverTime) | ||
488 | { | ||
489 | double totalChange = 0; | ||
490 | double? lastSample = null; | ||
491 | |||
492 | lock (m_samples) | ||
493 | { | ||
494 | foreach (double s in m_samples) | ||
495 | { | ||
496 | if (lastSample != null) | ||
497 | totalChange += s - (double)lastSample; | ||
498 | |||
499 | lastSample = s; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; | ||
504 | |||
505 | sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); | ||
506 | } | ||
380 | } | 507 | } |
381 | } | 508 | } |
382 | 509 | ||
@@ -423,9 +550,15 @@ namespace OpenSim.Framework.Monitoring | |||
423 | 550 | ||
424 | public override string ToConsoleString() | 551 | public override string ToConsoleString() |
425 | { | 552 | { |
426 | return string.Format( | 553 | StringBuilder sb = new StringBuilder(); |
554 | |||
555 | sb.AppendFormat( | ||
427 | "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})", | 556 | "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})", |
428 | Category, Container, ShortName, Value, UnitName, Antecedent, Consequent); | 557 | Category, Container, ShortName, Value, UnitName, Antecedent, Consequent); |
558 | |||
559 | AppendMeasuresOfInterest(sb); | ||
560 | |||
561 | return sb.ToString(); | ||
429 | } | 562 | } |
430 | } | 563 | } |
431 | } \ No newline at end of file | 564 | } \ No newline at end of file |
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index a20326d..3f992b1 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 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index fcc69c0..a7628d2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -80,6 +80,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
80 | "clientstack", | 80 | "clientstack", |
81 | scene.Name, | 81 | scene.Name, |
82 | StatType.Pull, | 82 | StatType.Pull, |
83 | MeasuresOfInterest.AverageChangeOverTime, | ||
83 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, | 84 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, |
84 | StatVerbosity.Debug)); | 85 | StatVerbosity.Debug)); |
85 | } | 86 | } |