Automatizando geração de logs com Delegating Handler em .NET
Tags: csharp, dotnet, development, developer
Published: 2023-08-11 13:09:25

Neste artigo vamos entender como funciona um Deleganting Handler e como podemos utilizá-lo para interceptar requisições e respostas Http e deixar de forma transparente o processo de geração de logs.

**Delegating Handler**

Um **Delegating Handler** funciona de forma similar a um filtro, onde através dele é possível interceptar requisições e respostas Http e então implementar uma lógica personalizada. Também é possível encadear vários Delegating Handlers criando uma pipeline que irá executar as lógicas personalizadas antes de serem enviadas ou recebidas pelo cliente ou servidor.

```



```

**Automatizando Logs**

Como foi visto, um Delegating Handler pode ser utilizado em diversos cenários no nosso dia a dia, efetuando a interceptação de requisições e respostas Http.

Abaixo iremos demonstrar como podemos fazer isso de forma rápida e fácil.

O primeiro passo é efetuar a criação de uma classe que herde de **DelegatingHandler**. Iremos utilizar o ILogger para efetuar a geração dos nossos logs.

```cs
public class LogDelegatingHandler : DelegatingHandler
{
    private readonly ILogger<LogDelegatingHandler> _logger;
    
    public LogDelegatingHandler(ILogger<LogDelegatingHandler> logger)
    {
        _logger = logger;
    }

    public LogDelegatingHandler(HttpMessageHandler innerHandler, ILogger<LogDelegatingHandler> logger) : base(innerHandler)
   {
        _logger = logger;
   }    
}
```

O próximo passo é efetuar o override do método **SendAsync**para que possamos interceptar o request e o response e implementar a nossa lógica personalizada.

```cs
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    string requestBody = null;
    string responseBody = null;
    
    if (request.Content != null) 
    {
        requestBody = await request.Content.ReadAsStringAsync();
    }

    _logger.LogDebug("Http request body is {requestBody}.", requestBody);

    var response = await base.SendAsync(request, cancellationToken);

    if (response.Content != null)
    {
        responseBody = await response.Content.ReadAsStringAsync();
    }

    _logger.LogDebug("Http response body is {responseBody}.", responseBody);

    return response;
}
```

Para que o nosso **Delegating Handler** possa ser facilmente utilizado, devemos então efetuar o seu registro e referenciar o seu uso nos serviços que necessitem da geração desses logs.

```cs
   static IHostBuilder CreateHostBuilder(string[] args) =>
     Host.CreateDefaultBuilder(args)
       .ConfigureAppConfiguration(app =>
       {
           app.AddJsonFile("appsettings.json");
           app.AddEnvironmentVariables();
       })
       .ConfigureServices((_, services) =>
       {
           services
               .AddTransient<LogDelegatingHandler>();

           services
               .AddTransient<ICepService, CepService>()
               .AddHttpClient("cepService")
               .AddHttpMessageHandler<LogDelegatingHandler>();
       })
       .UseSerilog((builder, configuration) =>
       {
           configuration.ReadFrom.Configuration(builder.Configuration);
       });
```

Com isso toda requisição Http que for feita no serviço informado será interceptada por nosso **LogDelegatingHandler** e terá os logs gerados.

**Conclusão**

O exemplo acima é apenas uma demonstração do que podemos fazer com o Delegating Handler. O objetivo foi apenas exemplificar o seu uso tornando a geração de logs mais transparente. Melhorias como a possibilidade de definição do nível de log podem ser implementadas.

Espero que tenham gostado do artigo, qualquer feedback é bem vindo.

Em breve voltarei com um outro exemplo de como podemos criar um Delegating Handler para automatizar o fluxo de autenticações.

Este exemplo está disponibilizado no **GitHub**:

[Logs Automáticos com Delegating Handler](https://github.com/brunohdossantos/logs-automaticos-com-delegatting-handler)

**Referências**

[Delegating Handler | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=net-6.0)