Використання консолі при налагодженні ASP.Net додатків

Збираюся починати новий проект і поступово наближаюся до стадії написання деяких базових речей. Вирішив зібрати і систематизувати свої знання про деякі аспекти розробки ПЗ на платформі ASP.Net, Отримані за більш ніж рік комерційної розробки. У результаті вийшла ось така стаття. Вона не претендує на принципово нові речі, це все давно знають, в певному сенсі це своєрідні best practices. Все, що написано нижче, швидше за все стане в нагоді новачкам, але і досвідчені розробники зможуть почерпнути для себе що-небуть цікаве.


Ми з вами живемо в часи просунутих засобів розробки, отладчиков, що підтримують налагодження багатопоточних додатків, і багатьох інших надзвичайно корисних речей. Але як і всяке інше явище, такий прогрес має і свої мінуси – на не самих швидких машинах процес покрокової налагодження може перетвориться на кошмар розробника. Всі висне, дебаггер натякає вам, що пора б і проапгрейдить машину, після півгодинного путешевствія за кодом вашого дітища ви вкотре тиснете F10 і з жахом летите разом з викинутим десь у глибинах коду виключенням на самий верхній рівень, в дбайливо підставлений catch. Повідомлення виключення говорить вам, що в метод прийшли невірні аргументи, але абсолютно незрозуміло, звідки і яким чином вони взялися. Зціпивши зуби і озброївшись терпінням ви вкотре починаєте полювання за мерзенним багом …
У мене за спиною кілька років занять олімпіадами з програмування, які супроводжувалися написанням коду на самих різних інструментах від Turbo Pascal до Visual Studio 2008 в самих різних умовах. Хто не знає, олімпіади зазвичай проходять в різних ВНЗ. Іноді вбиті студентами комп'ютери висли до неможливості, а кількість вірусів на машині перевищувало всякі розумні рамки. Втім, в таких умовах перебувають усі учасники змагання, так що жаловатся нема часу – потрібно вирішувати поставлені завдання. Так от, за ці роки я засвоїв дуже важливу річ: чи не найкращий дебаггер – це консоль. Так-так, от та сама, звичайна чорна штука, за якою вгору повзуть сірі букви. Втім, кольору залежать від фантазії користувача.
Навіть на швидких машинах консоль зручна при налагодженні довгих ітеративних або рекурсивних обчислень – вона видає інформацію набагато швидше звичайного отладчика, відразу всю, разом з проміжними результатами, достатньо тільки вписати в цікавлять вас місцях Console.WriteLine, printf, system.out.println або аналог мовою, на якому ви пишете свої додатки. Консоль – це той же лог, але для його перегляду не треба лізти у файли, вона у вас на екрані і ви можете бачити відразу все, що вас цікавить. В кінці-кінців, я думаю, що багато хто з розробників використовували її хоч раз в житті для налагодження.
Сьогодні я вам покажу на прикладі ASP.Net MVC програми, як можна використовувати консоль при налагодженні і логгірованіі. Отже, приступимо.
По-перше, нам потрібно інізіалізіровать саму консоль. Для цього опишемо невеликий статичний клас ConsoleManager, в яких імпортні AllocConsole з kernel32.dll. Також додамо метод, який буде ініціалізувати консоль, встановлювати її висновок і чистити її перед стартом програми:

  public static class ConsoleManager
  {
[DllImport ("kernel32.dll", EntryPoint = "AllocConsole", CharSet = CharSet.Unicode)]
    private static extern bool AllocConsole();

    public static void InitializeConsoleManager()
    {
#if CONSOLE
      try
      {
        AllocConsole();
Console.SetOut (new TextWriter (new StreamWriter (Console.OpenStandardOutput (), Encoding.Default, 100)));
        Console.Clear();
      }
      catch (Exception)
      {
      }
#endif
    }
  }


Оскільки ми не хочемо, щоб консоль була видна під час нормальної роботи програми на сервері, код, ініціалізірущій її, ми уклали в директиву умовної компіляції і звичайно ж не забули визначити символ CONSOLE в Debug конфігурації проекту. Тепер ліземо в Global.asax і ініціалізували консоль на старті програми:

    protected void Application_Start()
    {
      ConsoleManager.InitializeConsoleManager();
      // …
    }

Ура, тепер при старті програми у нас з'являється чорне віконце програми! Дуже добре, але робота не цьому не закінчена – тепер ми трохи прикрасимо її. Практично неодмінним атрибутом будь-якого веб-додатки являються логи – оскільки часто вони є практично єдиною доказом, за якою можна відстежити помилку на виробничих серверах. Гріх не дублювати повідомлення логгер в нашу консоль – це економить хмару часу при налагодженні. Для того, щоб розрізняти, які повідомлення треба писати в і в файл і в консоль, а які тільки на консоль опишемо перерахування:

  public enum Severity
  {
    None,
    Event,
    Error,
    Debug,
  }

Все просто:


Для визначення кольору, відповідного певного типу повідомлення напишемо простенький extension-метод:

 

    public static ConsoleColor GetLogEntryColor(this Severity severity)
    {
      switch (severity)
      {
        case Severity.None:
          return ConsoleColor.DarkGray;
        case Severity.Event:
          return ConsoleColor.Green;
        case Severity.Error:
          return ConsoleColor.Red;
        case Severity.Debug:
          return ConsoleColor.Cyan;
        default:
throw new ArgumentException (string.Format ("Unknown severity:" {0} "", severity));
      }
    }

 


Тут треба зауважити, що набагато гарніше був би декларативний підхід:

  public enum Severity
  {
    [SeverityColor(ConsoleColor.DarkGray)]
    None,
    [SeverityColor(ConsoleColor.Green)]
    Event,
    [SeverityColor(ConsoleColor.Red)]
    Error,
    [SeverityColor(ConsoleColor.Cyan)]
    Debug,
  }

 


але з міркувань продуктивності я від нього відмовився. Питання спірне і можливо в майбутньому я до нього ще повернуся. Тепер власне залишилося тільки описати наш логгер, не забувши, що ASP.Net програми багатопотокові:

  public static class Logger
  {
    [ThreadStatic]
    private static Severity m_CurrentSeverity;

    /// <summary>
    /// Writes debug message to log
    /// </summary>
    public static void WriteToLog(string message)
    {
      WriteToLog(message, Severity.Debug);
    }

public static void WriteToLog (string message, Severity severity)
    {
      lock (typeof(Logger))
      {
        m_CurrentSeverity = severity;
        WriteLineStart();
        WriteLine(message);
      }
    }

    private static void WriteLine(string message)
    {
      Write(message + Environment.NewLine);
    }

private static void Write (string message, params object [] parameters)
    {
      Write(string.Format(message, parameters));
    }

    private static void Write(string message)
    {
Console.ForegroundColor = m_CurrentSeverity.GetLogEntryColor ();
      Console.Write(message);
if (m_CurrentSeverity == Severity.Error / / m_CurrentSeverity == Severity.Event)
      {
        // file logging
      }
    }

    private static void WriteLineStart()
    {
      Write(“{0} -> “, DateTime.Now);
    }
  }

 


Всі навмисно спрощено для більшого розуміння. Консоль під час налагодження виглядає застосовано ось так:

З власного досвіду скажу, що з такою консоллю життя девелопера стає набагато легше.
Спасибі.
UPD. Мені тут підказали, що існує альтернативний інструмент – програма Debug View, яка реалізує практично ідентичну функціональність.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*