Abstraindo o logging com uma interface
ResumoEm vez de espalhar chamadas de log acopladas a um provedor específico, definimos uma interface
ILoggerManagerbem pequena. Assim a aplicação depende de uma abstração, e trocar o provedor (doILoggernativo para NLog, Serilog etc.) não impacta o resto do código.
1. Objetivos de Aprendizagem#
- Justificar por que abstrair o logging por trás de uma interface.
- Definir uma interface de logging enxuta e coesa.
- Entender a relação entre a abstração própria e o
ILogger<T>do framework.
2. Pré-requisitos#
- Solução
Catalogcom o projetoCatalog.Api(Módulo 16).
3. Conceito#
O ASP.NET Core já traz Microsoft.Extensions.Logging com ILogger<T>. Para a maioria dos casos, injetar ILogger<T> diretamente já é o suficiente e é a recomendação oficial.
Ainda assim, uma interface própria (ILoggerManager) é útil como exercício didático de inversão de dependência: as camadas de domínio/serviço passam a depender de uma abstração que você controla, e não diretamente do namespace do framework. O porquê: em arquiteturas em camadas (Módulo 17), a camada de domínio não deve referenciar detalhes de infraestrutura.
Notao log estruturado nativo (
_logger.LogInformation("Produto {Id} criado", id)) é preferível a concatenar strings, pois preserva os campos para consulta em ferramentas de observabilidade.
4. Mão na Massa#
4.1. Setup#
Crie um projeto de biblioteca para contratos e outro para a implementação (alinhado ao Onion do Módulo 17):
dotnet new classlib -n Catalog.LoggerService -f net9.0
dotnet new classlib -n Catalog.Contracts -f net9.0
dotnet sln add Catalog.LoggerService Catalog.Contracts
dotnet add Catalog.Api reference Catalog.LoggerService Catalog.Contracts
dotnet add Catalog.LoggerService reference Catalog.Contracts
4.2. Implementação Passo a Passo#
- Defina a interface em
Catalog.Contracts:
namespace Catalog.Contracts;
public interface ILoggerManager
{
void LogInfo(string message);
void LogWarn(string message);
void LogDebug(string message);
void LogError(string message);
}
- Mantenha-a pequena e estável: quatro níveis cobrem a necessidade da aplicação sem vazar a API do provedor.
4.3. Executando#
Ainda não há implementação; o build deve compilar as bibliotecas:
dotnet build
5. Exemplo Completo#
// Catalog.Contracts/ILoggerManager.cs
namespace Catalog.Contracts;
public interface ILoggerManager
{
void LogInfo(string message);
void LogWarn(string message);
void LogDebug(string message);
void LogError(string message);
}
6. Boas Práticas e Armadilhas#
| Faça | Evite |
|---|---|
| Manter a interface mínima e estável | Expor tipos do provedor (ex.: NLog.LogEventInfo) na interface |
| Colocar o contrato numa camada sem dependências de infra | Referenciar o pacote do provedor na camada de domínio |
Preferir ILogger nativo quando não precisar da abstração | Reinventar todo o subsistema de logging sem necessidade |
Atençãoao criar uma abstração própria, você perde o log estruturado nativo se a interface só aceitar
string. Considere assinaturas comparams object[]se precisar de campos estruturados.
7. Segurança e Produção#
- Nunca logue dados sensíveis: senhas, tokens, CPF, e-mail, número de cartão. Isso viola LGPD e cria vazamento persistente em arquivos de log.
- Trate a interface como um ponto único onde você pode aplicar mascaramento/scrubbing de PII.
8. Exercícios#
- Fácil: adicione um método
LogTrace. - Médio: discuta os prós e contras de trocar
string messagepor(string template, params object[] args). - Desafio: proponha como aplicar mascaramento automático de e-mails na implementação, sem alterar quem chama a interface.
9. Resumo#
Criamos ILoggerManager em uma camada de contratos, desacoplando a aplicação do provedor concreto. Reforçamos que ILogger<T> nativo já atende a maioria dos casos e que log sensível é proibido por compliance.
10. Próximos Passos#
No próximo tópico implementamos essa interface, configuramos o provedor e testamos via injeção de dependência.
11. Referências#
- Microsoft Learn — Logging no .NET
- Microsoft Learn — Logging no ASP.NET Core
- Microsoft Learn — Log de alto desempenho com LoggerMessage