logging silverlight-2.0

Marco de trabajo de Silverlight Logging y/o mejores prácticas



silverlight-2.0 (6)

Ahora que Silverlight 2 finalmente ha sido enviado. Me pregunto si alguien ha log4net marcos de trabajo de registro, tal vez algo así como el registro de la biblioteca empresarial o log4net . Me interesa algo que pueda realizar el seguimiento del cliente y también registrar mensajes en el servidor.

Hasta ahora, el único proyecto que he encontrado es Clog en CodeProject . Alguien ha usado esto? ¿Cuáles fueron tus pensamientos sobre eso?


Estoy a punto de profundizar en algo similar para un producto que hemos escrito. Estoy considerando usar PostSharp para Silverlight para agregar el registro del lado del cliente como un aspecto.

He utilizado el proyecto NLog con gran éxito antes en todo el .NET Framework y el Compact Framework, así que lo más probable es que tome el código del framework existente y agregue algunos objetivos de registro:

  • Un objetivo estándar de System.Diagnostics para permitir la captura usando DebugView, etc.
  • Un destino de servicio web asincrónico similar al de NLog.
  • Un objetivo de almacenamiento aislado con transferencia diferida a la semántica del servidor.

Miré brevemente a Clog y parece sufrir de un defecto importante: no puede registrar un error de conexión. Por lo tanto, suponiendo que su servidor web esté en línea todo el tiempo, sí, funcionará, pero cuando surgen problemas en el servidor o en el servidor, la información de registro se pierde y puede incluso bloquear su aplicación.


Estoy usando una ventana de JavaScript y haciendo que sea script en Silverlight. Para "producción", puedo desactivar esta ventana, pero aun así guardar las líneas de registro en la memoria, y luego, si algo sale mal, enviarlo al servidor. De esa forma obtengo lo mejor de ambos mundos: registro simple y en tiempo real en el cliente para la depuración y registros de situaciones remotas post-mortem que los usuarios pueden encontrar.



Si está dispuesto a quitarse el casco de su astronauta por un minuto, a continuación encontrará un registrador liviano que he escrito para Silverlight, para el registro del lado del cliente (para usar principalmente con las operaciones de WCF, pero podría ser para cualquier error).

Se usó originalmente en Monotouch para aplicaciones de iPhone, y se ha adaptado para IsolateStorage . Puede usar el método Read para mostrar en un cuadro de texto si es necesario. Probado en 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 }


Terminé escribiendo un nuevo marco de registro desde cero que soluciona este problema. Creé una cola local que obtendrá los mensajes de registro / seguimiento y luego los filtraré y los enviaré al servidor. Luego, la cola estará respaldada por Almacenamiento aislado, por lo que incluso si el cliente se desconecta de forma permanente para esa sesión, los mensajes se enviarán cuando vuelva a estar en línea.


si solo desea enviar mensajes de depuración a la consola. Puede usar el mecanismo console.log del navegador. Codifiqué un método de extensión para eso. Puedes encontrar en mi 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; }