Журналорование Http трафика в ASP.NET MVC

Журналирование всего Http трафика ASP.NET MVC приложения.

Существует немало библиотек для журналирования на платформе .NET
В этой статье я не буду производить их анализ и сравнение. Познакомиться с плюсами и минусами бибилиотек журналирования для .NET можно, например, здесь Обзор библиотек журналирования .NET

Для решения задачи была выбрана библиотека NLog.

В первую очередь через Manage Nuget Packages установим слудующие пакеты необходимые для журналирования Http трафика с помощью NLog:



После установки в проект добавиться файл NLog.config. Подробно ознакомиться с его назначением можно здесь. Но для решения нашей задачи всего лишь изменим секцию target следующим образом:


<target xsi:type="Database"
              name="dbLog"
              connectionString="Server=SERVERNAME;Database=DATABASENAME;Trusted_Connection=True;"
              dbProvider="System.Data.SqlClient"
            
    >
      <!--
        Script for creating the dbo.HttpLog table.
 
        SET ANSI_NULLS ON
        SET QUOTED_IDENTIFIER ON
        CREATE TABLE [dbo].[Log] (
            [Id] [int] IDENTITY(1,1) NOT NULL,
            [Application] [nvarchar](50) NOT NULL,
            [Logged] [datetime] NOT NULL,
            [Level] [nvarchar](50) NOT NULL,
            [Message] [nvarchar](max) NOT NULL,
            [UserName] [nvarchar](250) NULL,
            [ServerName] [nvarchar](max) NULL,
            [Port] [nvarchar](max) NULL,
            [Url] [nvarchar](max) NULL,
            [Https] [bit] NULL,
            [ServerAddress] [nvarchar](100) NULL,
            [RemoteAddress] [nvarchar](100) NULL,
            [Logger] [nvarchar](250) NULL,
            [Callsite] [nvarchar](max) NULL,
            [Exception] [nvarchar](max) NULL,
          CONSTRAINT [PK_dbo.Log] PRIMARY KEY CLUSTERED ([Id] ASC)
            WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
        ) ON [PRIMARY]
        -->
 
      <commandText>
        insert into dbo.HttpLogs (
        Application, Logged, Level, Message,
        Username,
        ServerName, Port, Url, Https,
        ServerAddress, RemoteAddress,
        Logger, CallSite, Exception, LogId
        ) values (
        @Application, @Logged, @Level, @Message,
        @Username,
        @ServerName, @Port, @Url, @Https,
        @ServerAddress, @RemoteAddress,
        @Logger, @Callsite, @Exception, @LogId
        );
      </commandText>
 
      <parameter name="@application" layout="${appsetting:name=AppName:default=Unknown\: set AppName in appSettings}" />
      <parameter name="@logged" layout="${date}" />
      <parameter name="@level" layout="${level}" />
      <parameter name="@message" layout="${message}" />
 
      <parameter name="@username" layout="${identity}" />
 
      <parameter name="@serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
      <parameter name="@port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
      <parameter name="@url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
      <parameter name="@https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
 
      <parameter name="@serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
      <parameter name="@remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />
 
      <parameter name="@logger" layout="${logger}" />
      <parameter name="@callSite" layout="${callsite}" />
      <parameter name="@exception" layout="${exception:tostring}" />
      
      <parameter name="@logId" layout="${event-context:item=logId}" />
      
    </target>

При этом нужно установить значния Server=SERVERNAME; и Database=DATABASENAME; для вашей базы данных.

Для работы с базой в проекте используется подход EntityFramework Code First.
Создадим класс Http лога, и добавим его в контекст EntityFramework.

public class HttpLog
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Int32 Id { getset; }
 
    public string Application { getset; }
    public DateTime Logged { getset; }
    public string Level { getset; }
    public string Message { getset; }
    public string UserName { getset; }
    public string ServerName { getset; }
    public string Port { getset; }
    public string Url { getset; }
    public bool Https { getset; }
    public string ServerAddress { getset; }
    public string RemoteAddress { getset; }
    public string Logger { getset; }
    public string Callsite { getset; }
    public string Exception { getset; }
    public Guid LogId { getset; }
}
Таким образом в базе будет создана соответствующая таблица HttpLog. Обратите внимание, что в файле NLog.config мы описали именно эту таблицу, т.е. через файл NLog.config мы настроили библиотеку NLog таким образом, чтобы она сохраняла логи в эту таблицу.

Для того, чтобы журналировать абсолютно весь трафик всех контроллеров ASP.NET MVC веб-приложения создадим класс MvcApplication, который унаследуем от HttpApplication.

public class MvcApplication : HttpApplication
    {
        readonly Logger logger = LogManager.GetCurrentClassLogger();
        Guid logId = Guid.Empty;
        private const string logIdName = "logId";
 
        protected void Application_BeginRequest()
        {
            logId = Guid.NewGuid();
            Log(HttpContext.Current.Request.ToRaw());
        }
 
        protected void Application_EndRequest()
        {
            Log(HttpContext.Current.Response.ToRaw());
        }
 
        protected void Application_Error()
        {
            Exception exception = Server.GetLastError();
            Log(exception.ToString());
        }
 
        protected void Log(string message)
        {
            LogEventInfo theEvent = new LogEventInfo(LogLevel.Info, "", message);
            theEvent.Properties[logIdName] = logId;
            logger.Log(theEvent);
        }
    }

В классе MvcApplication переопределены методы Application_BeginRequest, Application_EndRequest и Application_Error так, что эти методы будут вызываться при каждом запросе к веб-приложению. И в таблице HttpLog базы данных будет создаваться запись на каздый http запрос, ответ и в случае ошибки. При этом запрос через поле logIdName связывается или с ответом или с ошибкой.

Теперь унаследуем веб-приложения от MvcApplication и таким образом имеем очень простой способ реализации полного журналирования http трафика.

Если необходимо журналировать только определенные контроллеры приложения, можно создат базовый контроллер, в котором переопределить методы Application_BeginRequest, Application_EndRequest и Application_Error. А затем наследовать определенные контроллеры от этого базового.

Комментариев нет :

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

Примечание. Отправлять комментарии могут только участники этого блога.