K.B.Rajesh Ответов: 1

C# - log4net log не регистрирует должным образом асинхронный метод


Мы используем log4net в нашем приложении. Реальная проблема заключается в том, что сообщения журнала не регистрируются должным образом в асинхронном методе.

У нас есть два приложения, первое-консольное приложение, а второе-a .Net Web API.

Мы используем асинхронную логику в консольном приложении. Мы вызываем службу API в этом консольном приложении с помощью асинхронного метода. Log4net реализован и в этом API-приложении.

Мы зарегистрировали все запросы в этой службе API, но иногда журнал не был должным образом зарегистрирован или пропущен в файле журнала.

Пример: консольное приложение, вызывающее 1000 раз в этой службе API. Но API-сервис не записывает все запросы, пропускает 10 или 20 запросов.

Я предоставил свой пример кода API.

Кто-нибудь, пожалуйста, помогите.

Program.cs
------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using log4net;
using System.Reflection;

namespace Log4NetAsynchronous
{
    class Program
    {
        public static async Task<int> Method1(int i)
        {
            return await Task.Run(() =>
            {
                Console.WriteLine("Method 1 ==> " + i.ToString() + "\n");
                Logger.LogMsg("Method 1 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method1, Enums.LogType.INFO);
                Logger.LogMsg("Method 1 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method1, Enums.LogType.DEBUG);
                Logger.LogMsg("Method 1 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method1, Enums.LogType.ERROR);
                Task.Delay(1500).Wait();
                return 1;
            });
        }

        public static async Task<int> Method2(int i)
        {
            return await Task.Run(() =>
            {

                Console.WriteLine("Method 2 ==> " + i.ToString() + "\n");
                Logger.LogMsg("Method 2 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method2, Enums.LogType.INFO);
                Logger.LogMsg("Method 2 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method2, Enums.LogType.DEBUG);
                Logger.LogMsg("Method 2 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method2, Enums.LogType.ERROR);
                Task.Delay(1500).Wait();
                return 1;
            });
        }

        public static async Task<int> Method3(int i)
        {
            return await Task.Run(() =>
            {

                Console.WriteLine("Method 3 ==> " + i.ToString() + "\n");
                Logger.LogMsg("Method 3 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method3, Enums.LogType.INFO);
                Logger.LogMsg("Method 3 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method3, Enums.LogType.DEBUG);
                Logger.LogMsg("Method 3 -> Line Number: " + i.ToString() + Environment.NewLine, Enums.Methods.Method3, Enums.LogType.ERROR);
                Task.Delay(1500).Wait();
                return 1;
            });
        }

        public static async Task<IEnumerable<int>> Invoke1()
        {
            var method1 = new List<Task<int>>();
            for (int i = 1; i <= 3; i++)
            {
                method1.Add(Method1(i));
            }

            return await Task.WhenAll(method1);
        
        }
        public static async Task<IEnumerable<int>> Invoke2()
        {
            var method2 = new List<Task<int>>();
            for (int i = 1; i <= 5; i++)
            {
                method2.Add(Method2(i));
            }

            return await Task.WhenAll(method2);
        }
        public static async Task<IEnumerable<int>> Invoke3()
        {
            var method3 = new List<Task<int>>();
            for (int i = 1; i <= 5; i++)
            {
                method3.Add(Method3(i));
            }

            return await Task.WhenAll(method3);
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Start");
            var res1 = Invoke1();
            var res2 = Invoke2();
            var res3 = Invoke3();
            Console.WriteLine("Succes");
            Console.ReadKey();
        } 
    }
}
--------------

Logger.cs
--------------
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Log4NetAsynchronous
{
    public static class Logger
    {
        private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        public static void LogMsg(string msg, Enums.Methods Methods, Enums.LogType logType)
        {
            string strLogFileName = String.Empty;
            switch (Methods)
            {
                case Enums.Methods.Method1:
                    strLogFileName = "Method1";
                    break;

                case Enums.Methods.Method2:
                    strLogFileName = "Method2";
                    break;

                case Enums.Methods.Method3:
                    strLogFileName = "Method3";
                    break;
                default:
                    strLogFileName = "Method1";
                    break;
            }

            log4net.GlobalContext.Properties["LogFileName"] = strLogFileName;
            log4net.Config.XmlConfigurator.Configure();

            ILog log = LogManager.GetLogger(typeof(Logger));

            string timeStamp = string.Empty;

            switch (logType)
            {
                case Enums.LogType.DEBUG:
                    log.Debug(msg);
                    break;

                case Enums.LogType.INFO:
                    log.Info(msg);
                    break;

                case Enums.LogType.ERROR:
                    log.Error(msg);
                    break;
               default:
                    log.Info(msg);
                    break;
            }
        }
    }
}
-----------------

Enums.cs
-----------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Log4NetAsynchronous
{
    public class Enums
    {
        public enum Methods : int
        {
            Method1 = 1,

            Method2 = 2,

            Method3 = 3,
        }

        public enum LogType : int
        {
            DEBUG = 0,

            INFO = 1,

            WARN = 2,

            ERROR = 3,

            FATAL = 4,

            LOGDBINFO = 5,

            LOGSERVICEINFO = 6
        }

    }
}


<pre>App.config
--------------------
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!--log4net config section registration-->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>

  <!--log4net  config (configurations) section-->
  <log4net>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="InfoLogAppender" />
      <appender-ref ref="DebugLogAppender" />
      <appender-ref ref="ErrorLogAppender" />
    </root>
    <appender name="InfoLogAppender" type="Log4NetAsynchronous.AsynchronousFileAppender">
      <file type="log4net.Util.PatternString" value="D:\\Logs\\InfoLog\\%property{LogFileName}\\" />
      <datePattern value="dd-MMM-yyyy'.log'" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <maximumFileSize value="10MB" />
      <param name="StaticLogFileName" value="false"/>
      <threshold value="INFO" />
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{dd/MMM/yyyy hh:mm:ss} [%level] - %message" />
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <levelMin value="INFO" />
        <levelMax value="INFO" />
      </filter>
      <filter type="log4net.Filter.DenyAllFilter"/>
    </appender>

    <appender name="DebugLogAppender" type="Log4NetAsynchronous.AsynchronousFileAppender">
      <file type="log4net.Util.PatternString" value="D:\\Logs\\DebugLog\\%property{LogFileName}\\" />
      <datePattern value="dd-MMM-yyyy'.log'" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <threshold value="DEBUG" />
      <maximumFileSize value="10MB" />
      <param name="StaticLogFileName" value="false"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{dd/MMM/yyyy hh:mm:ss} [%level] - %message" />
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <levelMin value="DEBUG" />
        <levelMax value="DEBUG" />
      </filter>
      <filter type="log4net.Filter.DenyAllFilter"/>
    </appender>

    <appender name="ErrorLogAppender" type="Log4NetAsynchronous.AsynchronousFileAppender">
      <file type="log4net.Util.PatternString" value="D:\\Logs\\ErrorLog\\%property{LogFileName}\\" />
      <datePattern value="dd-MMM-yyyy'.log'" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <threshold value="ERROR" />
      <maximumFileSize value="10MB" />
      <param name="StaticLogFileName" value="false"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{dd/MMM/yyyy hh:mm:ss} [%level] - %message" />
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <levelMin value="ERROR" />
        <levelMax value="ERROR" />
      </filter>
      <filter type="log4net.Filter.DenyAllFilter"/>
    </appender>
  </log4net>  

</configuration>



Что я уже пробовал:

Actually the same logic only we have implemented in our API.

This code also getting the same issue whatever I'm getting in our API application.

Thanks,

Rajesh

1 Ответов

Рейтинг:
0

Garth J Lancaster

iirc, Log4Net-это синхронный регистратор, по крайней мере, из коробки. На веб - сайте есть несколько примеров создания asynch logger-я приведу некоторые URL-адреса, которые могут быть полезны

Используя асинхронный, такой как log4net аппендеры для высокой производительности лесозаготовки[^]

c# - Как создать асинхронную оболочку для log4net? - переполнение стека[^]

эта ссылка намекает на существование, такой как log4net.Асинхронный Тестирование Log4Net.Async с помощью statsd и Graphite ~ andyfrench.info[^] - см. также Галерея NuGet | Log4Net.Async 2.0.4[^] ... Крис Хейнс, написавший это, также находится в теме SO (2-я ссылка)


K.B.Rajesh

Большое вам спасибо за ваш ответ.
Я изменил код ThreadPool.QueueUserWorkItem(task => log.Debug(msg)) вместо log.Ошибка(msg) в файле регистратора.

Теперь все журналы пишутся правильно. но я столкнулся с еще одной проблемой. Вся информация, отладка и ошибки записываются в один и тот же файл.

Пожалуйста, помогите мне в этом. Мне нужно написать отдельный файл для всех уровней.

Garth J Lancaster

ладно, это "другое" требование ... все, что вам нужно сделать, это настроить приложение для каждого уровня-файл журнала
Итак, для каждого уровня создайте новое приложение (файл, скользящий файл, что угодно) - используя "информацию" в качестве примера ..
1) назовите его, например, RFAppender-информация
2) установите значение файла на уникальный путь к файлу/файлу-информация
3) Установите тип фильтра на "log4net.Фильтр.Уровнемер"
4) установите фильтр levelMin & levelMax в положение "информация"
5) Добавьте приложение в "корневой" список приложений
Я уверен, что если вы загуглите "log4net different file per level", то найдете информацию, если это не имеет смысла

Garth J Lancaster

btw - log4net file appenders имеют настройку iirc, которая позволяет установить режим блокировки файла - см. Это https://logging.apache.org/log4net/release/sdk/html/P_log4net_Appender_FileAppender_LockingModel.htm ... вероятно, вам следует установить свой на MinimalLock

K.B.Rajesh

Гарт Джей Ланкастер, большое вам спасибо за Вашу поддержку...!

Но я хочу сделать так, чтобы хранить журналы в нижеприведенной структуре папок.

корневая папка:
-----------------
Бревна-
----В окне infolog-
--------Метод1
--------Метода Method2
--------Метод3
----Отладочный журнал-
--------Метод1
--------Метода Method2
--------Метод3
----Журнал ошибок-
--------Метод1
--------Метода Method2
--------Метод3

Я хочу хранить информацию о каждом методе, отладку и журналы ошибок в конкретной структуре каждой папки.

Если не возражаете, не могли бы вы предоставить пример кода.

Garth J Lancaster

tl/dr; короткий ответ "Нет, не сожалею"
длинный ответ - кроме того, я не согласен с тем, что вы делаете со своими журналами, информация о том, как разделить журналы, как вы просили (исключая пример "Method1", который, вероятно, форматирует строки журнала), находится в сети .. вам, вероятно, платят за эту работу - я в настоящее время безработный, поэтому на каком-то этапе вы должны сделать свое собственное исследование/работу ног