Toda integração falha. A questão é se você descobre pelo monitoramento ou pelo cliente.
Este é o último post da série. Nos dois anteriores cobri padrões e implementação. Aqui fecho com o que aprendi sobre observabilidade — depois de ter descoberto falhas das duas formas acima.
O mínimo viável de monitoramento
Antes de qualquer ferramenta sofisticada, você precisa de três coisas:
1. Um objeto de log estruturado
// Campos recomendados no Custom Object: IntegracaoLog__c
IntegracaoLog__c log = new IntegracaoLog__c(
Sistema__c = 'EstoqueAPI', // Text(100)
Operacao__c = 'GET /produtos/{id}', // Text(255)
Status__c = 'Falha', // Picklist: Sucesso | Falha | Timeout
CodigoHTTP__c = 500, // Number
TempoRespostaMs__c = 1200, // Number
Payload__c = res.getBody(), // Long Text Area — apenas em falha
MensagemErro__c = e.getMessage(), // Text Area(255)
DataHora__c = Datetime.now() // DateTime
);
insert log;
Não guarde o payload em produção para chamadas de alto volume — você vai encher o armazenamento da org em semanas. Guarde apenas em falha, e mesmo assim considere truncar depois de X dias.
Alternativa: Nebula Logger
Antes de sair criando IntegracaoLog__c, vale saber que esse problema já foi resolvido antes. O Nebula Logger é um framework de logging open-source para Salesforce, mantido ativamente e amplamente adotado pela comunidade. Ele entrega o que você construiria no objeto customizado — campos estruturados, níveis de log (DEBUG / INFO / WARN / ERROR), integração com Platform Events e um dashboard pronto — sem precisar reinventar a roda.
A API é direta:
// Substitui o IntegracaoLogger customizado
Logger.info('Chamada bem-sucedida para EstoqueAPI')
.setHttpRequestDetails(req)
.setHttpResponseDetails(res);
Logger.saveLog();
// Em caso de erro:
Logger.error('Falha na chamada para EstoqueAPI')
.setHttpRequestDetails(req)
.setExceptionDetails(e);
Logger.saveLog();
Quando faz sentido usar: na maioria dos projetos novos, especialmente quando a org já permite instalação de pacotes gerenciados e você não quer manter uma infraestrutura de log própria a longo prazo.
Quando preferir o objeto customizado: orgs com restrições rígidas a pacotes de terceiros, ou quando os campos e regras de retenção precisam seguir requisitos muito específicos de compliance. Nesses casos, manter o controle total do objeto ainda compensa o custo de manutenção.
2. Alertas por falha consecutiva
Um único erro pode ser ruído. Cinco erros seguidos para o mesmo sistema externo é sinal de problema real. Configure um Flow ou Scheduled Apex que consulta os logs e dispara um email/Slack quando o threshold for atingido.
3. Dashboard simples
Um relatório com taxa de sucesso por sistema nos últimos 7 dias. Não precisa ser bonito. Precisa ser fácil de abrir quando alguém reportar um problema.
Os erros silenciosos que mais me custaram tempo
Timeout sem log
Se a chamada Apex lança
System.CalloutException: Read timed outmas não é capturada e logada corretamente, você não tem rastreabilidade. O registro fica num estado inconsistente e ninguém sabe por quê.
try {
EstoqueClient.get(externalId);
} catch (System.CalloutException e) {
// "Read timed out" chega aqui — log obrigatório
IntegracaoLogger.registrar('EstoqueAPI', 'timeout', e.getMessage());
throw e; // relança para não engolir o erro silenciosamente
}
Resposta 200 com erro no body
Algumas APIs retornam HTTP 200 com
{"status": "error", "message": "..."}no body. Se você só verifica o status code, vai tratar isso como sucesso — e a falha vai aparecer muito mais tarde, quando alguém perceber que o dado não foi processado.
EstoqueResponse resp = (EstoqueResponse) JSON.deserialize(res.getBody(), EstoqueResponse.class);
if (resp.sucesso == null || !resp.sucesso) {
throw new EstoqueException(resp.mensagem);
}
Mudança silenciosa de contrato
A API externa mudou um campo de Integer para String. O JSON.deserialize passa sem erro mas o valor fica nulo. Você descobre três semanas depois quando alguém percebe que estoque está sempre zero.
A proteção mais simples: validar os campos críticos do response antes de persistir.
O que eu faria diferente hoje
Olhando para trás, as três decisões que mais impactaram a qualidade das integrações que mantive:
Centralizar o HTTP num client único por sistema externo. Quando cada desenvolvedor cria seu próprio HttpRequest, você acaba com cinco implementações ligeiramente diferentes do mesmo endpoint, cada uma com seu próprio comportamento de erro.
Logar antes de persistir, não depois. Se o insert do registro Salesforce falha depois que você já chamou a API externa, você tem uma inconsistência sem evidência. Logar a chamada antes de commitar o dado te dá rastreabilidade mesmo na pior situação.
Não confiar no retry automático de Platform Events para falhas de negócio. O retry é para falhas de infraestrutura. Se o evento tem dados inválidos, retentá-lo 72 horas não vai resolver — vai só gerar ruído nos logs.
Encerrando a série
Integração é uma das partes mais antigas do Salesforce e ainda é onde projetos quebram. Os padrões não mudaram muito — o que muda é a escala e a expectativa de resiliência.
O que aprendi pode ser resumido em: escolha o padrão certo antes de escrever código, estruture o código para testabilidade, e construa observabilidade desde o primeiro dia — não depois que o cliente ligar.
Perdeu os posts anteriores? Veja Parte 1 (padrões) e Parte 2 (implementação).
Dúvidas ou experiências diferentes? Me conta no LinkedIn.