Utilizando o Discord como repositório de log em .NET
Usar o log no Discord é uma forma prática de receber, em tempo real, avisos sobre eventos importantes de uma aplicação .NET. O Discord é uma plataforma de comunicação que, com o tempo, passou a concorrer com o Microsoft Teams e o Slack no gerenciamento de times.
Inicialmente, ele tinha um foco maior no público gamer. Hoje, porém, tenta se firmar como um aplicativo de mensagens para o público geral, e o próprio balta.io usa o Discord como ferramenta de comunicação entre os alunos.
Além disso, o Discord disponibiliza uma rica API para desenvolvedores que permite integrar sistemas à plataforma. Entre os recursos dessa API estão os webhooks, que enviam mensagens para um canal com uma simples requisição HTTP.
Neste artigo, você vai configurar um provider de log no Discord em uma API ASP.NET Core com .NET 6. Em seguida, vai enviar mensagens informativas e detalhes de exceptions direto para um canal.
Por que usar log no Discord
Já que o Discord é uma plataforma tão presente no dia a dia, por que não usá-la para avisar quando algo relevante acontece na aplicação? Por exemplo, a conclusão de uma compra em um e-commerce ou o disparo de uma exception em produção.
Essa necessidade surgiu durante o desenvolvimento de um projeto em .NET. Quando um processo terminasse com sucesso, o autor queria receber uma mensagem no Discord avisando da conclusão.
Pensando nisso, ele criou dois pacotes open source:
- Discord Webhook Client, que usa webhooks do Discord para enviar mensagens.
- Discord .NET Logger Provider, que usa o Discord Webhook Client e cria um provider para a biblioteca
Microsoft.Extensions.Logging.
Na prática, o segundo pacote é o que interessa aqui. Ele permite enviar ao Discord os eventos de uma aplicação .NET usando a mesma interface ILogger que você já usa em qualquer projeto.
Vale lembrar que o log no Discord não substitui uma ferramenta de observabilidade. Ele funciona melhor como canal de notificação para eventos que exigem atenção humana imediata.
Casos de uso para log no Discord
Antes de configurar tudo, vale entender onde o recurso realmente ajuda. Em geral, o log no Discord brilha em projetos pequenos, ambientes de homologação e rotinas que rodam sem ninguém acompanhando.
Alguns exemplos comuns ajudam a visualizar esse uso:
- Avisar quando um processamento em lote termina com sucesso ou com falha.
- Notificar a equipe quando uma compra relevante acontece em um e-commerce.
- Alertar sobre exceptions não tratadas em um ambiente de testes.
- Acompanhar o início e o fim de um deploy ou de uma tarefa agendada.
Em todos esses casos, o time já está no Discord durante o dia. Por isso, receber o log no Discord reduz o tempo entre o problema acontecer e alguém perceber.
Por outro lado, sistemas com alto volume de eventos exigem mais cuidado. Nesse cenário, o log no Discord deve receber apenas um recorte pequeno e relevante, enquanto o restante segue para uma ferramenta própria de logs.
Como funciona um webhook do Discord
Um webhook nada mais é do que uma URL criada para um canal do Discord. Quando essa URL recebe uma requisição, o Discord publica a mensagem no canal, seja ela um log ou um aviso qualquer.
Segundo a documentação oficial de webhooks, eles são uma forma simples de postar mensagens em canais. Além disso, não exigem um usuário bot nem autenticação adicional.
O endpoint segue o formato POST /webhooks/{webhook.id}/{webhook.token}. Assim, o próprio token faz parte da URL e funciona como credencial de acesso.
A requisição aceita alguns campos principais:
content, com o texto da mensagem, limitado a 2000 caracteres.username, que substitui o nome padrão do webhook.avatar_url, que substitui o avatar padrão.embeds, com até 10 blocos de conteúdo formatado por mensagem.- Arquivos anexos, enviados como parte da mesma requisição.
Por esse motivo, o provider de log no Discord consegue enviar uma mensagem resumida e anexar um arquivo com os detalhes completos. Você verá esse comportamento quando registrarmos uma exception.
Criando um webhook no Discord
Para criar o webhook, abra as configurações do canal desejado, acesse a área de integrações e crie um novo webhook. Em seguida, copie a URL gerada, porque a aplicação vai usá-la para enviar o log no Discord.
Para mais detalhes sobre esse passo a passo, consulte o guia de introdução a webhooks do Discord. Para este exemplo, o autor criou um canal chamado #discord-webhook-client e, nele, um webhook.
Trate essa URL como um segredo. Afinal, qualquer pessoa com acesso a ela consegue publicar mensagens no seu canal.
Criando o projeto ASP.NET Core
Para demonstrar o log no Discord, vamos usar um projeto ASP.NET Core Web API com .NET 6. Para criar o projeto, execute o comando abaixo:
dotnet new webapi -o LoggingToDiscord
Com o projeto criado, abra-o no seu editor ou IDE favorito. O autor do exemplo original usa o Visual Studio 2022 Community.
Note que o .NET 6 já encerrou o ciclo de suporte da Microsoft. Mesmo assim, o exemplo mantém essa versão, porque é nela que o pacote e o código deste artigo foram testados.
Adicionando o pacote de log no Discord
Agora vamos adicionar o pacote logger-discord-provider. Para isso, rode o comando abaixo dentro da pasta LoggingToDiscord, onde o projeto foi criado:
dotnet add package logger-discord-provider --version 2.3.0
Repare que o comando fixa a versão 2.3.0. Isso acontece porque essa versão tem como alvo o .NET Standard 2.0 e, portanto, funciona no .NET 6.
Por outro lado, a versão 4.0.0 do pacote tem como alvo o .NET 8 e não instala em um projeto .NET 6. Além disso, o README atual do repositório usa um método de registro diferente, chamado AddDiscordLogger.
Depois de criar o projeto e adicionar o pacote, a solução fica com a seguinte estrutura:
Configurando o provider de log no Discord
Com o pacote instalado, vamos alterar o arquivo Program.cs. As linhas comentadas mostram o que muda em relação ao template padrão:
using JNogueira.Logger.Discord; // Namespace do pacote
var builder = WebApplication.CreateBuilder(args);
// Registra o IHttpContextAccessor, usado pelo provider para ler dados da requisição
builder.Services.AddHttpContextAccessor();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
var httpContextAccessor = scope.ServiceProvider.GetRequiredService<IHttpContextAccessor>();
// Obtém o LoggerFactory para adicionar o provider do Discord
var loggerFactory = scope.ServiceProvider.GetRequiredService<ILoggerFactory>();
// URL do webhook por onde as mensagens serão enviadas
loggerFactory.AddDiscord(new DiscordLoggerOptions(app.Configuration["DiscordWebhookUrl"])
{
ApplicationName = "LoggingToDiscord", // Nome da aplicação
EnvironmentName = app.Environment.EnvironmentName, // Ambiente de execução
UserName = "bot" // Nome exibido como remetente no canal
}, httpContextAccessor);
}
app.Run();
Primeiro, o código registra o IHttpContextAccessor no container de injeção de dependência. Então, o provider consegue anexar informações da requisição HTTP, como os headers, às mensagens de erro.
Em seguida, o bloco using cria um escopo, obtém o ILoggerFactory e chama AddDiscord. Esse método adiciona o provider ao sistema de logging, da mesma forma que o ILoggerFactory.AddProvider faz com qualquer provider.
As propriedades de DiscordLoggerOptions identificam a origem de cada log no Discord. Assim, quando várias aplicações escrevem no mesmo canal, você sabe de onde veio cada log.
Guardando a URL do webhook
No arquivo appsettings.json, adicione a URL do webhook que a aplicação vai usar:
{
"DiscordWebhookUrl": "https://discord.com/api/webhooks/..."
}
Essa abordagem funciona bem para um teste rápido do log no Discord. No entanto, como a URL contém o token do webhook, evite versionar o valor real no repositório.
Em desenvolvimento, uma alternativa é usar o Secret Manager do ASP.NET Core. Já em produção, prefira variáveis de ambiente ou um cofre de segredos, mantendo a mesma chave DiscordWebhookUrl.
Enviando mensagens de log no Discord
O template já traz o controller WeatherForecastController. Vamos alterar a rota HttpGet, no método Get, incluindo uma chamada ao método LogInformation do ILogger:
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
// Envia a mensagem para o canal do Discord via webhook
_logger.LogInformation("Hello! You received a message through Discord.");
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
Repare que o controller não conhece o Discord. Ele apenas usa o ILogger injetado, e o provider decide para onde a mensagem vai.
Depois de alterar o método, rode o projeto com CTRL + F5 no Visual Studio 2022 ou com o comando dotnet run. Então, a página do Swagger deve aparecer:
Em seguida, expanda a rota GET, clique em Try it out e depois em Execute.
Com isso, o log informativo chega ao canal do Discord:
Registrando exceptions com log no Discord
Outra aplicação do componente é enviar detalhes de uma exception para o canal. Para testar, vamos alterar a rota HttpPost e forçar uma DivideByZeroException:
[HttpPost(Name = "PostWeatherForecast")]
public IEnumerable<WeatherForecast> Post()
{
var divisor = 0;
// Dispara a exception em tempo de execução
var result = 5 / divisor;
return new List<WeatherForecast>();
}
No original, o método POST reaproveitava o nome de rota GetWeatherForecast. Aqui, ele ganhou um nome próprio, o que deixa o exemplo mais claro e evita confusão ao gerar links por nome de rota.
Rode o projeto novamente. Na página da API, clique em Try it out e em Execute na rota POST:
Logo depois, o log de erro chega ao canal do Discord:
Nesse caso, a mensagem traz um arquivo exception-details.txt. Ele reúne o tipo da exception, a base exception, o stack trace e os headers da requisição.
Mas quem registrou essa exception, se o controller não chamou o logger? Na verdade, o próprio ASP.NET Core registra exceptions não tratadas pelo ILogger, e por isso o provider também as recebe.
Boas práticas para log no Discord
Um canal do Discord é ótimo para alertas, mas pode virar ruído rapidamente. Por isso, algumas precauções ajudam a manter o recurso útil.
Filtre o nível dos logs
Em produção, envie para o Discord apenas logs de nível Warning ou superior. Dessa forma, o canal mostra o que exige ação e deixa o volume de mensagens informativas para outro destino.
O sistema de logging do .NET permite configurar esses filtros na seção Logging do appsettings.json. Se você quiser revisar esse mecanismo, o artigo sobre logging no ASP.NET explica os níveis e categorias.
Combine com outros providers
O Discord não guarda logs de forma estruturada nem oferece buscas avançadas. Assim, mantenha um destino principal para o histórico completo, como arquivos, um banco ou uma ferramenta de observabilidade.
Uma opção bastante usada é o Serilog, que você pode conhecer no artigo sobre Serilog no ASP.NET. Enquanto isso, o Discord fica com o papel de notificação rápida.
Cuide do desempenho e dos limites
A documentação da Microsoft sobre providers de logging lembra que o método ILogger.Log é síncrono. Portanto, um provider que faz chamadas HTTP precisa de cuidado para não atrasar as requisições da aplicação.
Além disso, o Discord aplica limites de taxa aos webhooks. Por esse motivo, evite registrar no canal eventos que se repetem a cada requisição, como um log informativo dentro de um endpoint muito acessado.
Proteja dados sensíveis
Lembre que o arquivo de detalhes inclui os headers da requisição. Portanto, tokens de autenticação, cookies e outros dados sensíveis podem acabar visíveis para todos os membros do canal.
Por esse motivo, use um canal privado e restrito à equipe responsável. Além disso, evite incluir senhas, documentos pessoais ou dados de clientes nas mensagens de log enviadas pela aplicação.
Considerações finais
O Discord oferece uma API muito rica, com vários outros recursos além dos webhooks. Para mais informações, acesse a documentação para desenvolvedores do Discord.
Neste artigo, você configurou o log no Discord em uma API .NET 6 com o pacote logger-discord-provider. Em poucos passos, a aplicação passou a enviar mensagens informativas e detalhes de exceptions para um canal.
O repositório do componente está disponível no GitHub do Discord .NET Logger Provider. Já o projeto usado neste artigo está no repositório logando-no-discord.
Em resumo, use o Discord como canal de alerta para eventos relevantes e mantenha um destino principal para o histórico. Assim, você ganha visibilidade imediata sem abrir mão de uma estratégia de logging completa.
FAQ
Preciso de um bot para enviar log no Discord?
Não. Os webhooks do Discord não exigem um usuário bot nem autenticação adicional, basta a URL gerada para o canal.
Qual versão do pacote usar com .NET 6?
Use a versão 2.3.0 do logger-discord-provider, que tem como alvo o .NET Standard 2.0. A versão 4.0.0 tem como alvo o .NET 8.
O controller precisa conhecer o Discord?
Não. O controller usa apenas o ILogger, e o provider registrado no ILoggerFactory envia a mensagem para o canal.
Exceptions não tratadas também chegam ao canal?
Sim. O ASP.NET Core registra exceptions não tratadas pelo sistema de logging, e o provider envia a mensagem com o arquivo exception-details.txt.
Onde guardar a URL do webhook?
Em desenvolvimento, use o Secret Manager. Em produção, prefira variáveis de ambiente ou um cofre de segredos, porque a URL contém o token do webhook.