aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring
diff options
context:
space:
mode:
authorubit2013-04-28 20:40:11 +0200
committerubit2013-04-28 20:40:11 +0200
commit61ea7ee5a94e5e3d33fc77c1c316318850309c42 (patch)
tree1e589fc3b448b580d1cc25b52215ef5ce2d7ae78 /OpenSim/Framework/Monitoring
parentMerge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork (diff)
parentController module for dynamic floaters (WIP) (diff)
downloadopensim-SC_OLD-61ea7ee5a94e5e3d33fc77c1c316318850309c42.zip
opensim-SC_OLD-61ea7ee5a94e5e3d33fc77c1c316318850309c42.tar.gz
opensim-SC_OLD-61ea7ee5a94e5e3d33fc77c1c316318850309c42.tar.bz2
opensim-SC_OLD-61ea7ee5a94e5e3d33fc77c1c316318850309c42.tar.xz
Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork
Conflicts: bin/Regions/Regions.ini.example
Diffstat (limited to 'OpenSim/Framework/Monitoring')
-rw-r--r--OpenSim/Framework/Monitoring/AssetStatsCollector.cs26
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs7
-rw-r--r--OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs9
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs29
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs228
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs26
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs69
-rw-r--r--OpenSim/Framework/Monitoring/UserStatsCollector.cs18
9 files changed, 380 insertions, 36 deletions
diff --git a/OpenSim/Framework/Monitoring/AssetStatsCollector.cs b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
index 2a4d45b..6a0f676 100644
--- a/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Timers; 29using System.Timers;
30 30
31using OpenMetaverse.StructuredData;
32
31namespace OpenSim.Framework.Monitoring 33namespace OpenSim.Framework.Monitoring
32{ 34{
33 /// <summary> 35 /// <summary>
@@ -100,5 +102,29 @@ Asset requests yesterday : {3} ({4} per hour) of which {5} were not found",
100 AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, 102 AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday,
101 AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); 103 AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday);
102 } 104 }
105
106 public override string XReport(string uptime, string version)
107 {
108 return OSDParser.SerializeJsonString(OReport(uptime, version));
109 }
110
111 public override OSDMap OReport(string uptime, string version)
112 {
113 double elapsedHours = (DateTime.Now - startTime).TotalHours;
114 if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero
115
116 long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours);
117 long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0);
118
119 OSDMap ret = new OSDMap();
120 ret.Add("AssetRequestsToday", OSD.FromLong(AssetRequestsToday));
121 ret.Add("AssetRequestsTodayPerHour", OSD.FromLong(assetRequestsTodayPerHour));
122 ret.Add("AssetRequestsNotFoundToday", OSD.FromLong(AssetRequestsNotFoundToday));
123 ret.Add("AssetRequestsYesterday", OSD.FromLong(AssetRequestsYesterday));
124 ret.Add("AssetRequestsYesterdayPerHour", OSD.FromLong(assetRequestsYesterdayPerHour));
125 ret.Add("AssetRequestsNotFoundYesterday", OSD.FromLong(assetRequestsNotFoundYesterday));
126
127 return ret;
128 }
103 } 129 }
104} 130}
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 446e3c0..23dba09 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -80,5 +80,12 @@ namespace OpenSim.Framework.Monitoring
80 { 80 {
81 return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; 81 return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ;
82 } 82 }
83
84 public virtual OSDMap OReport(string uptime, string version)
85 {
86 OSDMap ret = new OSDMap();
87 ret.Add("TotalMemory", new OSDReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
88 return ret;
89 }
83 } 90 }
84} 91}
diff --git a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
index 99f75e3..40df562 100644
--- a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
@@ -25,6 +25,8 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenMetaverse.StructuredData;
29
28namespace OpenSim.Framework.Monitoring 30namespace OpenSim.Framework.Monitoring
29{ 31{
30 /// <summary> 32 /// <summary>
@@ -45,5 +47,12 @@ namespace OpenSim.Framework.Monitoring
45 /// A <see cref="System.String"/> 47 /// A <see cref="System.String"/>
46 /// </returns> 48 /// </returns>
47 string XReport(string uptime, string version); 49 string XReport(string uptime, string version);
50
51 /// <summary>
52 /// Report back collected statistical information as an OSDMap of key/values
53 /// </summary>
54 /// <returns>
55 /// </returns>
56 OSDMap OReport(string uptime, string version);
48 } 57 }
49} 58}
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index 1f2bb40..36678bb 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index aa86202..6a68322 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -359,11 +359,12 @@ Asset service request failures: {3}" + Environment.NewLine,
359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, 359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); 360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
361 361
362 Dictionary<string, Dictionary<string, Stat>> sceneStats; 362 /* 20130319 RA: For the moment, disable the dump of 'scene' catagory as they are mostly output by
363 363 * the two formatted printouts above.
364 SortedDictionary<string, SortedDictionary<string, Stat>> sceneStats;
364 if (StatsManager.TryGetStats("scene", out sceneStats)) 365 if (StatsManager.TryGetStats("scene", out sceneStats))
365 { 366 {
366 foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats) 367 foreach (KeyValuePair<string, SortedDictionary<string, Stat>> kvp in sceneStats)
367 { 368 {
368 foreach (Stat stat in kvp.Value.Values) 369 foreach (Stat stat in kvp.Value.Values)
369 { 370 {
@@ -374,6 +375,7 @@ Asset service request failures: {3}" + Environment.NewLine,
374 } 375 }
375 } 376 }
376 } 377 }
378 */
377 379
378 /* 380 /*
379 sb.Append(Environment.NewLine); 381 sb.Append(Environment.NewLine);
@@ -405,6 +407,15 @@ Asset service request failures: {3}" + Environment.NewLine,
405 /// <returns></returns> 407 /// <returns></returns>
406 public override string XReport(string uptime, string version) 408 public override string XReport(string uptime, string version)
407 { 409 {
410 return OSDParser.SerializeJsonString(OReport(uptime, version));
411 }
412
413 /// <summary>
414 /// Report back collected statistical information as an OSDMap
415 /// </summary>
416 /// <returns></returns>
417 public override OSDMap OReport(string uptime, string version)
418 {
408 OSDMap args = new OSDMap(30); 419 OSDMap args = new OSDMap(30);
409// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); 420// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache));
410// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", 421// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}",
@@ -442,13 +453,11 @@ Asset service request failures: {3}" + Environment.NewLine,
442 args["Uptime"] = OSD.FromString (uptime); 453 args["Uptime"] = OSD.FromString (uptime);
443 args["Version"] = OSD.FromString (version); 454 args["Version"] = OSD.FromString (version);
444 455
445 string strBuffer = ""; 456 return args;
446 strBuffer = OSDParser.SerializeJsonString(args);
447
448 return strBuffer;
449 } 457 }
450 } 458 }
451 459
460
452 /// <summary> 461 /// <summary>
453 /// Pull packet queue stats from packet queues and report 462 /// Pull packet queue stats from packet queues and report
454 /// </summary> 463 /// </summary>
@@ -474,5 +483,11 @@ Asset service request failures: {3}" + Environment.NewLine,
474 { 483 {
475 return ""; 484 return "";
476 } 485 }
486
487 public OSDMap OReport(string uptime, string version)
488 {
489 OSDMap ret = new OSDMap();
490 return ret;
491 }
477 } 492 }
478} 493}
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
new file mode 100755
index 0000000..caea30d
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
@@ -0,0 +1,228 @@
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.Linq;
31using System.Text;
32
33using OpenMetaverse.StructuredData;
34
35namespace OpenSim.Framework.Monitoring
36{
37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000)
41public class EventHistogram
42{
43 private int m_timeBase;
44 private int m_numBuckets;
45 private int m_bucketMilliseconds;
46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram;
49 private object histoLock = new object();
50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 {
53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56
57 m_histogram = new long[m_numBuckets];
58 Zero();
59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount();
61 }
62
63 public void Event()
64 {
65 this.Event(1);
66 }
67
68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt)
70 {
71 lock (histoLock)
72 {
73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75
76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds)
78 {
79 Zero();
80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount();
82 }
83 else
84 {
85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds;
87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket)
90 {
91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 {
94 m_histogram[jj] = 0;
95 }
96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets)
99 {
100 bucket -= m_numBuckets;
101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds;
104 }
105 }
106 }
107 m_histogram[m_lastBucket] += cnt;
108 }
109 }
110
111 // Get a copy of the current histogram
112 public long[] GetHistogram()
113 {
114 long[] ret = new long[m_numBuckets];
115 lock (histoLock)
116 {
117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 {
120 if (indx >= m_numBuckets)
121 indx = 0;
122 ret[ii] = m_histogram[indx];
123 }
124 }
125 return ret;
126 }
127
128 public OSDMap GetHistogramAsOSDMap()
129 {
130 OSDMap ret = new OSDMap();
131
132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135
136 // Compute a number for the first bucket in the histogram.
137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140
141 ret.Add("Values", GetHistogramAsOSDArray());
142
143 return ret;
144 }
145 // Get a copy of the current histogram
146 public OSDArray GetHistogramAsOSDArray()
147 {
148 OSDArray ret = new OSDArray(m_numBuckets);
149 lock (histoLock)
150 {
151 int indx = m_lastBucket + 1;
152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 {
154 if (indx >= m_numBuckets)
155 indx = 0;
156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157 }
158 }
159 return ret;
160 }
161
162 // Zero out the histogram
163 public void Zero()
164 {
165 lock (histoLock)
166 {
167 for (int ii = 0; ii < m_numBuckets; ii++)
168 m_histogram[ii] = 0;
169 }
170 }
171}
172
173// A statistic that wraps a counter.
174// Built this way mostly so histograms and history can be created.
175public class CounterStat : Stat
176{
177 private SortedDictionary<string, EventHistogram> m_histograms;
178 private object counterLock = new object();
179
180 public CounterStat(
181 string shortName,
182 string name,
183 string description,
184 string unitName,
185 string category,
186 string container,
187 StatVerbosity verbosity)
188 : base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity)
189 {
190 m_histograms = new SortedDictionary<string, EventHistogram>();
191 }
192
193 // Histograms are presumably added at intialization time and the list does not change thereafter.
194 // Thus no locking of the histogram list.
195 public void AddHistogram(string histoName, EventHistogram histo)
196 {
197 m_histograms.Add(histoName, histo);
198 }
199
200 public delegate void ProcessHistogram(string name, EventHistogram histo);
201 public void ForEachHistogram(ProcessHistogram process)
202 {
203 foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms)
204 {
205 process(kvp.Key, kvp.Value);
206 }
207 }
208
209 public void Event()
210 {
211 this.Event(1);
212 }
213
214 // Count the underlying counter.
215 public void Event(int cnt)
216 {
217 lock (counterLock)
218 {
219 base.Value += cnt;
220
221 foreach (EventHistogram histo in m_histograms.Values)
222 {
223 histo.Event(cnt);
224 }
225 }
226 }
227}
228}
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index f91251b..2e7665f 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -29,12 +29,14 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenMetaverse.StructuredData;
33
32namespace OpenSim.Framework.Monitoring 34namespace OpenSim.Framework.Monitoring
33{ 35{
34 /// <summary> 36 /// <summary>
35 /// Holds individual statistic details 37 /// Holds individual statistic details
36 /// </summary> 38 /// </summary>
37 public class Stat 39 public class Stat : IDisposable
38 { 40 {
39 /// <summary> 41 /// <summary>
40 /// Category of this stat (e.g. cache, scene, etc). 42 /// Category of this stat (e.g. cache, scene, etc).
@@ -181,6 +183,12 @@ namespace OpenSim.Framework.Monitoring
181 Verbosity = verbosity; 183 Verbosity = verbosity;
182 } 184 }
183 185
186 // IDisposable.Dispose()
187 public virtual void Dispose()
188 {
189 return;
190 }
191
184 /// <summary> 192 /// <summary>
185 /// Record a value in the sample set. 193 /// Record a value in the sample set.
186 /// </summary> 194 /// </summary>
@@ -203,13 +211,27 @@ namespace OpenSim.Framework.Monitoring
203 public virtual string ToConsoleString() 211 public virtual string ToConsoleString()
204 { 212 {
205 StringBuilder sb = new StringBuilder(); 213 StringBuilder sb = new StringBuilder();
206 sb.AppendFormat("{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName); 214 sb.AppendFormat("{0}.{1}.{2} : {3} {4}", Category, Container, ShortName, Value, UnitName);
207 215
208 AppendMeasuresOfInterest(sb); 216 AppendMeasuresOfInterest(sb);
209 217
210 return sb.ToString(); 218 return sb.ToString();
211 } 219 }
212 220
221 public virtual OSDMap ToOSDMap()
222 {
223 OSDMap ret = new OSDMap();
224 ret.Add("Category", OSD.FromString(Category));
225 ret.Add("Container", OSD.FromString(Container));
226 ret.Add("ShortName", OSD.FromString(ShortName));
227 ret.Add("Name", OSD.FromString(Name));
228 ret.Add("Description", OSD.FromString(Description));
229 ret.Add("UnitName", OSD.FromString(UnitName));
230 ret.Add("Value", OSD.FromReal(Value));
231
232 return ret;
233 }
234
213 protected void AppendMeasuresOfInterest(StringBuilder sb) 235 protected void AppendMeasuresOfInterest(StringBuilder sb)
214 { 236 {
215 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) 237 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 0762b01..24db6d4 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -51,8 +51,8 @@ namespace OpenSim.Framework.Monitoring
51 /// <remarks> 51 /// <remarks>
52 /// Do not add or remove directly from this dictionary. 52 /// Do not add or remove directly from this dictionary.
53 /// </remarks> 53 /// </remarks>
54 public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats 54 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>(); 55 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
56 56
57 private static AssetStatsCollector assetStats; 57 private static AssetStatsCollector assetStats;
58 private static UserStatsCollector userStats; 58 private static UserStatsCollector userStats;
@@ -85,6 +85,7 @@ namespace OpenSim.Framework.Monitoring
85 if (cmd.Length > 2) 85 if (cmd.Length > 2)
86 { 86 {
87 var categoryName = cmd[2]; 87 var categoryName = cmd[2];
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
88 89
89 if (categoryName == AllSubCommand) 90 if (categoryName == AllSubCommand)
90 { 91 {
@@ -101,14 +102,27 @@ namespace OpenSim.Framework.Monitoring
101 } 102 }
102 else 103 else
103 { 104 {
104 Dictionary<string, Dictionary<string, Stat>> category; 105 SortedDictionary<string, SortedDictionary<string, Stat>> category;
105 if (!RegisteredStats.TryGetValue(categoryName, out category)) 106 if (!RegisteredStats.TryGetValue(categoryName, out category))
106 { 107 {
107 con.OutputFormat("No such category as {0}", categoryName); 108 con.OutputFormat("No such category as {0}", categoryName);
108 } 109 }
109 else 110 else
110 { 111 {
111 OutputCategoryStatsToConsole(con, category); 112 if (String.IsNullOrEmpty(containerName))
113 OutputCategoryStatsToConsole(con, category);
114 else
115 {
116 SortedDictionary<string, Stat> container;
117 if (category.TryGetValue(containerName, out container))
118 {
119 OutputContainerStatsToConsole(con, container);
120 }
121 else
122 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
124 }
125 }
112 } 126 }
113 } 127 }
114 } 128 }
@@ -120,14 +134,19 @@ namespace OpenSim.Framework.Monitoring
120 } 134 }
121 135
122 private static void OutputCategoryStatsToConsole( 136 private static void OutputCategoryStatsToConsole(
123 ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category) 137 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
124 { 138 {
125 foreach (var container in category.Values) 139 foreach (var container in category.Values)
126 { 140 {
127 foreach (Stat stat in container.Values) 141 OutputContainerStatsToConsole(con, container);
128 { 142 }
129 con.Output(stat.ToConsoleString()); 143 }
130 } 144
145 private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container)
146 {
147 foreach (Stat stat in container.Values)
148 {
149 con.Output(stat.ToConsoleString());
131 } 150 }
132 } 151 }
133 152
@@ -160,8 +179,8 @@ namespace OpenSim.Framework.Monitoring
160 /// <returns></returns> 179 /// <returns></returns>
161 public static bool RegisterStat(Stat stat) 180 public static bool RegisterStat(Stat stat)
162 { 181 {
163 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; 182 SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory;
164 Dictionary<string, Stat> container = null, newContainer; 183 SortedDictionary<string, Stat> container = null, newContainer;
165 184
166 lock (RegisteredStats) 185 lock (RegisteredStats)
167 { 186 {
@@ -175,14 +194,14 @@ namespace OpenSim.Framework.Monitoring
175 // This means that we don't need to lock or copy them on iteration, which will be a much more 194 // This means that we don't need to lock or copy them on iteration, which will be a much more
176 // common operation after startup. 195 // common operation after startup.
177 if (container != null) 196 if (container != null)
178 newContainer = new Dictionary<string, Stat>(container); 197 newContainer = new SortedDictionary<string, Stat>(container);
179 else 198 else
180 newContainer = new Dictionary<string, Stat>(); 199 newContainer = new SortedDictionary<string, Stat>();
181 200
182 if (category != null) 201 if (category != null)
183 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); 202 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category);
184 else 203 else
185 newCategory = new Dictionary<string, Dictionary<string, Stat>>(); 204 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>();
186 205
187 newContainer[stat.ShortName] = stat; 206 newContainer[stat.ShortName] = stat;
188 newCategory[stat.Container] = newContainer; 207 newCategory[stat.Container] = newContainer;
@@ -196,21 +215,21 @@ namespace OpenSim.Framework.Monitoring
196 /// Deregister a statistic 215 /// Deregister a statistic
197 /// </summary>> 216 /// </summary>>
198 /// <param name='stat'></param> 217 /// <param name='stat'></param>
199 /// <returns></returns 218 /// <returns></returns>
200 public static bool DeregisterStat(Stat stat) 219 public static bool DeregisterStat(Stat stat)
201 { 220 {
202 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; 221 SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory;
203 Dictionary<string, Stat> container = null, newContainer; 222 SortedDictionary<string, Stat> container = null, newContainer;
204 223
205 lock (RegisteredStats) 224 lock (RegisteredStats)
206 { 225 {
207 if (!TryGetStat(stat, out category, out container)) 226 if (!TryGetStat(stat, out category, out container))
208 return false; 227 return false;
209 228
210 newContainer = new Dictionary<string, Stat>(container); 229 newContainer = new SortedDictionary<string, Stat>(container);
211 newContainer.Remove(stat.ShortName); 230 newContainer.Remove(stat.ShortName);
212 231
213 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); 232 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category);
214 newCategory.Remove(stat.Container); 233 newCategory.Remove(stat.Container);
215 234
216 newCategory[stat.Container] = newContainer; 235 newCategory[stat.Container] = newContainer;
@@ -220,15 +239,15 @@ namespace OpenSim.Framework.Monitoring
220 } 239 }
221 } 240 }
222 241
223 public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats) 242 public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
224 { 243 {
225 return RegisteredStats.TryGetValue(category, out stats); 244 return RegisteredStats.TryGetValue(category, out stats);
226 } 245 }
227 246
228 public static bool TryGetStat( 247 public static bool TryGetStat(
229 Stat stat, 248 Stat stat,
230 out Dictionary<string, Dictionary<string, Stat>> category, 249 out SortedDictionary<string, SortedDictionary<string, Stat>> category,
231 out Dictionary<string, Stat> container) 250 out SortedDictionary<string, Stat> container)
232 { 251 {
233 category = null; 252 category = null;
234 container = null; 253 container = null;
@@ -252,9 +271,9 @@ namespace OpenSim.Framework.Monitoring
252 { 271 {
253 lock (RegisteredStats) 272 lock (RegisteredStats)
254 { 273 {
255 foreach (Dictionary<string, Dictionary<string, Stat>> category in RegisteredStats.Values) 274 foreach (SortedDictionary<string, SortedDictionary<string, Stat>> category in RegisteredStats.Values)
256 { 275 {
257 foreach (Dictionary<string, Stat> container in category.Values) 276 foreach (SortedDictionary<string, Stat> container in category.Values)
258 { 277 {
259 foreach (Stat stat in container.Values) 278 foreach (Stat stat in container.Values)
260 { 279 {
diff --git a/OpenSim/Framework/Monitoring/UserStatsCollector.cs b/OpenSim/Framework/Monitoring/UserStatsCollector.cs
index e89c8e6..81e0fa4 100644
--- a/OpenSim/Framework/Monitoring/UserStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/UserStatsCollector.cs
@@ -27,6 +27,8 @@
27 27
28using System.Timers; 28using System.Timers;
29 29
30using OpenMetaverse.StructuredData;
31
30namespace OpenSim.Framework.Monitoring 32namespace OpenSim.Framework.Monitoring
31{ 33{
32 /// <summary> 34 /// <summary>
@@ -88,5 +90,21 @@ namespace OpenSim.Framework.Monitoring
88 Logouts total : {3}", 90 Logouts total : {3}",
89 SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); 91 SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts);
90 } 92 }
93
94 public override string XReport(string uptime, string version)
95 {
96 return OSDParser.SerializeJsonString(OReport(uptime, version));
97 }
98
99 public override OSDMap OReport(string uptime, string version)
100 {
101 OSDMap ret = new OSDMap();
102 ret.Add("SuccessfulLogins", OSD.FromInteger(SuccessfulLogins));
103 ret.Add("SuccessfulLoginsToday", OSD.FromInteger(SuccessfulLoginsToday));
104 ret.Add("SuccessfulLoginsYesterday", OSD.FromInteger(SuccessfulLoginsYesterday));
105 ret.Add("Logouts", OSD.FromInteger(Logouts));
106
107 return ret;
108 }
91 } 109 }
92} 110}