Конкретный журнал для определенных файлов с использованием Nlog в .Net core 2.2

Я успешно настроил NLog в веб-API .net core 2.2. Но я хотел добиться спецификаций с логированием. Как добиться ниже:

  • Предупреждения должны быть зарегистрированы для предупреждения определенного файла
  • Ошибки должны регистрироваться в конкретном файле ошибки
  • Когда я регистрирую запрос/ответ, этот файл должен состоять только из моих запросов

Но в настоящее время с журналом запросов файл также сохраняет журналы ошибок/предупреждений в том же файле, а также в определенных файлах журналов ошибок/предупреждений. Как я могу разделить журналы в категоризированных файлах, чтобы определенные журналы сохранялись только в этом файле, а не в других файлах одновременно?

Мой файл nlog.config

<?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" autoReload="true" internalLogLevel="info" internalLogFile="internalLog.txt">  
    <extensions>  
        <add assembly="NLog.Web.AspNetCore" />  
    </extensions>  
    <!-- the targets to write to -->  
    <targets>  
        <!-- write to file -->  
        <target xsi:type="File" 
                name="allFile" 
                fileName="${var:customDir}\logs\AllLog\${shortdate}.log" 
                layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />  
        <!-- another file log. Uses some ASP.NET core renderers -->  
        <target xsi:type="File" 
                name="requestFile" 
                fileName="${var:customDir}\logs\RequestTrace\${shortdate}.log" 
                layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />

        <target xsi:type="File" name="warnFile" fileName="${var:customDir}\logs\Warnings\Warn_${shortdate}.log"  />
        <target xsi:type="File" name="errorFile" fileName="${var:customDir}\logs\Errors\Error_${shortdate}.log"  />
    </targets>  
    <!-- rules to map from logger name to target -->  
    <rules>  
        <logger name="*" minLevel="Trace" writeTo="allFile" />  
        <!--Skip non-critical Microsoft logs and so log only own logs-->  
        <!--<logger name="Microsoft.*" maxLevel="Info" final="true" />-->  
        <logger name="*" minLevel="Info" writeTo="requestFile" />  
        <logger name="*" minLevel="Warn"  writeTo="warnFile" />  
        <logger name="*" minLevel="Error"  writeTo="errorFile" />  
    </rules>  
</nlog> 

Мой файл запуска


    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(config =>
            {
                config.Filters.Add(new ApiLoggingMiddleware());
                config.Filters.Add(new ApiExceptionLoggingMiddleware());
            }
            ).SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)
            .ConfigureApiBehaviorOptions(options =>
            {
                options.SuppressInferBindingSourcesForParameters = true;
            });
        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseDeveloperExceptionPage();
            app.UseAuthentication();
            //app.UseMiddleware<ApiLoggingMiddleware>();
            LogManager.Configuration.Variables["customDir"] = Directory.GetCurrentDirectory();
        }
    }
}

Мой файл apilogginmiddleware.cs

   public class ApiLoggingMiddleware : TypeFilterAttribute
    {
        public ApiLoggingMiddleware() : base(typeof(AutoLogActionFilterImpl))
        {

        }

        private class AutoLogActionFilterImpl : IActionFilter
        {
            private readonly ILogger _logger;
            public AutoLogActionFilterImpl(ILoggerFactory loggerFactory)
            {
                _logger = loggerFactory.CreateLogger<ApiLoggingMiddleware>();
            }

            public void OnActionExecuting(ActionExecutingContext context)
            {
                // perform some business logic work
            }

            public void OnActionExecuted(ActionExecutedContext context)
            {
                ...
                _logger.LogInformation("Log request data");
                ...
            }
        }
    }
}

МОЙ файл apiexceptionloggingmiddleware.cs

    public class ApiExceptionLoggingMiddleware : TypeFilterAttribute
    {
        public ApiExceptionLoggingMiddleware() : base(typeof(AutoLogExceptionImpl))
        {

        }

        private class AutoLogExceptionImpl : IExceptionFilter
        {
            private readonly ILogger _logger;
            public AutoLogExceptionImpl(ILoggerFactory loggerFactory)
            {
                _logger = loggerFactory.CreateLogger<ApiLoggingMiddleware>();
            }

            public void OnException(ExceptionContext context)
            {
                _logger.LogError("Errors : " + context.Exception 
                    + Environment.NewLine + Environment.NewLine);
            }
        }
    }
}

person Dhiren    schedule 16.11.2019    source источник


Ответы (2)


Правила сопоставляются сверху вниз. Таким образом, minlevel=info будет соответствовать также ошибкам и т. д.

Простое решение здесь, используйте level вместо minlevel

  <rules>  
        <logger name="*" minLevel="Trace" writeTo="allFile" />  
        <!--Skip non-critical Microsoft logs and so log only own logs-->  
        <!--<logger name="Microsoft.*" maxLevel="Info" final="true" />-->  
        <logger name="*" level="Info" writeTo="requestFile" />  
        <logger name="*" level="Warn"  writeTo="warnFile" />  
        <logger name="*" level="Error"  writeTo="errorFile" />  
    </rules>

Альтернативный вариант

Другой вариант — использовать final и сначала сопоставить ошибку, затем предупредить и т. д.

E.g.

  <rules>  
      <logger name="*" minLevel="Trace" writeTo="allFile" />  
      <!--Skip non-critical Microsoft logs and so log only own logs-->        
      <!--<logger name="Microsoft.*" maxLevel="Info" final="true  />-->  
      <logger name="*" minLevel="Error" writeTo="errorFile" final="true” />
      <logger name="*" minLevel="Warn" writeTo="warnFile" final="true" />  
      <logger name="*" minLevel="Info" writeTo="requestFile" final="true" />
    </rules>

См. также https://github.com/NLog/NLog/wiki/Configuration-file#rules

person Julian    schedule 16.11.2019
comment
Я понял вашу логику, я тоже проверю это решение. Спасибо за поддержку. - person Dhiren; 18.11.2019

Я рекомендую вам сделать специальное правило логирования для вашего логгера запросов ApiLoggingMiddleware:

<rules>  
    <logger name="*" minLevel="Trace" writeTo="allFile" />  
    <!--Skip non-critical Microsoft logs and so log only own logs-->  
    <!--<logger name="Microsoft.*" maxLevel="Info" final="true" />-->  
    <logger name="*ApiLoggingMiddleware" minLevel="Info" writeTo="requestFile" />  
    <logger name="*" minLevel="Error"  writeTo="errorFile" final="true" />  
    <logger name="*" minLevel="Warn"  writeTo="warnFile" final="true" />  
</rules>  

Тогда requestFile-цель не будет загрязняться другими событиями регистрации информации.

Но убедитесь, что ApiExceptionLoggingMiddleware и ApiLoggingMiddleware не используют одно и то же имя регистратора. Похоже, что ApiLoggingMiddleware выполняет регистрацию запросов, поэтому избегайте повторного использования/злоупотребления его именем Logger-name (см. loggerFactory.CreateLogger<ApiLoggingMiddleware>())

person Rolf Kristensen    schedule 16.11.2019
comment
Я пробовал это и все еще получаю журнал запросов, загрязненный журналами ошибок, даже в журналах предупреждений я также получаю журналы ошибок. - person Dhiren; 16.11.2019
comment
Я получаю журналы WARN, INFO, ERROR в файле журнала запросов. - person Dhiren; 16.11.2019
comment
@Dhiren Обновленный ответ с новым NLog.config, который исправляет, поэтому ОШИБКА не стекает в warnFile. - person Rolf Kristensen; 16.11.2019
comment
@Dhiren Можете ли вы привести пример нежелательного имени регистратора в файле запроса (имя после LogLevel). ? Это невозможно, если у вас нет других регистраторов с именем ApiLoggingMiddleware. - person Rolf Kristensen; 16.11.2019
comment
@Dhiren Посмотри на проблему сейчас. ApiExceptionLoggingMiddleware использует то же имя регистратора, что и ApiLoggingMiddleware. Пожалуйста, исправьте это. - person Rolf Kristensen; 16.11.2019
comment
Хорошо, я понял вашу точку зрения. Позвольте мне попробовать, и я сообщу вам, спасибо за вашу хорошую поддержку и время. - person Dhiren; 18.11.2019