From 55f889cc66d78268c530c65a5fd111395cc26dc5 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Fri, 16 Nov 2012 05:02:06 +0000
Subject: refactor: Move stat classes out of StatManager and into their own
files for clarity.
---
OpenSim/Framework/Monitoring/Stats/Stat.cs | 238 +++++++++++++++++++++++++++++
1 file changed, 238 insertions(+)
create mode 100644 OpenSim/Framework/Monitoring/Stats/Stat.cs
(limited to 'OpenSim/Framework/Monitoring/Stats/Stat.cs')
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 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenSim.Framework.Monitoring
+{
+ ///
+ /// Holds individual statistic details
+ ///
+ public class Stat
+ {
+ ///
+ /// Category of this stat (e.g. cache, scene, etc).
+ ///
+ public string Category { get; private set; }
+
+ ///
+ /// Containing name for this stat.
+ /// FIXME: In the case of a scene, this is currently the scene name (though this leaves
+ /// us with a to-be-resolved problem of non-unique region names).
+ ///
+ ///
+ /// The container.
+ ///
+ public string Container { get; private set; }
+
+ public StatType StatType { get; private set; }
+
+ public MeasuresOfInterest MeasuresOfInterest { get; private set; }
+
+ ///
+ /// Action used to update this stat when the value is requested if it's a pull type.
+ ///
+ public Action PullAction { get; private set; }
+
+ public StatVerbosity Verbosity { get; private set; }
+ public string ShortName { get; private set; }
+ public string Name { get; private set; }
+ public string Description { get; private set; }
+ public virtual string UnitName { get; private set; }
+
+ public virtual double Value
+ {
+ get
+ {
+ // Asking for an update here means that the updater cannot access this value without infinite recursion.
+ // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
+ // called by the pull action and just return the value.
+ if (StatType == StatType.Pull)
+ PullAction(this);
+
+ return m_value;
+ }
+
+ set
+ {
+ m_value = value;
+ }
+ }
+
+ private double m_value;
+
+ ///
+ /// Historical samples for calculating measures of interest average.
+ ///
+ ///
+ /// Will be null if no measures of interest require samples.
+ ///
+ private static Queue m_samples;
+
+ ///
+ /// Maximum number of statistical samples.
+ ///
+ ///
+ /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from
+ /// the main Watchdog.
+ ///
+ private static int m_maxSamples = 24;
+
+ public Stat(
+ string shortName,
+ string name,
+ string description,
+ string unitName,
+ string category,
+ string container,
+ StatType type,
+ Action pullAction,
+ StatVerbosity verbosity)
+ : this(
+ shortName,
+ name,
+ description,
+ unitName,
+ category,
+ container,
+ type,
+ MeasuresOfInterest.None,
+ pullAction,
+ verbosity)
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Short name for the stat. Must not contain spaces. e.g. "LongFrames"
+ /// Human readable name for the stat. e.g. "Long frames"
+ /// Description of stat
+ ///
+ /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
+ /// e.g. " frames"
+ ///
+ /// Category under which this stat should appear, e.g. "scene". Do not capitalize.
+ /// Entity to which this stat relates. e.g. scene name if this is a per scene stat.
+ /// Push or pull
+ /// Pull stats need an action to update the stat on request. Push stats should set null here.
+ /// Measures of interest
+ /// Verbosity of stat. Controls whether it will appear in short stat display or only full display.
+ public Stat(
+ string shortName,
+ string name,
+ string description,
+ string unitName,
+ string category,
+ string container,
+ StatType type,
+ MeasuresOfInterest moi,
+ Action pullAction,
+ StatVerbosity verbosity)
+ {
+ if (StatsManager.SubCommands.Contains(category))
+ throw new Exception(
+ string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
+
+ ShortName = shortName;
+ Name = name;
+ Description = description;
+ UnitName = unitName;
+ Category = category;
+ Container = container;
+ StatType = type;
+
+ if (StatType == StatType.Push && pullAction != null)
+ throw new Exception("A push stat cannot have a pull action");
+ else
+ PullAction = pullAction;
+
+ MeasuresOfInterest = moi;
+
+ if ((moi & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
+ m_samples = new Queue(m_maxSamples);
+
+ Verbosity = verbosity;
+ }
+
+ ///
+ /// Record a value in the sample set.
+ ///
+ ///
+ /// Do not call this if MeasuresOfInterest.None
+ ///
+ public void RecordValue()
+ {
+ double newValue = Value;
+
+ lock (m_samples)
+ {
+ if (m_samples.Count >= m_maxSamples)
+ m_samples.Dequeue();
+
+ m_samples.Enqueue(newValue);
+ }
+ }
+
+ public virtual string ToConsoleString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
+
+ AppendMeasuresOfInterest(sb);
+
+ return sb.ToString();
+ }
+
+ protected void AppendMeasuresOfInterest(StringBuilder sb)
+ {
+ if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
+ == MeasuresOfInterest.AverageChangeOverTime)
+ {
+ double totalChange = 0;
+ double? lastSample = null;
+
+ lock (m_samples)
+ {
+ foreach (double s in m_samples)
+ {
+ if (lastSample != null)
+ totalChange += s - (double)lastSample;
+
+ lastSample = s;
+ }
+ }
+
+ int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
+
+ sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
+ }
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.1