Silverlight日志框架和/或最佳实践

25

现在 Silverlight 2 终于发布了。我想知道是否有人为它编写了任何日志框架,比如像企业库日志log4net这样的框架?我希望找到一个能够在客户端执行跟踪并将消息记录到服务器的工具。

到目前为止,我只发现了 Clog 这个项目,在 CodeProject 上。有人用过吗?你对它有什么看法?

6个回答

14
如果您愿意暂时摘下宇航员头盔,下面是我为Silverlight编写的轻量级记录器,用于客户端日志记录(主要用于WCF操作,但也可用于任何错误)。它最初用于Monotouch iPhone应用程序,并已适应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的替代方法吗? - Kiquenet

6

如果你只是想将调试信息输出到控制台,可以使用浏览器的console.log机制。我为此编写了一个扩展方法,你可以在我的博客上找到它。

    // 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;

    }

4

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

我以前在完整的.NET Framework和紧凑的框架下成功地使用过NLog项目,所以我很可能会采用现有的框架代码并添加一些日志记录目标:

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

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


System.DiagnosticsDebugView非常适合开发环境,但不适用于生产环境(我无法访问生产环境并使用_DebugView_)。 - Kiquenet

2

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接