clockwerk-opensim – Blame information for rev 1

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