Independentemente da plataforma que você utiliza, o registro de logs costuma ser um requisito essencial para o processamento de big data, estatísticas, auditorias, relatórios de clientes e transações, bem como para depurar a comunicação entre cliente e servidor e possíveis problemas.
Neste blog, abordamos o papel dos logs na depuração, em que eles constituem a ferramenta definitiva para localizar os diversos problemas tão comuns nas comunicações pela Internet.

O registro da comunicação entre o cliente e o servidor web ajuda muito a depurar possíveis problemas relacionados à versão do navegador, à rede do cliente e aos arquivos acessados. No entanto, isso não para por aí. Há inúmeras possibilidades do que registrar, dependendo inteiramente da sua plataforma e dos seus requisitos.
Arquitetura de logs do NGINX
Ao executar um proxy reverso, balanceador de carga ou uma rede de distribuição de conteúdo (CDN), você adiciona outro nó ao fluxo de comunicação entre o cliente e o servidor. Um servidor intermediário que manipula dados, como um proxy reverso, costuma causar problemas inesperados.
Como proxy reverso, o NGINX transforma a conexão entre o cliente e o servidor web (ou outro servidor de aplicações) em duas conexões distintas, encerrando a conexão do cliente e criando uma nova conexão com o servidor. Essa “divisão” em duas conexões também cria dois contextos distintos para o registro de logs, e o NGINX oferece suporte a eles de maneiras um pouco diferentes.
- Para o tráfego entre o cliente e o proxy reverso, o NGINX fornece um log de erros e um log de acesso, que registra eventos de processamento e ações que não são erros. Você habilita o log de erros com a diretiva
error_loge pode definir o nível de gravidade dos erros a serem registrados. Você habilita o log de acesso com a diretivaaccess_log. A diretiva associadalog_formatpermite personalizar o tipo de informação incluída nos logs e o formato das entradas de log. Você pode gravar os logs em um arquivo, no syslog ou em ambos. - Para o tráfego entre o proxy reverso e o servidor Web ou de aplicativos (que o NGINX chama de servidor upstream), o NGINX oferece suporte ao log de erros. No entanto, ele não oferece suporte ao registro de acesso para esse tráfego. A única maneira de visualizar eventos que não sejam erros entre o servidor proxy e um servidor upstream é definir o nível de severidade no log de erros como
debug. A desvantagem dessa configuração é que enormes quantidades de dados são registradas. Isso torna o processamento de solicitações mais lento e cria arquivos muito grandes, que podem rapidamente ocupar todo o espaço de armazenamento. (Observe que também é necessário recompilar o NGINX com o argumento--with-debugno comandoconfigure, pois o suporte à depuração não é habilitado por padrão.)
Nossa solução de log para servidores upstream
Como provedor de CDN, frequentemente nos deparamos com servidores upstream que não se comunicam adequadamente com nossos servidores proxy reversos e clientes. As mensagens de nível debug no log de erros nem sempre fornecem as informações necessárias para corrigir um problema no servidor upstream.
A solução logo se tornou bastante evidente: gerar um log de acesso ao servidor upstream adicionando uma função que reúna apenas as informações essenciais da comunicação entre o proxy reverso e os servidores upstream.

A ideia geral é fazer com que o NGINX chame nossa função sempre que uma solicitação for feita a um servidor upstream. Isso nos permite programar na própria função toda a lógica relacionada ao registro de logs do upstream.
O módulo padrão ngx_http_upstream_module processa as solicitações aos servidores upstream, e precisamos que ele chame a função para nós. Atualmente, o módulo não oferece suporte a essa funcionalidade, então aplicamos um patch para habilitar o callback quando necessário.
O registro de logs propriamente dito é realizado por um módulo separado que desenvolvemos, o qual utiliza o recurso de callback de log que adicionamos ao módulo upstream modificado. O novo módulo define uma nova diretiva upstream_log para configurar a funcionalidade de registro de logs. Essa diretiva usa o mesmo analisador da diretiva access_log, portanto, os dados podem ser gravados em um arquivo ou enviados a um servidor syslog por meio de um socket.
Quando o NGINX lê a diretiva upstream_log no arquivo nginx.conf durante a inicialização, duas funções são chamadas:
ngx_http_upstream_log_set_log, que analisa a diretiva e prepara a própria estrutura de log (ngx_log_t) usandongx_log_set_loginternamentengx_http_upstream_log_init(em uma etapa de pós-configuração), que registra nossa função principal de registro de logs no módulo upstream
Dessa forma, quando uma solicitação precisa ser encaminhada por proxy a um servidor upstream, tudo está pronto. O módulo upstream inicia uma conexão com o servidor upstream, e nosso patch garante que a função de registro seja chamada para registrar os detalhes da solicitação.
O formato de log está incorporado diretamente ao módulo upstream. Ainda temos a opção de adicionar suporte à configuração usando a diretiva log_format, mas isso não é necessário para o nosso caso de uso.
Valores registrados do upstream
A função de registro é chamada logo após o encerramento da conexão com o servidor upstream. Seu argumento é um ponteiro para uma requisição que está sendo processada no momento (a estrutura ngx_http_ request_t), o que permite que a função acesse e registre todos os dados da estrutura. O campo upstream (ponteiro para ngx_http_upstream_t) é de especial interesse, pois contém dados sobre a requisição upstream. Estamos particularmente interessados em:
- O código de status da resposta do servidor de origem
- A duração da solicitação
- O valor de um cabeçalho HTTP na resposta ou do cabeçalho Host
O acesso a toda a estrutura da requisição é o que confere flexibilidade ao módulo, pois permite registrar uma grande variedade de informações.
Problemas que encontramos
Inicialmente, implementamos a funcionalidade no ngx_http_core_module. Isso foi suficiente para um protótipo, mas não era uma solução muito adequada, pois poderia complicar futuras atualizações e modificações. Por fim, separamos a função de registro de upstream em um módulo independente, conforme descrito em Nossa solução de registro de upstream.
É claro que houve alguns problemas de implementação. Mais especificamente, em alguns pontos manipulamos incorretamente as strings ngx_str_t, por exemplo, usando a função sprintf da biblioteca C em vez de ngx_snprintf. Isso pode fazer com que dados indefinidos sejam gravados no log de upstream ou até mesmo causar uma falha de segmentação na thread de trabalho. Esses problemas foram resolvidos após extensas sessões de depuração e testes com ferramentas como Valgrind e AddressSanitizer.
Recursos do NGINX usados na CDN77
O principal motivo pelo qual a CDN77 usa o NGINX são seus recursos de cache. O servidor CDN é um nó inserido entre o cliente e o servidor web (servidor upstream), que encaminha as solicitações do cliente e requisita os arquivos apropriados ao servidor upstream. Quando o arquivo é armazenado em cache, ele é entregue a outros usuários que solicitam o mesmo arquivo a partir do mesmo local.
“Arquivos servidos localmente” é um dos recursos que usamos para que o NGINX forneça um arquivo armazenado no disco do servidor ao receber uma solicitação.
Alguns recursos e configurações adicionais são necessários para garantir um armazenamento em cache seguro. Utilizamos SSL (TLS 1.3 com 0‑RTT) ou tokens seguros que podem ser gerados para um endereço IP específico a fim de proteger adequadamente o conteúdo.
Outros recursos que utilizamos incluem páginas de erro personalizadas para nossos clientes, a implementação padrão do NGINX para grampeamento OCSP e o FastCGI para PHP, a fim de reduzir o número de processos PHP necessários.
Conclusão
O registro de logs de upstream não apenas nos ajudou e continua nos ajudando a depurar diversos problemas, como também proporcionou uma excelente oportunidade para nos aprofundarmos nas principais funcionalidades do NGINX e simplificou vários outros projetos que realizamos.
Sobre a CDN77
A CDN77 torna a entrega de conteúdo melhor e mais conveniente em todo o mundo. Com mais de 30 data centers, somos capazes de armazenar conteúdo em cache e distribuí-lo com eficiência em todo o planeta. Isso inclui conteúdo estático do seu site, distribuição de software, vídeo sob demanda (VoD) e transmissões ao vivo por meio de diversos protocolos, como HLS ou MPEG‑DASH, usando um mecanismo de streaming dedicado.
Começar a usar a CDN77 é muito fácil, rápido e simples. Inscreva-se para uma avaliação gratuita, crie um recurso de CDN e use a URL de CDN gerada ou um registro CNAME personalizado para integrá-lo ao seu site ou à sua solução de streaming. Todos os recursos, configurações e possíveis soluções personalizadas garantem que a CDN77 atenda às suas necessidades.
Sobre o autor
Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.
Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.
Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.