aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs139
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs1
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
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>
@@ -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 }