Log de erros
Público
Este artigo é para operadores da plataforma GCM. Administradores de igreja devem ver o artigo de log de auditoria em Usuários e funções para mudanças que eles podem investigar por conta própria — o Log de erros é em toda a plataforma e inclui stack traces e corpos de requisição, restritos à equipe GCM por design.
A aba Log de erros (/platform/error-log) é a fila central de triagem para tudo que explode em qualquer lugar do sistema. Exceções de frontend capturadas pela boundary do Sentry, funções edge que lançam, rotas de API Vercel que retornam 500 e triggers de banco que levantam — todos convergem para platform_error_log e aparecem aqui, filtráveis por fonte, severidade, organização e estado resolvido, com auto-refresh a cada 30 segundos.

As cinco fontes
Cada linha carrega um enum source. O dropdown de filtro permite restringir a um por vez:
- Frontend — exceções React não capturadas. Capturadas pelo error boundary global e postadas via
/api/log-error. Os camposurleuser_agentsão preenchidos. - Função edge — funções edge Deno que lançaram ou chamaram
log()com severidadeerror. A colunafunction_nameé definida. - API Vercel — funções serverless Node (as rotas
/api/*). Como funções edge, mas com o contexto do runtime Vercel. - Trigger do DB — levantado de dentro do Postgres, geralmente por um
RAISE EXCEPTIONem um trigger. A stack trace é o contexto de erro do Postgres. - Manual — qualquer coisa para a qual
log_errorfoi chamado explicitamente. Usado para avisos não fatais que valem a pena exibir.
Severidade
Três níveis, todos com código de cor:
warning— âmbar. Não falham requisições, mas ruidoso o bastante para investigar. Negações de RLS, consultas lentas, chamadas de gateway com retry.error— rosa. Uma requisição falhou. O usuário viu algo quebrado.fatal— vermelho escuro. Uma requisição falhou de um jeito que deixou o estado inconsistente. Trate como página um.
O filtro padrão é "não resolvido"
A página carrega com resolved = false para que a fila seja o que está aberto. Mude para Resolvido para ver o histórico triado, ou Todos para uma visão completa. O filtro Organização tem uma opção especial Não atribuído (sem organização) para linhas que dispararam antes de um contexto de tenant ser estabelecido (o caso mais comum para erros de boot do frontend).
A busca por texto bate em quatro colunas de uma vez: message, function_name, url, error_code. Use como você usaria a busca do Sentry — correspondência parcial, case-insensitive.
Como uma linha se parece
Cada linha na tabela mostra:
- Quando — relativo ("3min atrás"). Passe o mouse para o timestamp completo.
- Fonte — ícone colorido + rótulo.
- Severidade — pílula.
- Organização — derivada de
context.org_namequando presente, senão os 8 primeiros caracteres deorganization_id, senão um traço. - Mensagem — a mensagem de erro, truncada.
- Onde —
function_namese disponível, senãourl. - Status — Aberto ou Resolvido.
Clique em qualquer linha para abrir o diálogo de detalhes.
O diálogo de detalhes
O diálogo de detalhes é o espaço de trabalho de triagem. A metade superior é uma grade chave/valor: função / URL, código de erro, usuário (nome + e-mail), organização + plano, as funções que ele tinha, se era administrador de plataforma na hora, rota, contexto de ação, id de correlação, user agent.
Duas seções recolhíveis seguem:
- Stack trace — a stack bruta do runtime. Para triggers de DB, é o contexto de erro do Postgres. Para erros de frontend, é a stack JS, com source map quando possível.
- Contexto (completo) — a coluna JSONB
contextinteira pretty-printed. É aqui que funções edge guardam corpos de requisição, params de consulta e valores intermediários. Trate como sensível — pode incluir e-mails e IDs.
PII no contexto
A coluna context não é tarjada. É um dump bruto do que o código falho capturou. Não cole em Slack, em ticket público ou em issue do Sentry. O Log de erros vive atrás do portão de administrador de plataforma precisamente para que isso seja seguro.
Resolvendo uma linha
A parte de baixo do diálogo tem os controles de resolução:
- Marcar como resolvido — captura uma nota opcional ("corrigido em #123" ou "transiente, ignorando") e carimba
resolved,resolved_at,resolved_by,resolved_note. A linha sai da visão padrão de não resolvidos. - Reabrir — só visível em linhas já resolvidas. Limpa as colunas de resolução.
- Excluir — destrutivo. Apaga a única linha inteira. Útil para exposições de dados pessoais que não devem permanecer no banco.
A resolução é um sinal de workflow, não uma correção. Marcar uma linha como resolvida não para o bug subjacente — só diz a você mesmo no futuro que o erro foi triado.
Ações em massa
Duas operações em massa vivem no cabeçalho da tabela:
Expurgar resolvidos > 30d
Exclui permanentemente linhas resolvidas com mais de 30 dias. Esse é o sweep de retenção — uma linha triada não merece aluguel depois de um mês. Barato de rodar, seguro de rodar regularmente. O botão informa a contagem que removeu.
Limpar filtrado
Exclui cada linha que corresponde ao conjunto de filtros atual. Isso é perigoso e a UI sabe:
- O botão está desativado a menos que pelo menos um filtro restrinja o conjunto. Sem um filtro, o texto "correspondendo aos filtros atuais" do diálogo seria uma mentira.
- O diálogo de confirmação mostra a contagem exata que vai excluir.
Use para limpar uma classe ruidosa de avisos depois de você ter enviado a correção: filtre por source = frontend, message = ChunkLoadError, resolved = não resolvido, aperte Limpar, veja a contagem zerar.
O que o auto-refresh significa
A consulta refaz a cada 30 segundos via refetchInterval do React Query. O spinner de carregamento aparece em linha ao lado da contagem de linhas a cada refetch — se está rodando para sempre, a rede travou e as linhas existentes estão velhas. O botão Atualizar força uma invalidação imediata.
Padrões comuns
Um pico de avisos EDGE_FUNCTION de uma organização — geralmente um webhook mal configurado martelando um endpoint que retorna 429. Abra a organização e cheque as linhas channels dela.
Erros fatais sem organização — a falha aconteceu antes do contexto do tenant resolver. Quebras no boot do frontend, falhas do auth-hook e falhas de cold start de funções edge se agrupam aqui. Agrupe por mensagem e a causa geralmente é uma variável de env ausente.
Erros de negação de RLS de db_trigger — alguém está chamando uma consulta sem a função correta. Cruze o id do usuário em context com o log de auditoria para ver o que estava tentando fazer.
Se uma única linha precisa de investigação por um engenheiro que não é administrador de plataforma, copie o correlation_id e compartilhe isso — ele pode grep os logs de função edge no Supabase pelo mesmo id sem você ter que encaminhar a linha.
