aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs')
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs463
1 files changed, 463 insertions, 0 deletions
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
new file mode 100644
index 0000000..cdd7cc7
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -0,0 +1,463 @@
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.Text;
31using OpenMetaverse;
32using OpenMetaverse.StructuredData;
33using OpenSim.Framework.Monitoring.Interfaces;
34
35namespace OpenSim.Framework.Monitoring
36{
37 /// <summary>
38 /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane
39 /// </summary>
40 public class SimExtraStatsCollector : BaseStatsCollector
41 {
42 private long abnormalClientThreadTerminations;
43
44// private long assetsInCache;
45// private long texturesInCache;
46// private long assetCacheMemoryUsage;
47// private long textureCacheMemoryUsage;
48// private TimeSpan assetRequestTimeAfterCacheMiss;
49// private long blockedMissingTextureRequests;
50
51// private long assetServiceRequestFailures;
52// private long inventoryServiceRetrievalFailures;
53
54 private volatile float timeDilation;
55 private volatile float simFps;
56 private volatile float physicsFps;
57 private volatile float agentUpdates;
58 private volatile float rootAgents;
59 private volatile float childAgents;
60 private volatile float totalPrims;
61 private volatile float activePrims;
62 private volatile float totalFrameTime;
63 private volatile float netFrameTime;
64 private volatile float physicsFrameTime;
65 private volatile float otherFrameTime;
66 private volatile float imageFrameTime;
67 private volatile float inPacketsPerSecond;
68 private volatile float outPacketsPerSecond;
69 private volatile float unackedBytes;
70 private volatile float agentFrameTime;
71 private volatile float pendingDownloads;
72 private volatile float pendingUploads;
73 private volatile float activeScripts;
74 private volatile float scriptLinesPerSecond;
75
76 /// <summary>
77 /// Number of times that a client thread terminated because of an exception
78 /// </summary>
79 public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } }
80
81// /// <summary>
82// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
83// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
84// /// haven't yet been implemented...
85// /// </summary>
86// public long AssetsInCache { get { return assetsInCache; } }
87//
88// /// <value>
89// /// Currently unused
90// /// </value>
91// public long TexturesInCache { get { return texturesInCache; } }
92//
93// /// <value>
94// /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit
95// /// </value>
96// public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } }
97//
98// /// <value>
99// /// Currently unused
100// /// </value>
101// public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } }
102
103 public float TimeDilation { get { return timeDilation; } }
104 public float SimFps { get { return simFps; } }
105 public float PhysicsFps { get { return physicsFps; } }
106 public float AgentUpdates { get { return agentUpdates; } }
107 public float RootAgents { get { return rootAgents; } }
108 public float ChildAgents { get { return childAgents; } }
109 public float TotalPrims { get { return totalPrims; } }
110 public float ActivePrims { get { return activePrims; } }
111 public float TotalFrameTime { get { return totalFrameTime; } }
112 public float NetFrameTime { get { return netFrameTime; } }
113 public float PhysicsFrameTime { get { return physicsFrameTime; } }
114 public float OtherFrameTime { get { return otherFrameTime; } }
115 public float ImageFrameTime { get { return imageFrameTime; } }
116 public float InPacketsPerSecond { get { return inPacketsPerSecond; } }
117 public float OutPacketsPerSecond { get { return outPacketsPerSecond; } }
118 public float UnackedBytes { get { return unackedBytes; } }
119 public float AgentFrameTime { get { return agentFrameTime; } }
120 public float PendingDownloads { get { return pendingDownloads; } }
121 public float PendingUploads { get { return pendingUploads; } }
122 public float ActiveScripts { get { return activeScripts; } }
123 public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } }
124
125// /// <summary>
126// /// This is the time it took for the last asset request made in response to a cache miss.
127// /// </summary>
128// public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } }
129//
130// /// <summary>
131// /// Number of persistent requests for missing textures we have started blocking from clients. To some extent
132// /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either
133// /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics
134// /// driver bugs on clients (though this seems less likely).
135// /// </summary>
136// public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } }
137//
138// /// <summary>
139// /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as
140// /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted
141// /// as a failure
142// /// </summary>
143// public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } }
144
145 /// <summary>
146 /// Number of known failures to retrieve avatar inventory from the inventory service. This does not
147 /// cover situations where the inventory service accepts the request but never returns any data, since
148 /// we do not yet timeout this situation.
149 /// </summary>
150 /// <remarks>Commented out because we do not cache inventory at this point</remarks>
151// public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } }
152
153 /// <summary>
154 /// Retrieve the total frame time (in ms) of the last frame
155 /// </summary>
156 //public float TotalFrameTime { get { return totalFrameTime; } }
157
158 /// <summary>
159 /// Retrieve the physics update component (in ms) of the last frame
160 /// </summary>
161 //public float PhysicsFrameTime { get { return physicsFrameTime; } }
162
163 /// <summary>
164 /// Retain a dictionary of all packet queues stats reporters
165 /// </summary>
166 private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
167 = new Dictionary<UUID, PacketQueueStatsCollector>();
168
169 public void AddAbnormalClientThreadTermination()
170 {
171 abnormalClientThreadTerminations++;
172 }
173
174// public void AddAsset(AssetBase asset)
175// {
176// assetsInCache++;
177// //assetCacheMemoryUsage += asset.Data.Length;
178// }
179//
180// public void RemoveAsset(UUID uuid)
181// {
182// assetsInCache--;
183// }
184//
185// public void AddTexture(AssetBase image)
186// {
187// if (image.Data != null)
188// {
189// texturesInCache++;
190//
191// // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates
192// textureCacheMemoryUsage += image.Data.Length;
193// }
194// }
195//
196// /// <summary>
197// /// Signal that the asset cache has been cleared.
198// /// </summary>
199// public void ClearAssetCacheStatistics()
200// {
201// assetsInCache = 0;
202// assetCacheMemoryUsage = 0;
203// texturesInCache = 0;
204// textureCacheMemoryUsage = 0;
205// }
206//
207// public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts)
208// {
209// assetRequestTimeAfterCacheMiss = ts;
210// }
211//
212// public void AddBlockedMissingTextureRequest()
213// {
214// blockedMissingTextureRequests++;
215// }
216//
217// public void AddAssetServiceRequestFailure()
218// {
219// assetServiceRequestFailures++;
220// }
221
222// public void AddInventoryServiceRetrievalFailure()
223// {
224// inventoryServiceRetrievalFailures++;
225// }
226
227 /// <summary>
228 /// Register as a packet queue stats provider
229 /// </summary>
230 /// <param name="uuid">An agent UUID</param>
231 /// <param name="provider"></param>
232 public void RegisterPacketQueueStatsProvider(UUID uuid, IPullStatsProvider provider)
233 {
234 lock (packetQueueStatsCollectors)
235 {
236 // FIXME: If the region service is providing more than one region, then the child and root agent
237 // queues are wrongly replacing each other here.
238 packetQueueStatsCollectors[uuid] = new PacketQueueStatsCollector(provider);
239 }
240 }
241
242 /// <summary>
243 /// Deregister a packet queue stats provider
244 /// </summary>
245 /// <param name="uuid">An agent UUID</param>
246 public void DeregisterPacketQueueStatsProvider(UUID uuid)
247 {
248 lock (packetQueueStatsCollectors)
249 {
250 packetQueueStatsCollectors.Remove(uuid);
251 }
252 }
253
254 /// <summary>
255 /// This is the method on which the classic sim stats reporter (which collects stats for
256 /// client purposes) sends information to listeners.
257 /// </summary>
258 /// <param name="pack"></param>
259 public void ReceiveClassicSimStatsPacket(SimStats stats)
260 {
261 // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original
262 // SimStatsPacket that was being used).
263 timeDilation = stats.StatsBlock[0].StatValue;
264 simFps = stats.StatsBlock[1].StatValue;
265 physicsFps = stats.StatsBlock[2].StatValue;
266 agentUpdates = stats.StatsBlock[3].StatValue;
267 rootAgents = stats.StatsBlock[4].StatValue;
268 childAgents = stats.StatsBlock[5].StatValue;
269 totalPrims = stats.StatsBlock[6].StatValue;
270 activePrims = stats.StatsBlock[7].StatValue;
271 totalFrameTime = stats.StatsBlock[8].StatValue;
272 netFrameTime = stats.StatsBlock[9].StatValue;
273 physicsFrameTime = stats.StatsBlock[10].StatValue;
274 otherFrameTime = stats.StatsBlock[11].StatValue;
275 imageFrameTime = stats.StatsBlock[12].StatValue;
276 inPacketsPerSecond = stats.StatsBlock[13].StatValue;
277 outPacketsPerSecond = stats.StatsBlock[14].StatValue;
278 unackedBytes = stats.StatsBlock[15].StatValue;
279 agentFrameTime = stats.StatsBlock[16].StatValue;
280 pendingDownloads = stats.StatsBlock[17].StatValue;
281 pendingUploads = stats.StatsBlock[18].StatValue;
282 activeScripts = stats.StatsBlock[19].StatValue;
283 scriptLinesPerSecond = stats.StatsBlock[20].StatValue;
284 }
285
286 /// <summary>
287 /// Report back collected statistical information.
288 /// </summary>
289 /// <returns></returns>
290 public override string Report()
291 {
292 StringBuilder sb = new StringBuilder(Environment.NewLine);
293// sb.Append("ASSET STATISTICS");
294// sb.Append(Environment.NewLine);
295
296 /*
297 sb.Append(
298 string.Format(
299@"Asset cache contains {0,6} non-texture assets using {1,10} K
300Texture cache contains {2,6} texture assets using {3,10} K
301Latest asset request time after cache miss: {4}s
302Blocked client requests for missing textures: {5}
303Asset service request failures: {6}"+ Environment.NewLine,
304 AssetsInCache, Math.Round(AssetCacheMemoryUsage / 1024.0),
305 TexturesInCache, Math.Round(TextureCacheMemoryUsage / 1024.0),
306 assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0,
307 BlockedMissingTextureRequests,
308 AssetServiceRequestFailures));
309 */
310
311 /*
312 sb.Append(
313 string.Format(
314@"Asset cache contains {0,6} assets
315Latest asset request time after cache miss: {1}s
316Blocked client requests for missing textures: {2}
317Asset service request failures: {3}" + Environment.NewLine,
318 AssetsInCache,
319 assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0,
320 BlockedMissingTextureRequests,
321 AssetServiceRequestFailures));
322 */
323
324 sb.Append(Environment.NewLine);
325 sb.Append("CONNECTION STATISTICS");
326 sb.Append(Environment.NewLine);
327 sb.Append(
328 string.Format(
329 "Abnormal client thread terminations: {0}" + Environment.NewLine,
330 abnormalClientThreadTerminations));
331
332// sb.Append(Environment.NewLine);
333// sb.Append("INVENTORY STATISTICS");
334// sb.Append(Environment.NewLine);
335// sb.Append(
336// string.Format(
337// "Initial inventory caching failures: {0}" + Environment.NewLine,
338// InventoryServiceRetrievalFailures));
339
340 sb.Append(Environment.NewLine);
341 sb.Append("FRAME STATISTICS");
342 sb.Append(Environment.NewLine);
343 sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
344 sb.Append(Environment.NewLine);
345 sb.Append(
346 string.Format(
347 "{0,6:0.00} {1,6:0} {2,6:0.0} {3,6:0.0} {4,6:0} {5,6:0} {6,6:0} {7,6:0} {8,6:0} {9,6:0}",
348 timeDilation, simFps, physicsFps, agentUpdates, rootAgents,
349 childAgents, totalPrims, activePrims, activeScripts, scriptLinesPerSecond));
350
351 sb.Append(Environment.NewLine);
352 sb.Append(Environment.NewLine);
353 // There is no script frame time currently because we don't yet collect it
354 sb.Append("PktsIn PktOut PendDl PendUl UnackB TotlFt NetFt PhysFt OthrFt AgntFt ImgsFt");
355 sb.Append(Environment.NewLine);
356 sb.Append(
357 string.Format(
358 "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}",
359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
361 sb.Append(Environment.NewLine);
362
363 /*
364 sb.Append(Environment.NewLine);
365 sb.Append("PACKET QUEUE STATISTICS");
366 sb.Append(Environment.NewLine);
367 sb.Append("Agent UUID ");
368 sb.Append(
369 string.Format(
370 " {0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
371 "Send", "In", "Out", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset"));
372 sb.Append(Environment.NewLine);
373
374 foreach (UUID key in packetQueueStatsCollectors.Keys)
375 {
376 sb.Append(string.Format("{0}: ", key));
377 sb.Append(packetQueueStatsCollectors[key].Report());
378 sb.Append(Environment.NewLine);
379 }
380 */
381
382 sb.Append(base.Report());
383
384 return sb.ToString();
385 }
386
387 /// <summary>
388 /// Report back collected statistical information as json serialization.
389 /// </summary>
390 /// <returns></returns>
391 public override string XReport(string uptime, string version)
392 {
393 OSDMap args = new OSDMap(30);
394// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache));
395// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}",
396// assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0));
397// args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}",
398// BlockedMissingTextureRequests));
399// args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}",
400// AssetServiceRequestFailures));
401// args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}",
402// abnormalClientThreadTerminations));
403// args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}",
404// InventoryServiceRetrievalFailures));
405 args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", timeDilation));
406 args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", simFps));
407 args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", physicsFps));
408 args["AgntUp"] = OSD.FromString (String.Format ("{0:0.##}", agentUpdates));
409 args["RootAg"] = OSD.FromString (String.Format ("{0:0.##}", rootAgents));
410 args["ChldAg"] = OSD.FromString (String.Format ("{0:0.##}", childAgents));
411 args["Prims"] = OSD.FromString (String.Format ("{0:0.##}", totalPrims));
412 args["AtvPrm"] = OSD.FromString (String.Format ("{0:0.##}", activePrims));
413 args["AtvScr"] = OSD.FromString (String.Format ("{0:0.##}", activeScripts));
414 args["ScrLPS"] = OSD.FromString (String.Format ("{0:0.##}", scriptLinesPerSecond));
415 args["PktsIn"] = OSD.FromString (String.Format ("{0:0.##}", inPacketsPerSecond));
416 args["PktOut"] = OSD.FromString (String.Format ("{0:0.##}", outPacketsPerSecond));
417 args["PendDl"] = OSD.FromString (String.Format ("{0:0.##}", pendingDownloads));
418 args["PendUl"] = OSD.FromString (String.Format ("{0:0.##}", pendingUploads));
419 args["UnackB"] = OSD.FromString (String.Format ("{0:0.##}", unackedBytes));
420 args["TotlFt"] = OSD.FromString (String.Format ("{0:0.##}", totalFrameTime));
421 args["NetFt"] = OSD.FromString (String.Format ("{0:0.##}", netFrameTime));
422 args["PhysFt"] = OSD.FromString (String.Format ("{0:0.##}", physicsFrameTime));
423 args["OthrFt"] = OSD.FromString (String.Format ("{0:0.##}", otherFrameTime));
424 args["AgntFt"] = OSD.FromString (String.Format ("{0:0.##}", agentFrameTime));
425 args["ImgsFt"] = OSD.FromString (String.Format ("{0:0.##}", imageFrameTime));
426 args["Memory"] = OSD.FromString (base.XReport (uptime, version));
427 args["Uptime"] = OSD.FromString (uptime);
428 args["Version"] = OSD.FromString (version);
429
430 string strBuffer = "";
431 strBuffer = OSDParser.SerializeJsonString(args);
432
433 return strBuffer;
434 }
435 }
436
437 /// <summary>
438 /// Pull packet queue stats from packet queues and report
439 /// </summary>
440 public class PacketQueueStatsCollector : IStatsCollector
441 {
442 private IPullStatsProvider m_statsProvider;
443
444 public PacketQueueStatsCollector(IPullStatsProvider provider)
445 {
446 m_statsProvider = provider;
447 }
448
449 /// <summary>
450 /// Report back collected statistical information.
451 /// </summary>
452 /// <returns></returns>
453 public string Report()
454 {
455 return m_statsProvider.GetStats();
456 }
457
458 public string XReport(string uptime, string version)
459 {
460 return "";
461 }
462 }
463}