【问题标题】:Silverlight Logging framework and/or best practicesSilverlight 日志记录框架和/或最佳实践
【发布时间】:2010-09-18 17:28:15
【问题描述】:

现在 Silverlight 2 终于发货了。我想知道是否有人为它整理了任何日志框架,也许像enterprise library logginglog4net?我对可以执行跟踪客户端并将消息记录到服务器的东西很感兴趣。

到目前为止,我发现的唯一项目是Clog on CodeProject。有人用过这个吗?您对此有何看法?

【问题讨论】:

    标签: logging silverlight-2.0


    【解决方案1】:

    如果您愿意暂时摘下宇航员的头盔,下面是我为 Silverlight 编写的轻量级记录器,用于客户端日志记录(主要用于 WCF 操作,但可能用于任何错误)。

    它最初用于 iPhone 应用程序的 Monotouch,并已针对IsolateStorage 进行了改编。如果需要,您可以使用Read 方法在文本框中显示。在 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
    }
    

    【讨论】:

    • Read 在文本框中显示的方法?使用 IsolatedStorageFile 的另一种选择?
    【解决方案2】:

    如果您只想将调试消息输出到控制台。您可以使用浏览器的 console.log 机制。我为此编写了一个扩展方法。你可以在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;
    
        }
    

    【讨论】:

      【解决方案3】:

      我即将为我们编写的产品深入研究类似的东西。我正在考虑使用 PostSharp for Silverlight 来添加客户端日志记录作为一个方面。

      我之前在完整的 .NET Framework 和 Compact Framework 下使用 NLog 项目取得了巨大成功,因此我很可能会采用现有的框架代码并添加一些日志记录目标:

      • 标准 System.Diagnostics 目标,用于启用使用 DebugView 等进行捕获。
      • 类似于 NLog 中的异步 Web 服务目标。
      • 具有延迟传输到服务器语义的隔离存储目标。

      我简要地查看了 Clog,它似乎存在一个重大缺陷 - 它无法记录连接失败。因此,假设您的 Web 服务器一直在线,是的,它会工作,但是当上游或服务器本身出现问题时,日志记录数据将全部丢失,甚至可能导致您的应用程序崩溃。

      【讨论】:

      • System.DiagnosticsDebugView 对开发环境很好(而且更好),而不是生产环境(我无法访问生产和使用 DebugView)
      【解决方案4】:

      你也可以使用这个:http://silverlightlogging.codeplex.com/

      【讨论】:

        【解决方案5】:

        我最终从头开始编写了一个新的日志框架来解决这个缺陷。我创建了一个本地队列,它将获取日志/跟踪消息,然后进行过滤并将它们发送到服务器。然后队列将由独立存储支持,因此即使客户端在该会话中永久离线,消息也会在它重新在线时发送。

        【讨论】:

          【解决方案6】:

          我正在使用 JavaScript 窗口并使其可在 Silverlight 中编写脚本。对于“生产”,我可以关闭此窗口,但仍将日志行保存到内存中,然后如果出现问题,将其发送到服务器。这样我就可以两全其美 - 在客户端上进行简单的实时日志记录以进行调试,并记录用户可能遇到的远程事后分析情况。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-11-02
            • 1970-01-01
            • 2018-03-27
            • 2021-08-05
            • 2010-10-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多