Use o NLog para fazer logon

Data de criação de página :

ambiente

Estúdio Visual
  • Visual Studio 2019
Núcleo ASP.NET
  • 5.0 (MVC, página de navalha)

inicialmente

O NLog permite que você exatre faça registros de arquivos, e-mails e bancos de dados, dependendo das configurações.

O NLog ASP.NET ser incorporado ao sistema de registro padrão do núcleo. É possível fazer registros de saída de acordo com as configurações ao usar o madeireiro padrão.

Sobre os níveis de log

Os registros da Microsoft e os NLogs são divididos em seis estágios, e os níveis de saída são aproximadamente os mesmos:

Nível MicrosoftNLog
0 traço traço
1 depurar depurar
2 informação informação
3 aviso advertir
4 erro erro
5 crítico fatal
(6) (Nenhum) (Desligado)

Quanto maior o nível, mais importante é o log, e maior a probabilidade de ser escrito independentemente das restrições de saída de log.

Instruções de registro

Implantação do pacote NLog

ASP.NET você criou um projeto Core, adicione um pacote.

Clique com o botão direito do mouse em Dependências para o seu projeto e selecione Gerenciar pacotes NuGet.

Clique na guia Procurar e digitar NLog no campo de pesquisa para exibir pacotes relacionados ao NLog.

Selecione NLog e clique no botão instalar com a versão estável mais recente selecionada.

Clique em OK.

Também instale nLog.Web.AspNetCore.

O pacote foi adicionado ao projeto.

Adicionar nlog.config

Adicione nlog.config, a definição de saída do registro NLog, ao projeto. O conteúdo está no formato XML, então eu o criei como um arquivo XML. O nome do arquivo deve ser nlog.config (minúscula).

Crie o arquivo da seguinte forma: As configurações detalhadas serão discutidas mais tarde.

<?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"
      throwConfigExceptions="true"
      internalLogFile="${basedir}/internal-nlog-AspNetCore.txt">

  <!-- ログの出力レイアウトを変数 layoutDefine で定義 -->
  <variable name="layoutDefine"
            value="${longdate} [${event-properties:item=EventId_Id:whenEmpty=0}][${level:padding=-5}] ${message} ${exception:format=tostring} (${callsite:includeNamespace=false:fileName=true:includeSourcePath=false})" />

  <!-- 書き込むターゲット -->
  <targets>
    <!-- Visual Studio の出力 (デバッグ) に書き込みます -->
    <target xsi:type="Trace" name="TraceOutput" rawWrite="true" layout="${layoutDefine}" />

    <!-- 基本的な詳細を含むすべてのログメッセージのファイルターゲット -->
    <target xsi:type="File" name="FileOutput" fileName="${aspnet-appbasepath}/Log-${shortdate}.log" layout="${layoutDefine}" />

    <!-- Docker / Visual Studio の起動検出を改善するためにライフタイムメッセージをホストするためのコンソールターゲット  -->
    <target xsi:type="Console" name="LifetimeConsole" layout="${level:truncate=4}\: ${logger}[0]${newline}      ${message}${exception:format=tostring}" />
  </targets>

  <!-- ロガー名からターゲットにマップするルール -->
  <rules>
    <!-- Microsoft からのものを含むすべてのログ -->
    <logger name="*" writeTo="TraceOutput" />

    <!-- 起動の検出を高速化するために、ホスティングライフタイムメッセージをコンソールターゲットに出力します。Microsoft.Hosting.Lifetime はここより下の定義には出力しません -->
    <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="LifetimeConsole" final="true" />

    <!-- 重要でない Microsoft ログをスキップして、自分のログのみをログに記録する。システムが出す Warning 以上のログ以外はここより下の定義には出力されません -->
    <logger name="Microsoft.*" maxlevel="Info" final="true" />
    <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

    <!-- 上記で除外したもの以外をファイルに出力 -->
    <logger name="*" writeTo="FileOutput" />
  </rules>
</nlog>

Certifique-se de que as propriedades do nlog.config estão definidas para Criar ação: conteúdo, copiar para diretório de saída: Copiar se novo.

Editar appsetting.json

Por padrão, não importa como você define nlog.config, Information apenas esses níveis são de saída. Isso porque o registro também conta com appsetting.json.

Abra appsetting.json Logging.LogLevel.Default e altere o valor para Trace . Se você usar o NLog, você pode ajustar o nível no lado NLog, para que você possa produzir praticamente todos os níveis Trace definindo appsetting.json.

{
  "Logging": {
    "LogLevel": {
      "Default": "Trace",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Além disso, durante o desenvolvimento, appsettings. As configurações de desenvolvimento.json estão carregadas, então estamos mudando-as também.

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Trace",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

Preparando programas para nlog

Adicione um programa para que você possa fazer login no mecanismo NLog.

Abra .cs arquivo do programa e corrija-o da seguinte forma:

using NLog.Web;  // 追加

// 省略

public class Program
{
  public static void Main(string[] args)
  {
    var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    try
    {
      CreateHostBuilder(args).Build().Run();
    }
    catch (Exception exception)
    {
      // NLog:セットアップエラーをキャッチ
      logger.Error(exception, "例外のためにプログラムを停止しました。");
      throw;
    }
    finally
    {
      // アプリケーションを終了する前に、内部タイマー/スレッドをフラッシュして停止するようにしてください
      // (Linux でのセグメンテーション違反を回避してください)
      NLog.LogManager.Shutdown();
    }
  }

  public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
        webBuilder.UseStartup<Startup>();
      })
      .ConfigureLogging(logging =>
      {
        logging.ClearProviders();                 // NLog 以外で設定された Provider の無効化.
        logging.SetMinimumLevel(LogLevel.Trace);  // 最小ログレベルの設定
      })
      .UseNLog();  // NLog:依存性注入のための NLog のセットアップ
}

Log

Para projetos HomeComtroller MVC, para páginas razor, você teria sido passado para o IndexModel ILogger<IndexModel> logger construtor. Ele também está definido para no campo privado, para _logger que você possa usá-lo para registrar.

A seguir, um exemplo de saída de uma página razor, mas mvc pode sair com o mesmo código.

// 省略

public class IndexModel : PageModel
{
  private readonly ILogger<IndexModel> _logger;
  
  public IndexModel(ILogger<IndexModel> logger)
  {
    _logger = logger;
    
    _logger.LogTrace("Trace で出力します。");
    _logger.LogDebug("Debug で出力します。");
    _logger.LogInformation("Information で出力します。");
    _logger.LogWarning("Warning で出力します。");
    _logger.LogError("Error で出力します。");
    _logger.LogCritical("Critical で出力します。");
    
    _logger.LogInformation(1, "EventID ありで出力します。");
  }
  
  public void OnGet()
  {
    _logger.LogInformation("ページを表示するタイミングでログを出力します。");
  }
}

Ao depurar, acho que um arquivo de registro pode ser feito na pasta do projeto.

Você pode verificar o registro olhando para o conteúdo do arquivo.

Exemplo nlog.config comentário

Estou explicando em ordem, mas não estou explicando as partes menos importantes.

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      throwConfigExceptions="true"
      internalLogFile="${basedir}/internal-nlog-AspNetCore.txt">

Existem parâmetros, como as configurações de saída de log para o próprio NLog.

internalLogFile será o destino do registro. Isso pode ser útil, por exemplo, se houver um erro na saída do próprio log. ${basedir} refere-se à pasta de execução do programa.

internalLogLevel é o nível de saída do registro NLog. Off se for, não será saída.

<!-- ログの出力レイアウトを変数 layoutDefine で定義 -->
<variable name="layoutDefine"
          value="${longdate} [${event-properties:item=EventId_Id:whenEmpty=0}][${level:padding=-5}] ${message} ${exception:format=tostring} (${callsite:includeNamespace=false:fileName=true:includeSourcePath=false})" />

A variável é definida para qual layout o conteúdo do log será produzido. Você pode digitar diretamente em alvos posteriores, mas se você especificar vários do mesmo layout, é mais fácil gerenciá-los em uma variável.

É melhor consultar o site oficial para ver quais parâmetros podem ser especificados no layout.

Para referência, os parâmetros especificados aqui são de saída no seguinte formato:

do parâmetro
Conteúdo de saída
longdate Data e hora como "2021-03-17 11:46:36.5034"
propriedades de eventos Exibe o ID do evento, etc. da saída de log especificada pelo programa
nível Níveis como Rastreamento e Erro
Mensagem Mensagem especificada no registro do programa
exceção E se você passar exceção no registro de programas
callite Localização de registro, nome do arquivo, etc.

Exemplo de saída

2021-03-17 11:46:37.3537 [0][Info ] ページを表示するタイミングでログを出力します。  (IndexModel.OnGet(Index.cshtml.cs:26))
<!-- 書き込むターゲット -->
<targets>
  <!-- Visual Studio の出力 (デバッグ) に書き込みます -->
  <target xsi:type="Trace" name="TraceOutput" rawWrite="true" layout="${layoutDefine}" />

  <!-- 基本的な詳細を含むすべてのログメッセージのファイルターゲット -->
  <target xsi:type="File" name="FileOutput" fileName="${aspnet-appbasepath}/Log-${shortdate}.log" layout="${layoutDefine}" />

  <!-- Docker / Visual Studio の起動検出を改善するためにライフタイムメッセージをホストするためのコンソールターゲット  -->
  <target xsi:type="Console" name="LifetimeConsole" layout="${level:truncate=4}\: ${logger}[0]${newline}      ${message}${exception:format=tostring}" />
</targets>

Especifica o alvo para saída. Múltiplos podem ser especificados.

O primeiro xsi:type="Trace" especifica , e o registro é impresso na janela de saída do Visual Studio. Pode ser usado principalmente para depurar execução.

O segundo xsi:type="File" especifica e faz logon em um arquivo no caminho especificado. Se você ${shortdate} especificar no caminho, você pode escrever o registro para o arquivo da data do log no momento do registro. Também ${aspnet-appbasepath} especifica a pasta raiz do projeto Web. No entanto, ao operar, é melhor produzir arquivos de log fora do diretório da Web para substituição e segurança do programa.

O terceiro é xsi:type="Console" especificado e pode ser exibido no console no aplicativo do console. ASP.NET Core em si não é um aplicativo de console, mas também pode ser usado em ambientes como Docker e Azure porque o estado pode ser exibido no console. Esta é a descrição no site oficial da NLog.

<!-- ロガー名からターゲットにマップするルール -->
<rules>
  <!-- Microsoft からのものを含むすべてのログ -->
  <logger name="*" writeTo="TraceOutput" />

  <!-- 起動の検出を高速化するために、ホスティングライフタイムメッセージをコンソールターゲットに出力します。Microsoft.Hosting.Lifetime はここより下の定義には出力しません -->
  <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="LifetimeConsole" final="true" />

  <!-- 重要でない Microsoft ログをスキップして、自分のログのみをログに記録する。システムが出す Warning 以上のログ以外はここより下の定義には出力されません -->
  <logger name="Microsoft.*" maxlevel="Info" final="true" />
  <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

  <!-- 上記で除外したもの以外をファイルに出力 -->
  <logger name="*" writeTo="FileOutput" />
</rules>

Aqui você especifica qual nível e que tipo de logs para saída para onde. Esta descrição é aplicada de cima para cima.

O primeiro é name="*" produzir todos os logs para o alvo porque o nível é writeTo especificado enquanto especifica . Este target é o especificado em , por isso aparece na saída visual TraceOutput studio.

A segunda é Microsoft.Hosting.Lifetime a saída para a saída de log na writeTo (コンソール) biblioteca. As associações do ConsoleLifetime podem ser verificadas em consoles como Azure e Docker. minlevel="Info" porque Trace Debug especifica , e não está registrado. Além disso, as definições subsequentes não fazem final="true" Microsoft.Hosting.Lifetime registros relacionados à saída.

O terceiro name="Microsoft.*" é parar de registrar name="System.Net.Http.*" final="true" especificando e logs. name*é um curinga, o que significa Microsoft System.Net.Http que se refere a todas as bibliotecas relacionadas. , mas pare maxlevel="Info" Trace aqui, Debug Information porque WArningO Error registro também é de saída em definições subsequentes. Critical

O quarto é saída para final="true" um arquivo diferente do log parado acima.

Registros de arquivos

Há também um método de arquivamento do arquivo de log antigo em uma pasta separada para cada data com apenas um arquivo de registro principal.

por exemplo:

<target xsi:type="File"
        name="FileOutput"
        fileName="${aspnet-appbasepath}/Log.log"
        archiveNumbering="Date"
        archiveEvery="Day"
        archiveFileName="${aspnet-appbasepath}/Archive/Log_{#}.log"
        archiveDateFormat="yyyy-MM-dd"
        maxArchiveFiles="7"
        layout="${layoutDefine}" />

Os parâmetros aqui utilizados significam:

Descrição do parâmetro
archiveNumbering A data cria um arquivo de arquivo por data.
arquivoEvery O dia é usado para arquivar diariamente. Há também maneiras de especificar "Mês", "Hora", "Domingo", etc.
arquivoFileName Caminho para arquivar para. {#} altera em uma base de arquivo por arquivo.
arquivoDateFormat Formato de data por data do formato da data do arquivo.
maxArchiveFiles Especifica quantos arquivos para arquivar.

Há também maneiras de arquivar métodos sem data. Para mais informações, consulte o site oficial.

Quando executado, parece assim:

Enviar e-mails por log

O NLog também permite que você envie e-mails ao fazer o login. No entanto, se você enviar um e-mail como um log de depuração, ele se tornará demais para enviar, É uma boa ideia atingir apenas níveis de log limitados, como Error e Fatal. Além disso, para evitar o risco de falha, como bloquear o servidor de correio devido à transmissão de overs, Recomendamos que você especifique uma conta de e-mail somente para log.

A seguir, um exemplo de uma configuração. Se você quiser realmente enviar e-mails, siga o servidor SMTP que deseja usar.

<targets>
  <target xsi:type="Mail"
          name="SendMail"
          smtpServer="SMTP Server Name"
          smtpPort="25"
          subject="XXXX システムでエラーが発生しました"
          from="aaaa@example.com"
          to="bbbb@example.com"
          enableSsl="False"
          smtpAuthentication="None"
          smtpUserName=""
          smtpPassword=""
          layout="${layoutDefine}"/>
</targets>

<rules>
  <logger name="*" minlevel="Error" writeTo="SendMail" />
</rules>

Escreva logs no banco de dados

O NLog também pode escrever logs no banco de dados. A seguir, um exemplo, então consulte o site oficial para obter detalhes.

Esta seção descreve as etapas para gravar para o SQL Server em um servidor diferente.

Primeiro, crie uma tabela para fazer login no SQL Server de destino. Uma vez que você pode escolher o valor para escrever, defina o que você precisa como um registro como uma coluna.

A seguir, um exemplo de criação de tabela SQL.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
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,
  [User] [nvarchar](250) NOT NULL,
  [Message] [nvarchar](max) NOT 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] TEXTIMAGE_ON [PRIMARY]
GO

Uma biblioteca de clientes de banco de dados System.Data.SqlClient é necessária para o processamento do banco de dados. Vamos instalá-lo a partir de NuGet.

Escreve informações de banco de dados para appsettings.json. nlog.config permite carregar as informações em appsettings.json. As configurações são provisórias, por isso, defina-as de acordo com o banco de dados real. O nome-chave é arbitrário, mas é usado por nlog.config.

{
  "": "省略",

  "NlogConnection": {
    "DbHost": "ServerName\\SQLEXPRESS",
    "Database": "TestDatabase",
    "User": "UserName",
    "Password": "********"
  }
}

Definir nlog.config da seguinte forma:

<targets>
  <target xsi:type="Database"
          name="DatabaseOutput"
          dbProvider="sqlserver"
          dbHost="${configsetting:name=NlogConnection.DbHost}"
          dbDatabase="${configsetting:name=NlogConnection.Database}"
          dbUserName="${configsetting:name=NlogConnection.User}"
          dbPassword="${configsetting:name=NlogConnection.Password}">
    <commandText>
      insert into dbo.Log (
        Application, Logged, [Level], [User], Message, Logger, CallSite, Exception
      ) values (
        @Application, @Logged, @Level, @User, @Message, @Logger, @Callsite, @Exception
      );
    </commandText>
    <parameter name="@application" layout="XXXX System" />
    <parameter name="@logged" layout="${date}" />
    <parameter name="@level" layout="${level}" />
    <parameter name="@user" layout="${aspnet-user-identity}" />
    <parameter name="@message" layout="${message}" />
    <parameter name="@logger" layout="${logger}" />
    <parameter name="@callSite" layout="${callsite:filename=true}" />
    <parameter name="@exception" layout="${exception:tostring}" />
  </target>
</targets>

<rules>
  <logger name="*" writeTo="DatabaseOutput" />
</rules>

Se não houver erros de execução, ele será escrito da seguinte forma:

A propósito.cs observe que tentar escrever logs no banco de dados em um estágio inicial, como antes do programa .cs CreateHostBuilder métodos, pode falhar.

Obtenha madeireiros do RequestServices e registre-os

Pode ser tedioso adicionar ao construtor cada vez que você ILogger criar um novo controlador ou modelo de página. Alternativamente, RequestServices você pode obter de .

public void OnGet()
{
  // RequestServices から ILogger を取得する
  var logger = (ILogger<IndexModel>)HttpContext.RequestServices.GetService(typeof(ILogger<IndexModel>));

  logger.LogInformation("ページを表示するタイミングでログを出力します。");
}

Se especificar seu próprio controlador ou modelo de página também é complicado, você pode criar métodos de extensão ou classes básicas.

public static class AspNetExtention
{
  /// <summary>
  /// ロガーを取得する拡張メソッドです。
  /// </summary>
  public static ILogger<T> GetLogger<T>(this T self) where T : PageModel
    => (ILogger<T>)self.HttpContext.RequestServices.GetService(typeof(ILogger<T>));

  // MVC の場合
  //public static ILogger<T> GetLogger<T>(this T self) where T : Controller
  //  => (ILogger<T>)self.HttpContext.RequestServices.GetService(typeof(ILogger<T>));
}

Casos de uso

public void OnGet()
{
  // RequestServices から ILogger を取得する (this. は必要)
  var logger = this.GetLogger();

  logger.LogInformation("ページを表示するタイミングでログを出力します。");
}