Основы ведения журналов Silverlight и / или лучшие практики - PullRequest
25 голосов
/ 23 октября 2008

Теперь, когда Silverlight 2 наконец-то отправлен. Мне интересно, если кто-нибудь собрал какие-либо каркасы для этого, может быть что-то вроде регистрация в корпоративной библиотеке или log4net ? Мне интересно то, что может выполнять трассировку на стороне клиента, а также регистрировать сообщения на сервере.

Пока что единственный проект, который я нашел, это Clog on CodeProject . Кто-нибудь использовал это? Что вы думаете об этом?

Ответы [ 6 ]

14 голосов
/ 07 июля 2010

Если вы готовы на минуту снять шлем астронавта, ниже приведен облегченный регистратор, который я написал для 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
}
6 голосов
/ 25 мая 2009

, если вы просто хотите выводить отладочные сообщения на консоль. Вы можете использовать механизм браузера 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 голосов
/ 28 октября 2008

Я собираюсь вникнуть во что-то подобное для продукта, который мы написали. Я рассматриваю возможность использования PostSharp для Silverlight для добавления ведения журнала на стороне клиента в качестве аспекта.

Я с большим успехом использовал проект NLog в полной версии .NET Framework и Compact Framework, поэтому я, скорее всего, возьму существующий код инфраструктуры и добавлю несколько целей ведения журнала:

  • Стандартная цель System.Diagnostics для включения захвата с использованием DebugView и т. Д.
  • Асинхронная цель веб-службы, аналогичная цели в NLog.
  • Изолированная цель хранения с отложенной передачей в семантику сервера.

Я кратко рассмотрел Clog, и он, похоже, страдает одним существенным недостатком - он не может регистрировать сбой соединения. Итак, если ваш веб-сервер постоянно подключен к сети, да, он будет работать, но когда возникают проблемы в восходящем потоке или на самом сервере, все данные журнала теряются и могут даже привести к сбою приложения.

2 голосов
/ 24 ноября 2010

Вы также можете использовать это: http://silverlightlogging.codeplex.com/

0 голосов
/ 14 сентября 2009

Я использую окна JavaScript и делаю его скриптовым в Silverlight. Для «производства» я могу отключить это окно, но при этом сохранить строки журнала в памяти, а затем, если что-то пойдет не так, отправить это на сервер. Таким образом, я получаю лучшее из обоих миров - простая регистрация клиента в режиме реального времени для отладки и журналы для удаленных посмертных ситуаций, с которыми могут столкнуться пользователи.

0 голосов
/ 03 ноября 2008

Я закончил тем, что написал новую структуру ведения журнала с нуля, которая устраняет этот недостаток. Я создал локальную очередь, которая будет получать сообщения журнала / трассировки, а затем выполнять фильтрацию и отправлять их на сервер. Затем очередь будет поддерживаться изолированным хранилищем, поэтому даже если клиент постоянно отключается для этого сеанса, сообщения будут отправляться, когда он снова будет в сети.

...