IT записки

NLog — логирование в C#

Posted in C#, Поддержка by borismor on 28 сентября, 2010

Внимание! Сайт переехал. Перейдите на новую версию.

Недавно понадобилось прикрутить лог в программе на C#. Логи — самый лучший способ найти ошибку и отследить все действия пользователя. Я фанат логов 😀
Первая мысль была написать что-то свое. Но любопытство и лень пересилила и я сделал поиск в гугле (не напрасно!). Наткнулся на прекрасную библиотеку NLog. По функционалу библиотека на большой высоте. Бесплатная и хорошо настраиваемая (спец. конфигурационный файл). 2 (!!!) десятка типов всяких логов. Надо писать лог в базу? Пожалуйста. Надо отсылать по почте? Нет ничего проще. и т.д.
Документация хороша. В дистрибутив включены несколько десятков примеров конфиг-файлов. Так что очень легко можно разобраться.

Пара ссылок для закрепления материала:
Официальны сайт NLog [eng]
«Hello, NLog» — [рус.] статья с блога Ильи Дубаденко
«Introduction to NLog» — [eng] CodeProject
Раздел блога «О разработке на .Net» посвященный NLog [рус.]
Логгирование приложения на C# в базу данных FireBird Embedded с помощью NLog 2.0 [рус.]

Пример. Хотим лог который будет создаваться заново при каждом запуске приложения.
Создаем конф-лог.

  1. В Visula Studio выбираем «Project» — «Add New Item…»
  2. Выбираем «Empty NLog configuration file»
  3. Выбираем появившийся файл .conf в «Solution Explorer»
  4. Изменяем его проперти «Copy to Output Diretory» на «Copy always». Конф-файл будет всегда копироваться туда где строиться exe

Теперь содержание самого файла.
В нем содержит 2 тега после корня

  • Targets – В нем идет оисание лога т.е. источника для записи данных
  • Rules – Правила указывающие в какие случаях писать в определенный лог
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <!-- make sure to set 'Copy To Output Directory' option for this file -->
  <!-- go to http://nlog-project.org/wiki/Configuration_file for more information -->

<targets>
    <target name="run_log"
    xsi:type="File"
    layout="${longdate}|${level}| ${message}"
    deleteOldFileOnStartup="True"
    concurrentWrites="true"
    KeepFileOpen ="False"
    fileName="${basedir}/Application.log"
    encoding="win-1251"/>
</targets>

<rules>
    <logger name="*" minlevel="Debug" writeTo="run_log" />
    <logger name="*" minlevel="Trace" writeTo="run_log" />
</rules>
</nlog>

Расписываться не буду. Описание этого target`са можно посмотреть в хэлпе по библиотеке.
Теперь код. Лог я поместил сразу в main и сдела статичным.

using NLog;

namespace Test
{
    static class Program
    {
        public static Logger log;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                log = LogManager.GetCurrentClassLogger();

                log.Trace("Version: {0}", Environment.Version.ToString());
                log.Trace("OS: {0}", Environment.OSVersion.ToString());
                log.Trace("Command: {0}", Environment.CommandLine.ToString());

                NLog.Targets.FileTarget tar = (NLog.Targets.FileTarget)LogManager.Configuration.FindTargetByName("run_log");
                tar.DeleteOldFileOnStartup = false;
            }
            catch (Exception e)
            { 
                MessageBox.Show("Ошибка работы с логом!\n"+ e.Message);
            }

            // ловим все не обработанные исключения
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_Exception);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmMain());
        }
    }
}

Теперь из любого места программы можно записать данные в лог. Например.
Program.log.Trace(«run {0}», this.Text);

Update 27.08.2012
Для записи в SQLite прописываем:

    <target name="Database" xsi:type="Database" keepConnection="true"
            useTransactions="false"
            dbProvider="System.Data.SQLite.SQLiteConnection, System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"
            connectionString="Data Source=${basedir}\log.db;Version=3;"
            commandText="INSERT into LOGTABLE(Timestamp, Loglevel, Message) values(@Timestamp, @Loglevel, @Message)">
      <parameter name="@Timestamp" layout="${longdate}"/>
      <parameter name="@Loglevel" layout="${level:uppercase=true}"/>
      <parameter name="@Message" layout="${message}"/>
    </target>

log.db находится в каталоге программы.
Для создания таблицы в log.db выполните команду:

BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS LOGTABLE (Message TEXT, Loglevel varchar(50), Timestamp varchar(100));  
COMMIT;

Для записи в формате CSV добавляет в конфиг следующий раздел:

    <target name="csv" xsi:type="File" fileName="${basedir}/log.csv">
      <layout xsi:type="CSVLayout">
        <column name="time" layout="${longdate}" />
        <column name="message" layout="${message}" />
      </layout>
    </target>
Tagged with: ,

комментариев 9

Subscribe to comments with RSS.

  1. fuzzokolobok said, on 29 сентября, 2010 at 2:39 дп

    Вообще везде в промышленности, где я был или что-то видел используется log4net. Не берусь судить или сравнивать — т.к. не пробовал, но вот дела обстоят так

  2. BorisMor said, on 29 сентября, 2010 at 4:21 дп

    Тоже смотрел log4net. Распространенность скорее всего связанна что библиотека хорошая и давно вышла. Но вот так же давно уже и не выходят новые версии.
    На офиц.сайте прописана поддержка Framework 2.0.
    Плюс у NLog возможностей больше. Хотя большая часть из них никому и не сдалась)
    В принципе log4net и NLog очень схожи. Даже структура конфигурационного файла в чем то похожа.

  3. Gor said, on 8 октября, 2010 at 11:27 дп

    Мы используем log4net и очень доволны. Что нравится: быстрый, удобный, легко конфигурируемый. Кроме того многие сторонние библиотеки также используют log4net, что позволяет единообразно конфигурировать логи системы.
    P.S. Есть еще http://msdn.microsoft.com/en-us/library/ff647242.aspx

  4. Ozzy said, on 12 декабря, 2011 at 2:15 пп

    А мы используем Genome. Там есть гибкая подсистема логирования: http://genome-sdk.net Вот wiki по логированию: http://kenai.com/projects/genome-sdk/pages/LoggingSystem_ru

  5. gotter said, on 7 сентября, 2012 at 11:25 дп

    Для небольших приложений подойдет и такой класс: http://ivanp.ru/%D0%BF%D0%B8%D1%88%D0%B5%D0%BC-%D0%BB%D0%BE%D0%B3%D0%B8-%D0%BD%D0%B0-c-net-%D0%BB%D0%B5%D0%B3%D0%BA%D0%B8%D0%B9-%D1%81%D0%BF%D0%BE%D1%81%D0%BE%D0%B1/
    Когда подсистема логирования весит не меньше чем сама логика — не очень хорошо.

  6. C# и SQLite « IT записки said, on 16 октября, 2012 at 5:46 пп

    […] Далее несколько функций для работы с базой. База зовется как exe файл только расширение db. В коде встречается “Program.log” – это объект для логирования. […]

  7. MaksTR said, on 10 мая, 2013 at 6:50 дп

    NLog на данный момент являеться оптимальным вариантом под C#. log4net неплох но уже давно не развиваеться. логирование с помощью Microsoft Enterprise Library не очень удобно и уступает по возможностям NLog. в Геноме логер работает через ихний же IoC-контейнер, что являеться лишней тратой ресурсов, да и в целом библиотека тяжеловата. а писать свой велосипед стоит разве что начинающим для общего развития, в комерческих проектах велосипедам не место.

  8. Аноним said, on 25 марта, 2014 at 3:03 дп

    В Visula Studio выбираем «Project» — «Add New Item…»
    Выбираем «Empty NLog configuration file»
    Выбираем появившийся файл .conf в «Solution Explorer»
    Изменяем его проперти «Copy to Output Diretory» на «Copy always». Конф-файл будет всегда копироваться туда где строиться exe
    —————-
    Объясните подробнее, и вообще было бы хорошо писать не сравнение, а именно Getting Started для системы которую описываете, чтобы КПД было выше

  9. Аноним said, on 25 марта, 2014 at 3:04 дп

    Почему не написали что надо добавить private static Logger log = LogManager.GetCurrentClassLogger();


Оставьте комментарий