Stats Manager

=Introduction= The OpenSimulator stats manager system is the most modern stats implementation in OpenSimulator and will eventually replace all legacy systems. It allows statistics to be added, updated and removed at runtime. Statistics can be viewed via the console "show stats" command and recorded periodically to file for later analysis.

'''For information on the mechanisms for viewing and recording stats from the console and the web please see the Show stats page. This also has some information on the stats themselves.'''

=General Concepts= StatsManager acts as the interface between code that have statistics and modules that want to access and display those statistics. At startup, code register their statistics with StatsManager. Then, any code that wishes to access the statistics (whether to display them on the console, put them in databases, or make them available over the network) requests the values from StatsManager. This architecture allows multiple statistic display and analysis systems while also removing the burden of code instrumentation from the display systems. Also, once code is instrumented and registering statistics, those statistics are available to all display systems.

At initialization, code registers its statistics with StatsManager. The full name of a stat has three components, separated by periods (.). In order, these are


 * category - The category of the stat (e.g. server, scene)
 * container - The containing object for this stat. For example, on scene this is the scene name (e.g. region 1).  For server, this is the component to which the stat relates (e.g. memory, processor).
 * name - The stat itself. For example, ClientLogoutsDueToNoReceives or SimFPS.

Full names must be unique.

Registered statistics are generally of two types:
 * pull - the value of the statistic is "pulled" when the value is requested (using a closure to access the true value location); and
 * push - the value is periodically stored in the statistic by the monitored code. There are two types of "push" statistics - the kind that just store a value and those that record events.

In the namespace Opensim.Framework.Monitoring, there is the basic Stats class (invocation described below) that provides the basic push or pull statistic. There is also a CounterStat class designed for routines that want to track events. CounterStats can have EventHistogram classes added to keep histograms of events over time. This latter feature is good for tracking statistics that can change more quickly than any external sampling.

= Programmatic Interface =

Creating a stat
A statistic is represented by an instance of the OpenSim.Framework.Monitoring.Stat class or one of its descendant classes. Here's an example that creates a stat for recording all the HTTP requests served by the webserver embedded in OpenSimulator.

This breaks down as follows


 * HTTPRequestsServed - The short name of this stat. This is the name used when the stat is displayed or recorded.
 * Number of inbound HTTP requests processed - The full name of this stat.
 * The number of inbound HTTP requests processed by the builtin HTTP server. - A description of this stat.
 * requests - The unit name for this stat.
 * httpserver - The category for this stat.
 * container - The container for this stat within the category. In this case, we use the port number as the "container" since this distinguishes this data from similar stats on other ports.  Another example of a distinguishing container is the region name.
 * StatType.Pull - The statistic type. This is either Pull or Push.  If Pull, then when a stat is required (e.g. if the user requests the information or it needs to be recorded), then it is gathered by the given pullAction (of which more below).  If a statistic if push, then the pull action is null (or will be ignored) and the code registering the stat is responsible for updating the value directly on an ongoing basis.
 * MeasuresOfInterest.AverageChangeOverTime - This can be None or ChangeOverTime. If None, then only the raw stat is recorded.  If ChangeOverTime, then StatsManager also derives the moving average over the last 24 samples.
 * stat => stat.Value = RequestNumber - This is the anonymous function used to generate the stat on a pull request. In this case, the RequestNumber within the HTTP management code is inserted into the stat value.
 * StatVerbosity.Debug - StatVerbosity can be Debug or Info. Info should be used for stats that the user will always be interested in seeing (e.g. number of users on a region) and Debug for debugging stats (such as HTTP requests served).  However, right now stat display is not filtered on verbosity.

Registering a stat
A created stat must then be registered with the StatsManager. In the case of our example above, this is done as follows.

Deregistering a stat
If your code is never disabled during runtime then you don't need to worry about deregistering the stat. However, if it can be removed (e.g. because it is in a region module) then you can deregister a stat as follows.

Fetching stats
There are several interfaces for fetching stats. The easiest is: which accepts the name of a category, container, and the short version of the stat name and returns the statistic. Null is returned if the stat is not found.

There are also methods to return all of the stats within a category (TryGetStatsForCategory) and within a container (GetStatsForEachContainer).