konfiguracja

NLog i logowanie do kilku plików na różny sposób.

W jednym z projektów mam serwis, który zajmuje się przetwarzaniem plików i dla każdego takiego przetwarzania muszę dostarczyć log tego co się zadziało, począwszy od rzeczy typu:

_log.Info("Task id: {0}", taskId);

a skończywszy na wyjątkach, zarówno tych, które dotyczą funkcjonowania samego serwisu, a skończywszy na tych, które wystąpiły w kontekście danego zadania. Najważniejsze jednak jest to, że muszą być dwa pliki logu:
1. dla użytkownika z informacją co się działo w każdym zadaniu,
2. dla wygody administratora chcę mieć jeden wór, w którym będzie zalogowane wszystko bez konieczności latania po wszystkich plikach z pkt 1.

Konfiguracja mojego NLoggera wygląda następująco:

<?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">
   <targets>
      <target name="TaskLogFile" xsi:type="File" fileName=""
         layout="${longdate}|${level:uppercase=true}|${message}" />
      <target name="ServiceLogFile" xsi:type="File"
         fileName="c:\Temp\Log/${date:format=yyyyMMdd}_FilesProcessingService.txt"
         layout="${longdate}|${level:uppercase=true}|${message}" />
   </targets>
   <rules>
      <logger name="*" minlevel="Trace" writeTo="TaskLogFile" />
   </rules>
   <rules>
      <logger name="*" minlevel="Trace" writeTo="ServiceLogFile" />
   </rules>
</nlog>

Mam dwa loggery, których nazwy wyjaśniają do czego każdy służy, zaś w kodzie mam metodę, która dla każdego przetwarzanego zadania konfiguruje target na nowo. Pusty fileName w targecie „TaskLogFile” powoduje, że nic do niego nie jest logowane. Użyteczny feature.

private string SetLogFilePath()
{
   var target = (FileTarget)LogManager.Configuration.FindTargetByName("TaskLogFile");
   var fileName = $@"{Path.Combine(
      ConfigurationManager.AppSettings["TaskLogFileDirectory"], 
      Guid.NewGuid().ToString())}.txt";
   target.FileName = fileName;
   return fileName;
}

Jak widać cała rekonfiguracja ma na celu utworzenie nowego pliku, do którego będą logowane dane danego zadania. A teraz główna metoda serwisu:

private void ProcessFiles(object obj)
{
   _log.Info("Service has started ...");
   try
   {
      /*łączenie się z bazą danych*/
      foreach (var taskId in db.Fetch<int>(ProcessingFileTaskQueries.GetNotProcessedQuery()))
      {
         var task = db.SingleById<ProcessingFileTask>(taskId);
         if (task != null)
         {
            //do tego miejsca wszystko jest logowane do pliku 
            //${date:format=yyyyMMdd}_FilesProcessingService.txt
            task.LogFilePath = SetLogFilePath();
            //wszelkie logowanie dla danego tasku robimy od tego miejsca, po ustawieniu loggera.
            //ale te same informacje pojawiają się także w pliku 
            //${date:format=yyyyMMdd}_FilesProcessingService.txt
         }
      }
   }
   catch (Exception e)
   {
      _log.Error(e);
   }
}

W ten sposób osiągnąłem funkcjonalność, która loguje do dwóch osobnych plików
1. dla konkretnego zadania do udostępnienia dla użytkownika w aplikacji
2. jeden „wór” z logami wszystkich zadań i samego serwisu.

Czy można inaczej, lepiej? Pewnie można.

 

Leave a Reply

Your email address will not be published. Required fields are marked *