aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SimStatsReporter.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs450
1 files changed, 450 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
new file mode 100644
index 0000000..b2cea5d
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -0,0 +1,450 @@
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 OpenSim 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;
29//using System.Collections.Generic;
30using System.Timers;
31using OpenMetaverse.Packets;
32using OpenSim.Framework;
33using OpenSim.Framework.Statistics;
34using OpenSim.Region.Framework.Interfaces;
35
36namespace OpenSim.Region.Framework.Scenes
37{
38 public class SimStatsReporter
39 {
40 public delegate void SendStatResult(SimStats stats);
41
42 public delegate void YourStatsAreWrong();
43
44 public event SendStatResult OnSendStatsResult;
45
46 public event YourStatsAreWrong OnStatsIncorrect;
47
48 private SendStatResult handlerSendStatResult = null;
49
50 private YourStatsAreWrong handlerStatsIncorrect = null;
51
52 private enum Stats : uint
53 {
54 TimeDilation = 0,
55 SimFPS = 1,
56 PhysicsFPS = 2,
57 AgentUpdates = 3,
58 FrameMS = 4,
59 NetMS = 5,
60 OtherMS = 6,
61 PhysicsMS = 7,
62 AgentMS = 8,
63 ImageMS = 9,
64 ScriptMS = 10,
65 TotalPrim = 11,
66 ActivePrim = 12,
67 Agents = 13,
68 ChildAgents = 14,
69 ActiveScripts = 15,
70 ScriptLinesPerSecond = 16,
71 InPacketsPerSecond = 17,
72 OutPacketsPerSecond = 18,
73 PendingDownloads = 19,
74 PendingUploads = 20,
75 UnAckedBytes = 24,
76 }
77
78 // Sending a stats update every 3 seconds
79 private int statsUpdatesEveryMS = 3000;
80 private float statsUpdateFactor = 0;
81 private float m_timeDilation = 0;
82 private int m_fps = 0;
83 // saved last reported value so there is something available for llGetRegionFPS
84 private float lastReportedSimFPS = 0;
85 private float m_pfps = 0;
86 private int m_agentUpdates = 0;
87
88 private int m_frameMS = 0;
89 private int m_netMS = 0;
90 private int m_agentMS = 0;
91 private int m_physicsMS = 0;
92 private int m_imageMS = 0;
93 private int m_otherMS = 0;
94
95//Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed.
96//Ckrinke private int m_scriptMS = 0;
97
98 private int m_rootAgents = 0;
99 private int m_childAgents = 0;
100 private int m_numPrim = 0;
101 private int m_inPacketsPerSecond = 0;
102 private int m_outPacketsPerSecond = 0;
103 private int m_activePrim = 0;
104 private int m_unAckedBytes = 0;
105 private int m_pendingDownloads = 0;
106 private int m_pendingUploads = 0;
107 private int m_activeScripts = 0;
108 private int m_scriptLinesPerSecond = 0;
109
110 private int objectCapacity = 45000;
111
112 private Scene m_scene;
113
114 private RegionInfo ReportingRegion;
115
116 private Timer m_report = new Timer();
117
118
119 public SimStatsReporter(Scene scene)
120 {
121 statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000);
122 m_scene = scene;
123 ReportingRegion = scene.RegionInfo;
124
125 m_report.AutoReset = true;
126 m_report.Interval = statsUpdatesEveryMS;
127 m_report.Elapsed += new ElapsedEventHandler(statsHeartBeat);
128 m_report.Enabled = true;
129
130 if (StatsManager.SimExtraStats != null)
131 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
132 }
133
134 public void SetUpdateMS(int ms)
135 {
136 statsUpdatesEveryMS = ms;
137 statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000);
138 m_report.Interval = statsUpdatesEveryMS;
139 }
140
141 private void statsHeartBeat(object sender, EventArgs e)
142 {
143 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21];
144 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
145
146 // Know what's not thread safe in Mono... modifying timers.
147 // System.Console.WriteLine("Firing Stats Heart Beat");
148 lock (m_report)
149 {
150 uint regionFlags = 0;
151
152 try
153 {
154 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
155 regionFlags = estateModule != null ? estateModule.GetRegionFlags() : (uint) 0;
156 }
157 catch (Exception)
158 {
159 // leave region flags at 0
160 }
161
162#region various statistic googly moogly
163
164 // Our FPS is actually 10fps, so multiplying by 5 to get the amount that people expect there
165 // 0-50 is pretty close to 0-45
166 float simfps = (int) ((m_fps * 5));
167 // save the reported value so there is something available for llGetRegionFPS
168 lastReportedSimFPS = (float)simfps / statsUpdateFactor;
169
170 //if (simfps > 45)
171 //simfps = simfps - (simfps - 45);
172 //if (simfps < 0)
173 //simfps = 0;
174
175 //
176 float physfps = ((m_pfps / 1000));
177
178 //if (physfps > 600)
179 //physfps = physfps - (physfps - 600);
180
181 if (physfps < 0)
182 physfps = 0;
183
184#endregion
185
186 //Our time dilation is 0.91 when we're running a full speed,
187 // therefore to make sure we get an appropriate range,
188 // we have to factor in our error. (0.10f * statsUpdateFactor)
189 // multiplies the fix for the error times the amount of times it'll occur a second
190 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
191 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
192
193 for (int i = 0; i<21;i++)
194 {
195 sb[i] = new SimStatsPacket.StatBlock();
196 }
197
198 sb[0].StatID = (uint) Stats.TimeDilation;
199 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor));
200
201 sb[1].StatID = (uint) Stats.SimFPS;
202 sb[1].StatValue = simfps/statsUpdateFactor;
203
204 sb[2].StatID = (uint) Stats.PhysicsFPS;
205 sb[2].StatValue = physfps / statsUpdateFactor;
206
207 sb[3].StatID = (uint) Stats.AgentUpdates;
208 sb[3].StatValue = (m_agentUpdates / statsUpdateFactor);
209
210 sb[4].StatID = (uint) Stats.Agents;
211 sb[4].StatValue = m_rootAgents;
212
213 sb[5].StatID = (uint) Stats.ChildAgents;
214 sb[5].StatValue = m_childAgents;
215
216 sb[6].StatID = (uint) Stats.TotalPrim;
217 sb[6].StatValue = m_numPrim;
218
219 sb[7].StatID = (uint) Stats.ActivePrim;
220 sb[7].StatValue = m_activePrim;
221
222 sb[8].StatID = (uint)Stats.FrameMS;
223 sb[8].StatValue = m_frameMS / statsUpdateFactor;
224
225 sb[9].StatID = (uint)Stats.NetMS;
226 sb[9].StatValue = m_netMS / statsUpdateFactor;
227
228 sb[10].StatID = (uint)Stats.PhysicsMS;
229 sb[10].StatValue = m_physicsMS / statsUpdateFactor;
230
231 sb[11].StatID = (uint)Stats.ImageMS ;
232 sb[11].StatValue = m_imageMS / statsUpdateFactor;
233
234 sb[12].StatID = (uint)Stats.OtherMS;
235 sb[12].StatValue = m_otherMS / statsUpdateFactor;
236
237 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
238 sb[13].StatValue = (m_inPacketsPerSecond);
239
240 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
241 sb[14].StatValue = (m_outPacketsPerSecond / statsUpdateFactor);
242
243 sb[15].StatID = (uint)Stats.UnAckedBytes;
244 sb[15].StatValue = m_unAckedBytes;
245
246 sb[16].StatID = (uint)Stats.AgentMS;
247 sb[16].StatValue = m_agentMS / statsUpdateFactor;
248
249 sb[17].StatID = (uint)Stats.PendingDownloads;
250 sb[17].StatValue = m_pendingDownloads;
251
252 sb[18].StatID = (uint)Stats.PendingUploads;
253 sb[18].StatValue = m_pendingUploads;
254
255 sb[19].StatID = (uint)Stats.ActiveScripts;
256 sb[19].StatValue = m_activeScripts;
257
258 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond;
259 sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor;
260
261 SimStats simStats
262 = new SimStats(
263 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)objectCapacity, rb, sb, m_scene.RegionInfo.originRegionID);
264
265 handlerSendStatResult = OnSendStatsResult;
266 if (handlerSendStatResult != null)
267 {
268 handlerSendStatResult(simStats);
269 }
270 resetvalues();
271 }
272 }
273
274 private void resetvalues()
275 {
276 m_timeDilation = 0;
277 m_fps = 0;
278 m_pfps = 0;
279 m_agentUpdates = 0;
280 m_inPacketsPerSecond = 0;
281 m_outPacketsPerSecond = 0;
282 m_unAckedBytes = 0;
283 m_scriptLinesPerSecond = 0;
284
285 m_frameMS = 0;
286 m_agentMS = 0;
287 m_netMS = 0;
288 m_physicsMS = 0;
289 m_imageMS = 0;
290 m_otherMS = 0;
291
292//Ckrinke This variable is not used, so comment to remove compiler warning until it is used.
293//Ckrinke m_scriptMS = 0;
294 }
295
296 # region methods called from Scene
297 // The majority of these functions are additive
298 // so that you can easily change the amount of
299 // seconds in between sim stats updates
300
301 public void AddTimeDilation(float td)
302 {
303 //float tdsetting = td;
304 //if (tdsetting > 1.0f)
305 //tdsetting = (tdsetting - (tdsetting - 0.91f));
306
307 //if (tdsetting < 0)
308 //tdsetting = 0.0f;
309 m_timeDilation = td;
310 }
311
312 public void SetRootAgents(int rootAgents)
313 {
314 m_rootAgents = rootAgents;
315 CheckStatSanity();
316
317 }
318
319 internal void CheckStatSanity()
320 {
321 if (m_rootAgents < 0 || m_childAgents < 0)
322 {
323 handlerStatsIncorrect = OnStatsIncorrect;
324 if (handlerStatsIncorrect != null)
325 {
326 handlerStatsIncorrect();
327 }
328 }
329 if (m_rootAgents == 0 && m_childAgents == 0)
330 {
331 m_unAckedBytes = 0;
332 }
333 }
334
335 public void SetChildAgents(int childAgents)
336 {
337 m_childAgents = childAgents;
338 CheckStatSanity();
339 }
340
341 public void SetObjects(int objects)
342 {
343 m_numPrim = objects;
344 }
345
346 public void SetActiveObjects(int objects)
347 {
348 m_activePrim = objects;
349 }
350
351 public void AddFPS(int frames)
352 {
353 m_fps += frames;
354 }
355
356 public void AddPhysicsFPS(float frames)
357 {
358 m_pfps += frames;
359 }
360
361 public void AddAgentUpdates(int numUpdates)
362 {
363 m_agentUpdates += numUpdates;
364 }
365
366 public void AddInPackets(int numPackets)
367 {
368 m_inPacketsPerSecond += numPackets;
369 }
370
371 public void AddOutPackets(int numPackets)
372 {
373 m_outPacketsPerSecond += numPackets;
374 }
375
376 public void AddunAckedBytes(int numBytes)
377 {
378 m_unAckedBytes += numBytes;
379 if (m_unAckedBytes < 0) m_unAckedBytes = 0;
380 }
381
382 public void addFrameMS(int ms)
383 {
384 m_frameMS += ms;
385 }
386 public void addNetMS(int ms)
387 {
388 m_netMS += ms;
389 }
390 public void addAgentMS(int ms)
391 {
392 m_agentMS += ms;
393 }
394 public void addPhysicsMS(int ms)
395 {
396 m_physicsMS += ms;
397 }
398 public void addImageMS(int ms)
399 {
400 m_imageMS += ms;
401 }
402 public void addOtherMS(int ms)
403 {
404 m_otherMS += ms;
405 }
406
407// private static readonly log4net.ILog m_log
408// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
409
410 public void addPendingDownload(int count)
411 {
412 m_pendingDownloads += count;
413 if (m_pendingDownloads < 0) m_pendingDownloads = 0;
414 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
415 }
416
417 public void addScriptLines(int count)
418 {
419 m_scriptLinesPerSecond += count;
420 }
421
422 public void SetActiveScripts(int count)
423 {
424 m_activeScripts = count;
425 }
426
427 public void SetObjectCapacity(int objects)
428 {
429 objectCapacity = objects;
430 }
431
432 /// <summary>
433 /// This is for llGetRegionFPS
434 /// </summary>
435 public float getLastReportedSimFPS()
436 {
437 return lastReportedSimFPS;
438 }
439
440 public void AddPacketsFromClientStats(int inPackets, int outPackets, int unAckedBytes)
441 {
442 AddInPackets(inPackets);
443 AddOutPackets(outPackets);
444 AddunAckedBytes(unAckedBytes);
445
446 }
447
448 #endregion
449 }
450}