Now that Silverlight 2 has finally shipped. I'm wondering if anyone has put together any logging frameworks for it, maybe something like enterprise library logging or log4net? I'm interesting in something that can perform tracing client side and also log messages to the server.
So far the only project I have found is Clog on CodeProject. Has anyone used this? What were your thoughts on it?
Look for a logging framework with an elegant solution to this problem (or at least an elegant option). Of particular concern, from a codebase cleanliness perspective, are the impact on code noise and ease of unit test writing. Make sure that the framework you choose has guidance on how to handle these concerns.
Logging frameworks offer flexibility and prevent you from reinventing the wheel.
If you're willing to take your astronaut's helmet off for a minute, below is a lightweight logger I've written for Silverlight, for client-side logging (for use mainly with WCF operations but could be for any errors).
It was originally used in Monotouch for iPhone apps, and has been adapted for IsolateStorage
. You can use the Read
method to display in a textbox if needed. Tested in SL4.
/// <summary> /// A lightweight logging class for Silverlight. /// </summary> public class Log { /// <summary> /// The log file to write to. Defaults to "dd-mm-yyyy.log" e.g. "13-01-2010.log" /// </summary> public static string LogFilename { get; set; } /// <summary> /// Whether to appendthe calling method to the start of the log line. /// </summary> public static bool UseStackFrame { get; set; } static Log() { LogFilename = string.Format("{0}.log", DateTime.Today.ToString("dd-MM-yyyy")); UseStackFrame = false; } /// <summary> /// Reads the entire log file, or returns an empty string if it doesn't exist yet. /// </summary> /// <returns></returns> public static string ReadLog() { string result = ""; IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForSite(); if (storage.FileExists(LogFilename)) { try { using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(LogFilename,FileMode.OpenOrCreate,storage)) { using (StreamReader reader = new StreamReader(stream)) { result = reader.ReadToEnd(); } } } catch (IOException) { // Ignore } } return result; } /// <summary> /// Writes information (not errors) to the log file. /// </summary> /// <param name="format">A format string</param> /// <param name="args">Any arguments for the format string.</param> public static void Info(string format, params object[] args) { WriteLine(LoggingLevel.Info, format, args); } /// <summary> /// Writes a warning (non critical error) to the log file /// </summary> /// <param name="format">A format string</param> /// <param name="args">Any arguments for the format string.</param> public static void Warn(string format, params object[] args) { WriteLine(LoggingLevel.Warn, format, args); } /// <summary> /// Writes a critical or fatal error to the log file. /// </summary> /// <param name="format">A format string</param> /// <param name="args">Any arguments for the format string.</param> public static void Fatal(string format, params object[] args) { WriteLine(LoggingLevel.Fatal, format, args); } /// <summary> /// Writes the args to the default logging output using the format provided. /// </summary> public static void WriteLine(LoggingLevel level, string format, params object[] args) { string message = string.Format(format, args); // Optionally show the calling method if (UseStackFrame) { var name = new StackFrame(2, false).GetMethod().Name; string prefix = string.Format("[{0} - {1}] ", level, name); message = string.Format(prefix + format, args); } Debug.WriteLine(message); WriteToFile(message); } /// <summary> /// Writes a line to the current log file. /// </summary> /// <param name="message"></param> private static void WriteToFile(string message) { try { IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForSite(); bool b = storage.FileExists(LogFilename); using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(LogFilename,FileMode.Append,storage)) { using (StreamWriter writer = new StreamWriter(stream)) { writer.WriteLine("[{0}] {1}", DateTime.UtcNow.ToString(), message); } } } catch (IOException) { // throw new Catch22Exception(); } } } /// <summary> /// The type of error to log. /// </summary> public enum LoggingLevel { /// <summary> /// A message containing information only. /// </summary> Info, /// <summary> /// A non-critical warning error message. /// </summary> Warn, /// <summary> /// A fatal error message. /// </summary> Fatal }
if you just want to output debug messages to the console. You could use the Browser's console.log mechanism. I coded a extension method for that. You can find on my blog.
// http://kodierer.blogspot.com.es/2009/05/silverlight-logging-extension-method.html public static string Log(string message) { var msgLog = ""; try { HtmlWindow window = HtmlPage.Window; //only log if a console is available var isConsoleAvailable = (bool)window.Eval("typeof(console) != 'undefined' && typeof(console.log) != 'undefined'"); if (!isConsoleAvailable) return "isConsoleAvailable " + isConsoleAvailable; var createLogFunction = (bool)window.Eval("typeof(ssplog) == 'undefined'"); if (createLogFunction) { // Load the logging function into global scope: string logFunction = @"function ssplog(msg) { console.log(msg); }"; string code = string.Format(@"if(window.execScript) {{ window.execScript('{0}'); }} else {{ eval.call(null, '{0}'); }}", logFunction); window.Eval(code); } // Prepare the message DateTime dateTime = DateTime.Now; string output = string.Format("{0} - {1} - {2}", dateTime.ToString("u"), "DEBUG", message); // Invoke the logging function: var logger = window.Eval("ssplog") as ScriptObject; logger.InvokeSelf(output); } catch (Exception ex) { msgLog = "Error Log " + ex.Message; } return msgLog; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With