Os registos são guardados na base de dados

  • Registros em ficheiro: é preciso aceder ao servidor para descarregar ou abrir ficheiros de texto, com pesquisa pouco prática;
  • Registros em base de dados: pode criar diretamente uma página de gestão de registros na área administrativa, com suporte a pesquisa por condições SQL, filtros e paginação;
  1. Facilita a manutenção centralizada, auditoria de registros e acompanhamento de erros.

Desvantagem: cenários com muitos registros aumentam a carga da base de dados. Em ambiente de produção pode otimizar com escrita em buffer, tabelas particionadas e limpeza periódica de registros antigos.

1 Criar tabela de registros (SQL Server)

-- Tabela de registros Log
create table Log (
    Id bigint identity,
    AddTime datetime not null,
    Thread nvarchar(100) not null,
    Level nvarchar(200) not null,
    Logger nvarchar(500) not null,
    Message nvarchar(3000) not null,
    Exception nvarchar(4000) null,
    constraint PK_LOG primary key (Id)
)
go

-- ========== Comentários dos campos (opcional, para facilitar consulta na base de dados) ==========
declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Tabela de registros log4net',
'user', @CurrentUser, 'table', 'Log'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Chave primária do registo',
'user', @CurrentUser, 'table', 'Log', 'column', 'Id'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Data de criação',
'user', @CurrentUser, 'table', 'Log', 'column', 'AddTime'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Thread de execução',
'user', @CurrentUser, 'table', 'Log', 'column', 'Thread'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Nível do registo (Info/Debug/Error etc.)',
'user', @CurrentUser, 'table', 'Log', 'column', 'Level'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Nome do logger',
'user', @CurrentUser, 'table', 'Log', 'column', 'Logger'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Conteúdo da mensagem do registo',
'user', @CurrentUser, 'table', 'Log', 'column', 'Message'
go

declare @CurrentUser sysname
select @CurrentUser = user_name()
execute sp_addextendedproperty 'MS_Description',
'Dados da exceção',
'user', @CurrentUser, 'table', 'Log', 'column', 'Exception'
goCode language: PHP (php)

Descrição dos campos:

CampoDescrição
IdChave primária auto‑incremental
AddTimeHora a que o registo foi gerado
ThreadNome da thread que gerou o registo
LevelNível do registo: DEBUG/INFO/WARN/ERROR/FATAL
LoggerNome do logger atual (nome completo da classe)
MessageTexto normal do registo
ExceptionRastreio da exceção, vazio quando não há erros

2 Pacote de instalação NuGet

Install-Package log4net

Utilizado diretamente no .NET Framework; também compatível com .NET Core/.NET5+/ASP.NET Core.

3 Configuração completa log4net (App.config / Web.config)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- Registar secção de configuração log4net -->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

  <log4net>
    <!-- ADONetAppender: módulo para gravar na base de dados -->
    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
      <!-- bufferSize=1: sem buffer, gravação em tempo real; aumente o valor para gravação em lote e reduzir carga da base de dados -->
      <bufferSize value="1" />

      <!-- Tipo de driver de ligação SqlServer -->
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

      <!-- Cadeia de ligação da base de dados, altere nome da base, utilizador e senha -->
      <connectionString value="DATABASE=log4netdemo;SERVER=.;UID=sa;PWD=pwdpwd;Connect Timeout=15;" />

      <!-- SQL de inserção, os campos devem corresponder exatamente à tabela e aos parâmetros -->
      <commandText value="INSERT INTO Log ([AddTime],[Thread],[Level],[Logger],[Message],[Exception])
VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />

      <!-- Parâmetro 1: data do registo -->
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
      </parameter>

      <!-- Parâmetro 2: nome da thread -->
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="100" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%t" />
        </layout>
      </parameter>

      <!-- Parâmetro 3: nível do registo -->
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="200" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%p" />
        </layout>
      </parameter>

      <!-- Parâmetro 4: nome do Logger -->
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="500" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%c" />
        </layout>
      </parameter>

      <!-- Parâmetro 5: mensagem do registo -->
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="3000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%m" />
        </layout>
      </parameter>

      <!-- Parâmetro 6: dados da exceção -->
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
    </appender>

    <!-- Logger raiz, ativar saída para base de dados -->
    <root>
      <level value="Info" />
      <appender-ref ref="ADONetAppender" />
      <!-- Pode também ativar registos em ficheiro para dupla saída: <appender-ref ref="nome_do_modulo_ficheiro"/> -->
    </root>
  </log4net>
</configuration>Code language: HTML, XML (xml)

Aviso importante: a captura de ecrã só mostra os dois primeiros parâmetros. A configuração completa precisa dos seis parâmetros, senão ocorrem erros no arranque.

4 Ativar log4net no código

1. Projeto Web .NET Framework (Global.asax)
protected void Application_Start(object sender, EventArgs e)
{
    // Carregar configuração log4net
    log4net.Config.XmlConfigurator.Configure();
}Code language: JavaScript (javascript)
2. Aplicação consola / WinForms

Na primeira linha do método Main em Program.cs:

log4net.Config.XmlConfigurator.Configure();Code language: CSS (css)
3. Código de utilização habitual
// Obter instância do logger
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

// Escrever registo normal
log.Info("Sistema iniciado com sucesso");

// Escrever registo de erro
try
{
    int a = 1 / 0;
}
catch (Exception ex)
{
    log.Error("Ocorreu um erro de cálculo", ex);
}Code language: PHP (php)

Os registos são guardados na base de dados

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *