aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Monitoring/Stats/CounterStat.cs')
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs439
1 files changed, 228 insertions, 211 deletions
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
index d81f182..caea30d 100755
--- a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
@@ -1,211 +1,228 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Text; 31using System.Text;
32 32
33using OpenMetaverse.StructuredData; 33using OpenMetaverse.StructuredData;
34 34
35namespace OpenSim.Framework.Monitoring 35namespace OpenSim.Framework.Monitoring
36{ 36{
37// Create a time histogram of events. The histogram is built in a wrap-around 37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets. 38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be: 39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000) 40// new EventHistogram(60, 1000)
41public class EventHistogram 41public class EventHistogram
42{ 42{
43 private int m_timeBase; 43 private int m_timeBase;
44 private int m_numBuckets; 44 private int m_numBuckets;
45 private int m_bucketMilliseconds; 45 private int m_bucketMilliseconds;
46 private int m_lastBucket; 46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds; 47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram; 48 private long[] m_histogram;
49 private object histoLock = new object(); 49 private object histoLock = new object();
50 50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket) 51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 { 52 {
53 m_numBuckets = numberOfBuckets; 53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket; 54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds; 55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56 56
57 m_histogram = new long[m_numBuckets]; 57 m_histogram = new long[m_numBuckets];
58 Zero(); 58 Zero();
59 m_lastBucket = 0; 59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount(); 60 m_timeBase = Util.EnvironmentTickCount();
61 } 61 }
62 62
63 public void Event() 63 public void Event()
64 { 64 {
65 this.Event(1); 65 this.Event(1);
66 } 66 }
67 67
68 // Record an event at time 'now' in the histogram. 68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt) 69 public void Event(int cnt)
70 { 70 {
71 lock (histoLock) 71 lock (histoLock)
72 { 72 {
73 // The time as displaced from the base of the histogram 73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase); 74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75 75
76 // If more than the total time of the histogram, we just start over 76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds) 77 if (bucketTime > m_totalHistogramMilliseconds)
78 { 78 {
79 Zero(); 79 Zero();
80 m_lastBucket = 0; 80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount(); 81 m_timeBase = Util.EnvironmentTickCount();
82 } 82 }
83 else 83 else
84 { 84 {
85 // To which bucket should we add this event? 85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds; 86 int bucket = bucketTime / m_bucketMilliseconds;
87 87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over. 88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket) 89 while (bucket != m_lastBucket)
90 { 90 {
91 // Zero from just after the last bucket to the new bucket or the end 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++) 92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 { 93 {
94 m_histogram[jj] = 0; 94 m_histogram[jj] = 0;
95 } 95 }
96 m_lastBucket = bucket; 96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning 97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets) 98 if (bucket > m_numBuckets)
99 { 99 {
100 bucket -= m_numBuckets; 100 bucket -= m_numBuckets;
101 m_lastBucket = 0; 101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0; 102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds; 103 m_timeBase += m_totalHistogramMilliseconds;
104 } 104 }
105 } 105 }
106 } 106 }
107 m_histogram[m_lastBucket] += cnt; 107 m_histogram[m_lastBucket] += cnt;
108 } 108 }
109 } 109 }
110 110
111 // Get a copy of the current histogram 111 // Get a copy of the current histogram
112 public long[] GetHistogram() 112 public long[] GetHistogram()
113 { 113 {
114 long[] ret = new long[m_numBuckets]; 114 long[] ret = new long[m_numBuckets];
115 lock (histoLock) 115 lock (histoLock)
116 { 116 {
117 int indx = m_lastBucket + 1; 117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++) 118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 { 119 {
120 if (indx >= m_numBuckets) 120 if (indx >= m_numBuckets)
121 indx = 0; 121 indx = 0;
122 ret[ii] = m_histogram[indx]; 122 ret[ii] = m_histogram[indx];
123 } 123 }
124 } 124 }
125 return ret; 125 return ret;
126 } 126 }
127 127
128 // Get a copy of the current histogram 128 public OSDMap GetHistogramAsOSDMap()
129 public OSDArray GetHistogramAsOSDArray() 129 {
130 { 130 OSDMap ret = new OSDMap();
131 OSDArray ret = new OSDArray(m_numBuckets); 131
132 lock (histoLock) 132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 { 133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 int indx = m_lastBucket + 1; 134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135 for (int ii = 0; ii < m_numBuckets; ii++, indx++) 135
136 { 136 // Compute a number for the first bucket in the histogram.
137 if (indx >= m_numBuckets) 137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 indx = 0; 138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret[ii] = OSD.FromLong(m_histogram[indx]); 139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140 } 140
141 } 141 ret.Add("Values", GetHistogramAsOSDArray());
142 return ret; 142
143 } 143 return ret;
144 144 }
145 // Zero out the histogram 145 // Get a copy of the current histogram
146 public void Zero() 146 public OSDArray GetHistogramAsOSDArray()
147 { 147 {
148 lock (histoLock) 148 OSDArray ret = new OSDArray(m_numBuckets);
149 { 149 lock (histoLock)
150 for (int ii = 0; ii < m_numBuckets; ii++) 150 {
151 m_histogram[ii] = 0; 151 int indx = m_lastBucket + 1;
152 } 152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 } 153 {
154} 154 if (indx >= m_numBuckets)
155 155 indx = 0;
156// A statistic that wraps a counter. 156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157// Built this way mostly so histograms and history can be created. 157 }
158public class CounterStat : Stat 158 }
159{ 159 return ret;
160 private SortedDictionary<string, EventHistogram> m_histograms; 160 }
161 private object counterLock = new object(); 161
162 162 // Zero out the histogram
163 public CounterStat( 163 public void Zero()
164 string shortName, 164 {
165 string name, 165 lock (histoLock)
166 string description, 166 {
167 string unitName, 167 for (int ii = 0; ii < m_numBuckets; ii++)
168 string category, 168 m_histogram[ii] = 0;
169 string container, 169 }
170 StatVerbosity verbosity) 170 }
171 : base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity) 171}
172 { 172
173 m_histograms = new SortedDictionary<string, EventHistogram>(); 173// A statistic that wraps a counter.
174 } 174// Built this way mostly so histograms and history can be created.
175 175public class CounterStat : Stat
176 // Histograms are presumably added at intialization time and the list does not change thereafter. 176{
177 // Thus no locking of the histogram list. 177 private SortedDictionary<string, EventHistogram> m_histograms;
178 public void AddHistogram(string histoName, EventHistogram histo) 178 private object counterLock = new object();
179 { 179
180 m_histograms.Add(histoName, histo); 180 public CounterStat(
181 } 181 string shortName,
182 182 string name,
183 public delegate void ProcessHistogram(string name, EventHistogram histo); 183 string description,
184 public void ForEachHistogram(ProcessHistogram process) 184 string unitName,
185 { 185 string category,
186 foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms) 186 string container,
187 { 187 StatVerbosity verbosity)
188 process(kvp.Key, kvp.Value); 188 : base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity)
189 } 189 {
190 } 190 m_histograms = new SortedDictionary<string, EventHistogram>();
191 191 }
192 public void Event() 192
193 { 193 // Histograms are presumably added at intialization time and the list does not change thereafter.
194 this.Event(1); 194 // Thus no locking of the histogram list.
195 } 195 public void AddHistogram(string histoName, EventHistogram histo)
196 196 {
197 // Count the underlying counter. 197 m_histograms.Add(histoName, histo);
198 public void Event(int cnt) 198 }
199 { 199
200 lock (counterLock) 200 public delegate void ProcessHistogram(string name, EventHistogram histo);
201 { 201 public void ForEachHistogram(ProcessHistogram process)
202 base.Value += cnt; 202 {
203 203 foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms)
204 foreach (EventHistogram histo in m_histograms.Values) 204 {
205 { 205 process(kvp.Key, kvp.Value);
206 histo.Event(cnt); 206 }
207 } 207 }
208 } 208
209 } 209 public void Event()
210} 210 {
211} 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}