From bee710bd5723394d3b8bdca2c9f18248d4c04ae2 Mon Sep 17 00:00:00 2001 From: Jim Radford Date: Sun, 18 Oct 2009 00:08:20 +0000 Subject: [PATCH] LIBOMV-720 Adds network utilization tracking, example TestClient command 'netstats' included to display the results. git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@3152 52acb1d6-8a22-11de-b505-999d5b087335 --- OpenMetaverse/Caps.cs | 9 +- OpenMetaverse/GridClient.cs | 17 +--- OpenMetaverse/Settings.cs | 5 + OpenMetaverse/Simulator.cs | 23 ++++- .../Commands/Stats/NetstatsCommand.cs | 96 +++++++++++++++++++ 5 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 Programs/examples/TestClient/Commands/Stats/NetstatsCommand.cs diff --git a/OpenMetaverse/Caps.cs b/OpenMetaverse/Caps.cs index e4c7c6b8..111c29d6 100644 --- a/OpenMetaverse/Caps.cs +++ b/OpenMetaverse/Caps.cs @@ -230,6 +230,13 @@ namespace OpenMetaverse Simulator.Client.Network.CapsEvents.RaiseEvent(eventName, message, Simulator); else Simulator.Client.Network.CapsEvents.BeginRaiseEvent(eventName, message, Simulator); + + #region Stats Tracking + if (Simulator.Client.Settings.TRACK_UTILIZATION) + { + Simulator.Client.Stats.Update(eventName, OpenMetaverse.Stats.Type.Message, 0, body.ToString().Length); + } + #endregion } else { @@ -257,6 +264,6 @@ namespace OpenMetaverse } } } - } + } } } diff --git a/OpenMetaverse/GridClient.cs b/OpenMetaverse/GridClient.cs index 4593155c..de61b95e 100644 --- a/OpenMetaverse/GridClient.cs +++ b/OpenMetaverse/GridClient.cs @@ -101,6 +101,8 @@ namespace OpenMetaverse /// Throttling total bandwidth usage, or allocating bandwidth /// for specific data stream types public AgentThrottle Throttle; + + public Stats.UtilizationStatistics Stats; /// /// Default constructor /// @@ -124,20 +126,7 @@ namespace OpenMetaverse Terrain = new TerrainManager(this); Sound = new SoundManager(this); Throttle = new AgentThrottle(this); - - //if (Settings.ENABLE_INVENTORY_STORE) - // InventoryStore = new Inventory(Inventory); - //if (Settings.ENABLE_LIBRARY_STORE) - // LibraryStore = new Inventory(Inventory); - - //Inventory.OnSkeletonsReceived += - // delegate(InventoryManager manager) - // { - // if (Settings.ENABLE_INVENTORY_STORE) - // InventoryStore.InitializeFromSkeleton(Inventory.InventorySkeleton); - // if (Settings.ENABLE_LIBRARY_STORE) - // LibraryStore.InitializeFromSkeleton(Inventory.LibrarySkeleton); - // }; + Stats = new OpenMetaverse.Stats.UtilizationStatistics(); } /// diff --git a/OpenMetaverse/Settings.cs b/OpenMetaverse/Settings.cs index f7bc927e..b9ce846d 100644 --- a/OpenMetaverse/Settings.cs +++ b/OpenMetaverse/Settings.cs @@ -230,6 +230,11 @@ namespace OpenMetaverse /// estimates for simulated objects public bool USE_INTERPOLATION_TIMER = true; + /// + /// If true, utilization statistics will be tracked. There is a minor penalty + /// in CPU time for enabling this option. + /// + public bool TRACK_UTILIZATION = true; #endregion #region Parcel Tracking diff --git a/OpenMetaverse/Simulator.cs b/OpenMetaverse/Simulator.cs index 349aa930..d9677a76 100644 --- a/OpenMetaverse/Simulator.cs +++ b/OpenMetaverse/Simulator.cs @@ -124,7 +124,7 @@ namespace OpenMetaverse } #endregion Enums - + /// /// /// @@ -228,8 +228,7 @@ namespace OpenMetaverse #endregion Structs - #region Public Members - + #region Public Members /// A public reference to the client that this Simulator object /// is attached to public GridClient Client; @@ -451,8 +450,8 @@ namespace OpenMetaverse public Simulator(GridClient client, IPEndPoint address, ulong handle) : base(address) { - Client = client; - + Client = client; + Handle = handle; Network = Client.Network; PacketArchive = new IncomingPacketIDCollection(Settings.PACKET_ARCHIVE_SIZE); @@ -731,6 +730,13 @@ namespace OpenMetaverse } #endregion Queue or Send + + #region Stats Tracking + if (Client.Settings.TRACK_UTILIZATION) + { + Client.Stats.Update(type.ToString(), OpenMetaverse.Stats.Type.Packet, dataLength, 0); + } + #endregion } internal void SendPacketFinal(NetworkManager.OutgoingPacket outgoingPacket) @@ -982,6 +988,13 @@ namespace OpenMetaverse Network.PacketInbox.Enqueue(incomingPacket); #endregion Inbox Insertion + + #region Stats Tracking + if (Client.Settings.TRACK_UTILIZATION) + { + Client.Stats.Update(packet.Type.ToString(), OpenMetaverse.Stats.Type.Packet, 0, packet.Length); + } + #endregion } protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent) diff --git a/Programs/examples/TestClient/Commands/Stats/NetstatsCommand.cs b/Programs/examples/TestClient/Commands/Stats/NetstatsCommand.cs new file mode 100644 index 00000000..f111e7ac --- /dev/null +++ b/Programs/examples/TestClient/Commands/Stats/NetstatsCommand.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; +using OpenMetaverse.Packets; + +namespace OpenMetaverse.TestClient +{ + public class NetstatsCommand : Command + { + public NetstatsCommand(TestClient testClient) + { + Name = "netstats"; + Description = "Provide packet and capabilities utilization statistics"; + Category = CommandCategory.Simulator; + } + + public override string Execute(string[] args, UUID fromAgentID) + { + StringBuilder output = new StringBuilder(); + if (!Client.Settings.TRACK_UTILIZATION) + { + return "TRACK_UTILIZATION is not enabled in Settings, statistics not available"; + } + + + StringBuilder packetOutput = new StringBuilder(); + StringBuilder capsOutput = new StringBuilder(); + + packetOutput.AppendFormat("{0,-30}|{1,4}|{2,4}|{3,-10}|{4,-10}|" + System.Environment.NewLine, "Packet Name", "Sent", "Recv", + " TX Bytes ", " RX Bytes "); + + capsOutput.AppendFormat("{0,-30}|{1,4}|{2,4}|{3,-10}|{4,-10}|" + System.Environment.NewLine, "Message Name", "Sent", "Recv", + " TX Bytes ", " RX Bytes "); + // " RX " + + long packetsSentCount = 0; + long packetsRecvCount = 0; + long packetBytesSent = 0; + long packetBytesRecv = 0; + + long capsSentCount = 0; + long capsRecvCount = 0; + long capsBytesSent = 0; + long capsBytesRecv = 0; + + foreach (KeyValuePair kvp in Client.Stats.GetStatistics()) + { + if (kvp.Value.Type == OpenMetaverse.Stats.Type.Message) + { + capsOutput.AppendFormat("{0,-30}|{1,4}|{2,4}|{3,-10}|{4,-10}|" + System.Environment.NewLine, kvp.Key, kvp.Value.TxCount, kvp.Value.RxCount, + FormatBytes(kvp.Value.TxBytes), FormatBytes(kvp.Value.RxBytes)); + + capsSentCount += kvp.Value.TxCount; + capsRecvCount += kvp.Value.RxCount; + capsBytesSent += kvp.Value.TxBytes; + capsBytesRecv += kvp.Value.RxBytes; + } + else if (kvp.Value.Type == OpenMetaverse.Stats.Type.Packet) + { + packetOutput.AppendFormat("{0,-30}|{1,4}|{2,4}|{3,-10}|{4,-10}|" + System.Environment.NewLine, kvp.Key, kvp.Value.TxCount, kvp.Value.RxCount, + FormatBytes(kvp.Value.TxBytes), FormatBytes(kvp.Value.RxBytes)); + + packetsSentCount += kvp.Value.TxCount; + packetsRecvCount += kvp.Value.RxCount; + packetBytesSent += kvp.Value.TxBytes; + packetBytesRecv += kvp.Value.RxBytes; + } + } + + capsOutput.AppendFormat("{0,30}|{1,4}|{2,4}|{3,-10}|{4,-10}|" + System.Environment.NewLine, "Capabilities Totals", capsSentCount, capsRecvCount, + FormatBytes(capsBytesSent), FormatBytes(capsBytesRecv)); + + packetOutput.AppendFormat("{0,30}|{1,4}|{2,4}|{3,-10}|{4,-10}|" + System.Environment.NewLine, "Packet Totals", packetsSentCount, packetsRecvCount, + FormatBytes(packetBytesSent), FormatBytes(packetBytesRecv)); + + return System.Environment.NewLine + capsOutput.ToString() + System.Environment.NewLine + System.Environment.NewLine + packetOutput.ToString(); + } + + public string FormatBytes(long bytes) + { + const int scale = 1024; + string[] orders = new string[] { "GB", "MB", "KB", "Bytes" }; + long max = (long)Math.Pow(scale, orders.Length - 1); + + foreach (string order in orders) + { + if ( bytes > max ) + return string.Format("{0:##.##} {1}", decimal.Divide( bytes, max ), order); + + max /= scale; + } + return "0"; + } + } +}