- 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;
- 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:
| Campo | Descrição |
|---|---|
| Id | Chave primária auto‑incremental |
| AddTime | Hora a que o registo foi gerado |
| Thread | Nome da thread que gerou o registo |
| Level | Nível do registo: DEBUG/INFO/WARN/ERROR/FATAL |
| Logger | Nome do logger atual (nome completo da classe) |
| Message | Texto normal do registo |
| Exception | Rastreio 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
Previous: Introdução e instalação
Next: Saída de logs no console