Impeça o Coralogix RUM de Roubar sua Rede Inicial
O Coralogix RUM envia beacons durante o carregamento e rouba rede do seu próprio LCP. Em vez disso, armazene os eventos em buffer e envie-os no page hide.

Impeça o Coralogix RUM de roubar sua rede inicial
Uma ferramenta de RUM tem apenas um trabalho: medir a experiência que seus usuários realmente têm. O Coralogix faz o oposto durante o carregamento. Ele começa a enviar beacons no momento em que você chama init, então se essa chamada estiver no seu bundle principal, o SDK dispara seu primeiro lote na janela de carregamento e hidratação e rouba a rede exatamente do LCP que ele deveria estar medindo.
A ferramenta primeiro prejudica o número e depois o reporta. Isso é o oposto do ideal. Portanto, escrevo uma solução alternativa que armazena os dados em buffer e os envia para a API do Coralogix ao sair da página (assim como o Core/Dash faz por padrão, então se você estiver procurando por uma ferramenta de RUM melhor, considere mudar).
O Coralogix acha que é mais importante do que a sua página
Olhe com o que esse beacon está competindo. Sua hero image. Suas fontes. O script que hidrata a página. Em uma fibra ótica você pode nunca notar isso. Mas nem todos os seus usuários estão em fibra. Em um telefone, em um trem, no wifi do hotel, a largura de banda é escassa e esse beacon luta contra o seu próprio conteúdo por ela. Os visitantes com as piores conexões vão notar. E para quê??
E aqui está a parte que deve te incomodar: não há motivo para todos esses dados iniciais. Nenhum. Os dados são apenas sobre uma visita que ainda está acontecendo. Ninguém está lendo isso ao vivo (e se estiverem, isso seria muito assustador). Pode ficar na memória e ir quando a visita terminar, custar nada e não perder nada. Enviar durante o carregamento tem apenas desvantagens. Só pode desacelerar a página e não traz nenhum benefício. Isso é estúpido. Então recupere o controle: capture todos os eventos, não envie nenhum deles até que a visita termine.

Tudo bem, chega de reclamar. Hora de consertar. É assim que você faz o coralogix se comportar corretamente!
Faça buffer de tudo, não envie nada
O Coralogix oferece um hook beforeSend. Retorne o evento e ele envia. Retorne null e ele descarta. Então coloque o evento em um array primeiro e depois retorne null. Todos os eventos capturados, nada na rede.
import { CoralogixRum } from '@coralogix/browser';
const PUBLIC_KEY = '<YOUR_PUBLIC_KEY>';
const APPLICATION = 'my-app';
// Capture every event, send none of them live.
const buffer = [];
CoralogixRum.init({
public_key: PUBLIC_KEY,
application: APPLICATION,
version: '1.0.0',
coralogixDomain: 'EU1',
beforeSend: (event) => {
buffer.push({ event, t: Date.now() }); // stamp now, flush later
return null; // suppress the SDK's own beacon
},
}); Eu verifiquei se isso captura o que importa, porque beforeSend parece um filtro apenas para erros na documentação. Não é. Ele dispara para todos os tipos de eventos: o snapshot de inicialização, resource timing, todos os Core Web Vitals, interações do usuário e erros. O SDK continua fazendo seu trabalho real, medindo toda a página. Ele apenas fica silencioso na rede até você mandar enviar.
Envie na saída
Agora envie o buffer quando a página for ocultada. É aqui que a versão ingênua morre. Você recorre ao navigator.sendBeacon, porque essa é a maneira de manual para enviar no descarregamento (unload). Isso não funciona aqui. O ingress autentica com um cabeçalho Authorization: Bearer, e o sendBeacon não pode definir cabeçalhos de requisição. Ele retorna true e gera um erro 403 silenciosamente. Use fetch com keepalive em vez disso. Ele sobrevive ao descarregamento da mesma forma e permite que você defina o cabeçalho.
Mais uma coisa que o beacon escondeu de você: o ingress não aceita eventos brutos. O SDK envolve cada um em um span e envia { logs: [...] }. Portanto, reconstrua esse formato antes de enviar.
const INGRESS = 'https://ingress.eu1.rum-ingress-coralogix.com/browser/v1beta/logs';
// swap eu1 for your region (us1, us2, eu2, ap1...) to match coralogixDomain
// The ingress wants the SDK's span shape, not raw events. Rebuild it.
function toCxSpan({ event, t }) {
const hasStack = !!(event.error_context
&& event.error_context.original_stacktrace
&& event.error_context.original_stacktrace.length);
return {
version_metadata: event.version_metadata,
applicationName: APPLICATION,
subsystemName: 'cx_rum',
severity: (event.event_context && event.event_context.severity) || 3,
isErrorWithStacktrace: hasStack,
timestamp: t,
text: { cx_rum: Object.assign({}, event, { timestamp: t }) },
};
}
function flush() {
if (!buffer.length) return;
const logs = buffer.splice(0).map(toCxSpan); // drain: a second call sends nothing
fetch(INGRESS, {
method: 'POST',
keepalive: true, // survives unload, and unlike sendBeacon it can set headers
headers: {
'Authorization': 'Bearer ' + PUBLIC_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ logs, skip_enrichment_with_ip: false }),
}).catch(function () {});
}
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'hidden') flush();
});
window.addEventListener('pagehide', flush); splice esvazia o buffer, então um segundo evento oculto não envia nada. O visibilitychange para hidden é o sinal confiável, mesmo em dispositivos móveis onde o unload nunca dispara. O pagehide é o backup. Uma ressalva: o keepalive compartilha um orçamento de 64 KB entre requisições em andamento (in-flight); portanto, uma sessão longa que armazena milhares de entradas de recursos em buffer pode excedê-lo. Se você coletar muito, divida o array logs em envios menores.
O que isso custa
Você agora está reconstruindo o formato do Coralogix manualmente, tenha cuidado! O session_context é um pouco mais enxuto que o do próprio SDK. O Coralogix preenche o session id, o user agent e o dispositivo depois que o beforeSend é executado, então seus spans construídos manualmente carregam menos desse detalhe do que um beacon normal carregaria. Para a captura dos Core Web Vitals não importa. Para análises profundas de sessão, pode importar. E confirme um 200 na aba Network no primeiro deploy, pois uma chave incorreta ou uma regra rigorosa de CORS falham do mesmo jeito silencioso que o beacon falhava.
Se manter um formato de rede que você não possui não parece uma boa ideia, a alternativa direta é adiar o CoralogixRum.init() até depois da hidratação e deixar o SDK enviar normalmente a partir daí. Você perde as métricas de carregamento pré-init, mas mantém a sua sanidade. Escolha a sua troca.
Seu score do Lighthouse não conta a história toda.
Seus usuários reais estão em Android com 4G. Analiso o que eles vivem de fato.
Analisar dados de campo
