From 8135e2f4f330e2fcb3d951f55d5a67f3aaf225e2 Mon Sep 17 00:00:00 2001 From: Jim Radford Date: Thu, 8 May 2008 16:58:09 +0000 Subject: [PATCH] Enhances logging manager, Uses concept of Level and above for logging, The levels are Debug, Error, Info, Warn and None. Setting Settings.LOG_LEVEL to any of these settings will get you that level and above only. git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1850 52acb1d6-8a22-11de-b505-999d5b087335 --- libsecondlife/AgentManager.cs | 6 +- libsecondlife/Helpers.cs | 1 + libsecondlife/Logger.cs | 51 +++++++++-- libsecondlife/Settings.cs | 90 +++++++++++++++---- .../Commands/Inventory/UploadImageCommand.cs | 4 +- .../Commands/System/DebugCommand.cs | 33 +++++-- .../examples/TestClient/TestClient.cs | 2 +- libsecondlife/examples/sldump/sldump.cs | 2 +- 8 files changed, 150 insertions(+), 39 deletions(-) diff --git a/libsecondlife/AgentManager.cs b/libsecondlife/AgentManager.cs index 04f85822..65e93ae8 100644 --- a/libsecondlife/AgentManager.cs +++ b/libsecondlife/AgentManager.cs @@ -1447,13 +1447,13 @@ namespace libsecondlife /// Key of the source agent /// Key of the target object /// - /// - /// + /// The type from the enum + /// A unique for this effect public void PointAtEffect(LLUUID sourceAvatar, LLUUID targetObject, LLVector3d globalOffset, PointAtType type, LLUUID effectID) { ViewerEffectPacket effect = new ViewerEffectPacket(); - + effect.AgentData.AgentID = Client.Self.AgentID; effect.AgentData.SessionID = Client.Self.SessionID; diff --git a/libsecondlife/Helpers.cs b/libsecondlife/Helpers.cs index 1a8039d3..b19a7691 100644 --- a/libsecondlife/Helpers.cs +++ b/libsecondlife/Helpers.cs @@ -84,6 +84,7 @@ namespace libsecondlife /// public enum LogLevel { + None, /// Non-noisy useful information, may be helpful in /// debugging a problem Info, diff --git a/libsecondlife/Logger.cs b/libsecondlife/Logger.cs index da914a95..3ae7a358 100644 --- a/libsecondlife/Logger.cs +++ b/libsecondlife/Logger.cs @@ -1,3 +1,29 @@ +/* + * Copyright (c) 2007-2008, Second Life Reverse Engineering Team + * All rights reserved. + * + * - Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Neither the name of the Second Life Reverse Engineering Team nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + using System; using log4net; using log4net.Config; @@ -25,8 +51,6 @@ namespace libsecondlife /// log4net logging engine public static ILog LogInstance; - /// Whether the DEBUG level of logging is enabled - public static bool IsDebugEnabled; /// /// Default constructor @@ -43,7 +67,7 @@ namespace libsecondlife appender.Layout = new log4net.Layout.PatternLayout("%timestamp [%thread] %-5level - %message%newline"); BasicConfigurator.Configure(appender); - LogInstance.Info("No log configuration found, defaulting to console logging"); + //LogInstance.Info("No log configuration found, defaulting to console logging"); } } @@ -97,16 +121,27 @@ namespace libsecondlife switch (level) { case Helpers.LogLevel.Debug: - LogInstance.Debug(message, exception); + if(Settings.LOG_LEVEL == Helpers.LogLevel.Debug + || Settings.LOG_LEVEL == Helpers.LogLevel.Error + || Settings.LOG_LEVEL == Helpers.LogLevel.Info + || Settings.LOG_LEVEL == Helpers.LogLevel.Warning) + LogInstance.Debug(message, exception); break; case Helpers.LogLevel.Info: - LogInstance.Info(message, exception); + if(Settings.LOG_LEVEL == Helpers.LogLevel.Info + || Settings.LOG_LEVEL == Helpers.LogLevel.Debug + || Settings.LOG_LEVEL == Helpers.LogLevel.Error) + LogInstance.Info(message, exception); break; case Helpers.LogLevel.Warning: - LogInstance.Warn(message, exception); + if(Settings.LOG_LEVEL == Helpers.LogLevel.Warning + || Settings.LOG_LEVEL == Helpers.LogLevel.Debug) + LogInstance.Warn(message, exception); break; case Helpers.LogLevel.Error: - LogInstance.Error(message, exception); + if(Settings.LOG_LEVEL == Helpers.LogLevel.Error + || Settings.LOG_LEVEL == Helpers.LogLevel.Debug) + LogInstance.Error(message, exception); break; } } @@ -135,7 +170,7 @@ namespace libsecondlife [System.Diagnostics.Conditional("DEBUG")] public static void DebugLog(object message, SecondLife client) { - if (IsDebugEnabled) + if (Settings.LOG_LEVEL == Helpers.LogLevel.Debug) { if (client != null && client.Settings.LOG_NAMES) message = String.Format("<{0}>: {1}", client.Self.Name, message); diff --git a/libsecondlife/Settings.cs b/libsecondlife/Settings.cs index f0d12000..040abfd9 100644 --- a/libsecondlife/Settings.cs +++ b/libsecondlife/Settings.cs @@ -39,55 +39,74 @@ namespace libsecondlife /// happen at login or dynamically public class Settings { + #region Login/Networking Settings + /// Main grid login server public const string AGNI_LOGIN_SERVER = "https://login.agni.lindenlab.com/cgi-bin/login.cgi"; + /// Beta grid login server public const string ADITI_LOGIN_SERVER = "https://login.aditi.lindenlab.com/cgi-bin/login.cgi"; + /// The relative directory where external resources are kept public const string RESOURCE_DIR = "libsl_data"; /// Login server to connect to public string LOGIN_SERVER = AGNI_LOGIN_SERVER; - // Timeouts and Intervals + /// IP Address the client will bind to + public static System.Net.IPAddress BIND_ADDR = System.Net.IPAddress.Any; + + #endregion + #region Timeouts and Intervals /// Number of milliseconds before an asset transfer will time /// out public const int TRANSFER_TIMEOUT = 30 * 1000; + /// Number of milliseconds before a teleport attempt will time /// out public int TELEPORT_TIMEOUT = 40 * 1000; + /// Number of milliseconds before NetworkManager.Logout() will /// time out public int LOGOUT_TIMEOUT = 5 * 1000; + /// Number of milliseconds before a CAPS call will time out /// and try again /// Setting this too low will cause web requests to repeatedly /// time out and retry public int CAPS_TIMEOUT = 60 * 1000; + /// Number of milliseconds for xml-rpc to timeout public int LOGIN_TIMEOUT = 60 * 1000; + /// Milliseconds before a packet is assumed lost and resent public int RESEND_TIMEOUT = 4000; + /// Milliseconds without receiving a packet before the /// connection to a simulator is assumed lost public int SIMULATOR_TIMEOUT = 30 * 1000; + /// Milliseconds to wait for a simulator info request through /// the grid interface public int MAP_REQUEST_TIMEOUT = 5 * 1000; /// Number of milliseconds between sending pings to each sim public const int PING_INTERVAL = 2200; + /// Number of milliseconds between sending camera updates public const int DEFAULT_AGENT_UPDATE_INTERVAL = 500; + /// Number of milliseconds between updating the current /// positions of moving, non-accelerating and non-colliding objects public const int INTERPOLATION_INTERVAL = 250; + /// Millisecond interval between ticks, where all ACKs are /// sent out and the age of unACKed packets is checked public const int NETWORK_TICK_INTERVAL = 500; - // Sizes + #endregion + #region Sizes /// The initial size of the packet inbox, where packets are /// stored before processing @@ -108,7 +127,8 @@ namespace libsecondlife /// Network stats queue length (seconds) public int STATS_QUEUE_SIZE = 5; - // Configuration options (mostly booleans) + #endregion + #region Configuration opetions (mostly booleans) /// Enable to process packets synchronously, where all of the /// callbacks for each packet must return before the next packet is @@ -119,15 +139,14 @@ namespace libsecondlife /// would need to be rewritten as asynchronous code before this is /// feasible public bool SYNC_PACKETCALLBACKS = false; - /// Attach avatar names to log messages - public bool LOG_NAMES = true; - /// Log packet retransmission info - public bool LOG_RESENDS = true; + /// Enable/disable storing terrain heightmaps in the /// TerrainManager public bool STORE_LAND_PATCHES = false; + /// Enable/disable sending periodic camera updates public bool SEND_AGENT_UPDATES = true; + /// Enable/disable libsecondlife automatically setting the /// bandwidth throttle after connecting to each simulator /// The default libsecondlife throttle uses the equivalent of @@ -135,68 +154,88 @@ namespace libsecondlife /// set a throttle your connection will by default be throttled well /// below the minimum values and you may experience connection problems public bool SEND_AGENT_THROTTLE = true; + /// Enable/disable the sending of pings to monitor lag and /// packet loss public bool SEND_PINGS = false; + /// Should we connect to multiple sims? This will allow /// viewing in to neighboring simulators and sim crossings /// (Experimental) public bool MULTIPLE_SIMS = true; + /// If true, all object update packets will be decoded in to /// native objects. If false, only updates for our own agent will be /// decoded. Registering an event handler will force objects for that /// type to always be decoded. If this is disabled the object tracking /// will have missing or partial prim and avatar information public bool ALWAYS_DECODE_OBJECTS = true; + /// If true, when a cached object check is received from the /// server the full object info will automatically be requested public bool ALWAYS_REQUEST_OBJECTS = false; + /// Whether to establish connections to HTTP capabilities /// servers for simulators public bool ENABLE_CAPS = true; + /// Whether to decode sim stats public bool ENABLE_SIMSTATS = true; + /// The capabilities servers are currently designed to /// periodically return a 502 error which signals for the client to /// re-establish a connection. Set this to true to log those 502 errors public bool LOG_ALL_CAPS_ERRORS = false; + /// If true, any reference received for a folder or item /// libsecondlife is not aware of will automatically be fetched public bool FETCH_MISSING_INVENTORY = true; + /// If true, and SEND_AGENT_UPDATES is true, /// AgentUpdate packets will continuously be sent out to give the bot /// smoother movement and autopiloting public bool CONTINUOUS_AGENT_UPDATES = true; + /// If true, currently visible primitives and avatars will be /// stored in dictionaries inside Simulator.Objects. If /// false, a new Avatar or Primitive object will be created each time /// an object update packet is received public bool OBJECT_TRACKING = true; + + #endregion + #region Parcel Tracking + /// If true, parcel details will be stored in the /// Simulator.Parcels dictionary as they are received public bool PARCEL_TRACKING = true; + /// /// If true, an incoming parcel properties reply will automatically send /// a request for the parcel access list /// public bool ALWAYS_REQUEST_PARCEL_ACL = true; + /// /// if true, an incoming parcel properties reply will automatically send /// a request for the traffic count. /// public bool ALWAYS_REQUEST_PARCEL_DWELL = true; - // Texture cache + #endregion + #region Texture Cache /// /// If true, images downloaded from the server will be cached /// in a local directory /// public bool USE_TEXTURE_CACHE = false; + /// Path to store cached texture data public string TEXTURE_CACHE_DIR = RESOURCE_DIR + "/cache"; - /// IP Address the client will bind to - public static System.Net.IPAddress BIND_ADDR = System.Net.IPAddress.Any; + + #endregion + #region Misc + /// Default color used for viewer particle effects public LLColor DEFAULT_EFFECT_COLOR = new LLColor(255, 0, 0, 255); @@ -204,12 +243,26 @@ namespace libsecondlife /// Read-only since this value is dynamically fetched at login public int UPLOAD_COST { get { return priceUpload; } } - /// Enable/disable debugging log messages - public bool DEBUG - { - get { return Logger.IsDebugEnabled; } - set { Logger.IsDebugEnabled = value; } - } + #endregion + #region Logging Configuration + + /// + /// Get or set the minimum log level to output to the console by default + /// + /// If the library is not compiled with DEBUG defined and this level is set to DEBUG + /// You will get no output on the console. This behavior can be overriden by creating + /// a logger configuration file for log4net + /// + public static Helpers.LogLevel LOG_LEVEL = Helpers.LogLevel.Debug; + + /// Attach avatar names to log messages + public bool LOG_NAMES = true; + + /// Log packet retransmission info + public bool LOG_RESENDS = true; + + #endregion + #region Private Fields private SecondLife Client; private int priceUpload = 0; @@ -222,6 +275,9 @@ namespace libsecondlife Client.Network.RegisterCallback(Packets.PacketType.EconomyData, new NetworkManager.PacketCallback(EconomyDataHandler)); } + #endregion + #region Packet Callbacks + /// /// Gets the cost of uploading an asset to the grid /// @@ -233,5 +289,7 @@ namespace libsecondlife priceUpload = econ.Info.PriceUpload; } + + #endregion } } diff --git a/libsecondlife/examples/TestClient/Commands/Inventory/UploadImageCommand.cs b/libsecondlife/examples/TestClient/Commands/Inventory/UploadImageCommand.cs index a2f59a09..87acb1a7 100644 --- a/libsecondlife/examples/TestClient/Commands/Inventory/UploadImageCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/Inventory/UploadImageCommand.cs @@ -12,6 +12,7 @@ namespace libsecondlife.TestClient { AutoResetEvent UploadCompleteEvent = new AutoResetEvent(false); LLUUID TextureID = LLUUID.Zero; + DateTime start; public UploadImageCommand(TestClient testClient) { @@ -39,7 +40,7 @@ namespace libsecondlife.TestClient if (jpeg2k == null) return "Failed to compress image to JPEG2000"; Console.WriteLine("Finished compressing image to JPEG2000, uploading..."); - + start = DateTime.Now; DoUpload(jpeg2k, inventoryName); if (UploadCompleteEvent.WaitOne((int)timeout, false)) @@ -75,6 +76,7 @@ namespace libsecondlife.TestClient success, status, itemID, assetID)); TextureID = assetID; + Console.WriteLine(String.Format("Upload took {0}", DateTime.Now.Subtract(start))); UploadCompleteEvent.Set(); } ); diff --git a/libsecondlife/examples/TestClient/Commands/System/DebugCommand.cs b/libsecondlife/examples/TestClient/Commands/System/DebugCommand.cs index fbfde7c8..507d45a8 100644 --- a/libsecondlife/examples/TestClient/Commands/System/DebugCommand.cs +++ b/libsecondlife/examples/TestClient/Commands/System/DebugCommand.cs @@ -10,27 +10,42 @@ namespace libsecondlife.TestClient public DebugCommand(TestClient testClient) { Name = "debug"; - Description = "Turn debug messages on or off. Usage: debug [on/off]"; + Description = "Turn debug messages on or off. Usage: debug [level] where level is one of None, Debug, Error, Info, Warn"; } public override string Execute(string[] args, LLUUID fromAgentID) { if (args.Length != 1) - return "Usage: debug [on/off]"; + return "Usage: debug [level] where level is one of None, Debug, Error, Info, Warn"; - if (args[0].ToLower() == "on") + if (args[0].ToLower() == "debug") { - Client.Settings.DEBUG = true; - return "Debug logging is on"; + Settings.LOG_LEVEL = Helpers.LogLevel.Debug; + return "Logging is set to Debug"; } - else if (args[0].ToLower() == "off") + else if (args[0].ToLower() == "none") { - Client.Settings.DEBUG = false; - return "Debug logging is off"; + Settings.LOG_LEVEL = Helpers.LogLevel.None; + return "Logging is set to None"; + } + else if (args[0].ToLower() == "warn") + { + Settings.LOG_LEVEL = Helpers.LogLevel.Warning; + return "Logging is set to level Warning"; + } + else if (args[0].ToLower() == "info") + { + Settings.LOG_LEVEL = Helpers.LogLevel.Info; + return "Logging is set to level Info"; + } + else if (args[0].ToLower() == "error") + { + Settings.LOG_LEVEL = Helpers.LogLevel.Error; + return "Logging is set to level Error"; } else { - return "Usage: debug [on/off]"; + return "Usage: debug [level] where level is one of None, Debug, Error, Info, Warn"; } } } diff --git a/libsecondlife/examples/TestClient/TestClient.cs b/libsecondlife/examples/TestClient/TestClient.cs index 8da30428..476a76f8 100644 --- a/libsecondlife/examples/TestClient/TestClient.cs +++ b/libsecondlife/examples/TestClient/TestClient.cs @@ -39,7 +39,7 @@ namespace libsecondlife.TestClient RegisterAllCommands(Assembly.GetExecutingAssembly()); - Settings.DEBUG = true; + Settings.LOG_LEVEL = Helpers.LogLevel.Debug; Settings.LOG_RESENDS = false; Settings.STORE_LAND_PATCHES = true; Settings.ALWAYS_DECODE_OBJECTS = true; diff --git a/libsecondlife/examples/sldump/sldump.cs b/libsecondlife/examples/sldump/sldump.cs index b4efb0c9..01f0282d 100644 --- a/libsecondlife/examples/sldump/sldump.cs +++ b/libsecondlife/examples/sldump/sldump.cs @@ -86,7 +86,7 @@ namespace sldump client = new SecondLife(); // Turn off some unnecessary things - client.Settings.DEBUG = false; + Settings.LOG_LEVEL = Helpers.LogLevel.None; client.Settings.MULTIPLE_SIMS = false; // Throttle packets that we don't want all the way down client.Throttle.Land = 0;