New Relic Browser: Tracking User Experience with First Paint and First Contentful Paint Metrics
Em um blog post chamado Web Page Usability Matters, o Gerente de Engenharia do Google Chrome Addy Osmani escreveu, “Carregar uma página é uma jornada progressiva com quatro momentos chaves: Está acontecendo? É útil? É usável? E é agradável?
As páginas web estão mais dinâmicas do que nunca e uma única métrica não é o suficiente para entender a performance e experiência do usuário final.
Este post tem por objetivo misturar a explicação de conceitos envolvendo carregamento de páginas web, métricas de experiência do usuário e sua importância, atrelado a como extrair essas métricas do New Relic.
Lembrando que o objetivo não é ensinar a mexer na plataforma do New Relic, portanto, vou considerar que você sabe o que é um Dashboard, como criar um gráfico (chart) e tem noções de NRQL (New Relic Query Language) que é a “linguagem SQL do New Relic”.
Lista de etapas de page load timeline
presentes na imagem:
DOM Content Load
;window load
é disparado;Durante esse processo, muito coisa pode acontecer, sendo assim, é bom ter em mente que a velocidade o qual seu site será renderizado depende de diversas variáveis, tais como:
Então, vejamos algumas métricas clássicas de carregamento.
Loading Metrics
Métricas tradicionais como DOM Content Loaded
e Page Load
(historicamente medida pelo evento de window.load
) por si só são pouco efetivas para monitorar sites modernos. No entanto, não podemos descartar sua importância e as oportunidades de melhoria que nos trazem ao serem analisadas. Vejamos brevemente como cada uma funciona.
Document: DOMContentLoaded event
O evento DOMContentLoaded é disparado quando o documento HTML inicial foi completamente carregado e parseado, sem esperar por estilos, imagens e subframes finalizarem seu carregamento.
Window: load event
O eventoload
é disparado quando uma página está totalmente carregada, incluindo os recursos dependentes como estilos, scripts, iframes e imagens. É diferente do DOM Content Loaded que dispara sem esperar pelos recursos finalizarem seus carregamentos.
E agora, vamos ver como podemos criar gráficos no New Relic que nos auxiliem a mensurar essas informações.
Vamos criar um histograma baseado na duração do tempo do evento Pageview
pegando dados de uma semana para termos uma base consistente onde a url contém www.teste.com.br
SELECT histogram(duration, width: 10, buckets: 20)
FROM PageView
SINCE 1 week ago
WHERE pageUrl LIKE '%www.teste.com.br%'
O que é um histograma
Um histograma é similar a um gráfico de barras, porém, cada barra representa um intervalo ao invés de um número específico. Histogram charts mostram o response time distribuído em um período selecionado de tempo. O New Relic intencionalmente corta a porcentagem da amostragem para 95% visto que esses 5% restantes são exceções (requisições aleatórias que tomaram muito tempo) e poluiriam as estatísticas.
No exemplo abaixo apesar da função utilizada de histogram
criamos um heatmap
das mesmas informações só que agora por categorizadas por url.
Page Load By Url
SELECT histogram(duration, width: 10, buckets: 20)
FROM PageView
SINCE 1 week ago
WHERE pageUrl LIKE '%www.teste.com.br%'
FACET pageUrl
Lembrando que a duração (duration) do tempo de carregamento da página no New Relic é calculada desde quando o usuário clica num hyperlink até que a página esteja totalmente carregada e dispare o evento window load event
( Navigation Timing API loadEventEnd
menos navigationStart
).
Slowest Page Loads
SELECT max(duration)
FROM PageView
WHERE appName = 'MVC-Frontend (GCP)' AND pageUrl LIKE '%www.magazinevoce%'
FACET pageUrl
SINCE 1 week ago LIMIT 50
Atenção
Por empirismo percebi que a propriedadeappName
apesar de estar disponível não funciona bem com queries porPageView
. A melhor opção é fazer umWHERE
compageUrl
s da aplicação ou utilizar ambas as condições.
Métricas de performance centradas no usuário são críticas para os times de desenvolvimento frontend que desejam mensurar e melhorar a experiência dos clientes.
User Centric Perceived Performance metrics
Métricas que identificam a “performance percebida” podem trazer luz em relação a essa experiência do usuário e ajudar a entender o quão rápido as páginas estão carregando. Essas métricas ajudam a responder a pergunta: “Quanto tempo passa antes do usuário ver o conteúdo?”
A seguir temos ilustração de google.developer.com que mostra a relação entre firstInputDelay, firstInteraction (ou TTI), firstContentfulPaint, e a thread principal do browser. (Creative Commons Attribution 4.0 License)
Falando sobre Paint
é bom deixarmos claro que o New Relic se baseia na PerformancePaintTiming API
e que por sua vez não está disponível em todos os browsers, como mostra o site Can I Use ( PerformancePaintTiming API ).
First Paint é o tempo entre a navegação e quando o navegador renderiza o primeiro pixel na tela, renderizando qualquer coisa que é visualmente diferente do background color padrão do body.
É possível extrair essas informações do Pageview
no entanto a documentação do New Relic aconselha utilizar o PageViewTiming
: PageViewTiming - Async or dynamic page details.
First Paint
SELECT histogram(firstPaint, 10, 20)
FROM PageViewTiming
SINCE 24 hours ago
WHERE pageUrl LIKE '%www.magazinevoce%'
First Paint by url
SELECT histogram(firstPaint,10,20)
FROM PageViewTiming
SINCE 1 week ago
WHERE appName = 'MVC-Frontend (GCP)' AND pageUrl LIKE '%www.magazinevoce%'
FACET pageUrl
Median First Paint times by browser
SELECT percentile(firstPaint, 50)
FROM PageViewTiming
SINCE 1 week ago
WHERE appName = 'MVC-Frontend (GCP)' AND pageUrl LIKE '%www.magazinevoce%'
FACET userAgentName
Median First Paint by browser and agent
SELECT percentile(firstPaint, 50)
FROM PageViewTiming
SINCE 1 week ago
WHERE appName = 'MVC-Frontend (GCP)' AND pageUrl LIKE '%www.magazinevoce%'
FACET userAgentName, userAgentVersion
Median First Paint times from Microsoft Edge by Url
SELECT percentile(firstPaint, 50)
FROM PageViewTiming
SINCE 1 week ago
WHERE appName = 'MVC-Frontend (GCP)' AND pageUrl LIKE '%www.magazinevoce%' AND userAgentName = 'Microsoft Edge'
FACET pageUrl
First Contentful Paint ocorre quando o navegador renderiza qualquer conteúdo do DOM, incluindo qualquer texto, imagem, canvas ou svg. A imagem abaixo ilustra esse conceito:
Google developer guide: User-centric Performance Metrics
Why only consider the first input delay metric - Google Web Dev
A primeira impressão que os usuários têm de quão rápido seu site carrega pode ser medida com a First Contentful Paint (FCP). Mas a rapidez com que seu site pode renderizar pixels na tela é apenas parte da história. Igualmente importante é a capacidade de resposta do seu site quando os usuários tentam interagir com esses pixels!
Median paint and load times
SELECT percentile(timeToResponseStart, 50) AS 'first byte', percentile(firstPaint, 50) as 'First paint', percentile(firstContentfulPaint, 50) as 'First contentful paint' , percentile(timeToDomContentLoadedEventEnd, 50) AS 'DOM content loaded', percentile(duration, 50) AS 'Window load + AJAX'
FROM BrowserInteraction
SINCE 2 days ago UNTIL now
WHERE appName = 'MVC-Frontend (GCP)'
TIMESERIES
Median firstContentfulPaint with historical performance
SELECT percentile(firstContentfulPaint, 50) as 'First contentful paint'
FROM BrowserInteraction
WHERE appName = 'MVC-Frontend (GCP)'
SINCE 1 day ago
COMPARE WITH 2 days ago
TIMESERIES
Quando estamos falando de performance de carregamento de página nenhuma métrica conta a história como um todo. A métrica LCP é provavelmente uma das mais representativas quando falamos de performance percebida de um site em RUM (Real User Monitoring
). É confiável, consistente e fácil de entender.
Web.dev
Largest Contentful Paint - LCP (maior renderização de conteúdo) é uma métrica Core Web Vitals e mede quando o maior elemento de conteúdo na janela de visualização se torna visível. Ela pode ser usada para determinar quando o conteúdo principal da página terminou de ser renderizado na tela.
Largest Contentful Paint
SELECT percentile(largestContentfulPaint, 75)
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)' AND timingName = 'largestContentfulPaint' SINCE 1 week ago
Largest Contentful Paint by Experience
SELECT percentage(count(*), WHERE largestContentfulPaint < 2.5) AS 'good', percentage(count(*), WHERE largestContentfulPaint >= 2.5 and largestContentfulPaint < 4) AS 'needs improvement', percentage(count(*), WHERE largestContentfulPaint >= 4) AS 'poor'
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)' AND timingName = 'largestContentfulPaint' SINCE 1 week ago
Largest Contentful Paint by Url
SELECT percentile(largestContentfulPaint, 75)
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)' AND timingName = 'largestContentfulPaint' AND pageUrl LIKE '%www.magazinevoce%'
FACET pageUrl
SINCE 1 week ago
Largest Contentful Paint by Browser
SELECT percentile(largestContentfulPaint, 75)
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)' AND timingName = 'largestContentfulPaint' AND pageUrl LIKE '%www.magazinevoce%'
FACET userAgentName
SINCE 1 week ago
Interactivity metrics
Métricas de interação auxiliam a medir e melhorar a experiência do usuário evidenciando pontos como:
First Interaction captura o momento que o usuário engaja pela primeira vez com o site, essa interação pode ser do tipo: click
, keydown
, mousedown
, pointerdown
e touchstart
(desconheço a existência de outros).
Esse timestamp representa o primeiro passo no cálculo do First Input Delay
, que é o tempo da primeira interação ( First Interaction
) até o momento que o site responde (is interactive).
Para determinar se certas interações performam melhor do que outras, podemos utilizar a query abaixo.
Median firstInteraction by interactionType
SELECT percentile(firstInteraction, 50)
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)'
FACET interactionType
Para encontrar padrões que determinem o quão cedo os usuários interagem com o conteúdo depois dele estar visível na página, podemos seguir com o exemplo abaixo.
Median firstInteraction compared to firstPaint and firstContentfulPaint
SELECT percentile(firstContentfulPaint, 50), percentile(firstPaint, 50), percentile(firstInteraction, 50)
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)'
SINCE 2 days ago
TIMESERIES
First Input Delay mede o tempo entre o usuário interagir com o site e o mesmo responder. O usuário pode, por exemplo, ter clicado em algo e o navegador com a main thread ocupada, carregando um arquivo Javascript enorme e impossibilitado de responder.
Em outras palavras, a ideia que seu código rodará imediatamente após um evento é falsa.
Why only consider the first input delay metric - Google Web Dev
First Input Delay (FID), ou Atraso da Primeira Entrada, é uma métrica importante e centrada no usuário para medir a responsividade do carregamento porque quantifica a experiência que os usuários sentem ao tentar interagir com páginas que não respondem: uma FID baixa ajuda a garantir que a página seja utilizável.
Why only consider the first input delay metric - Google Web Dev
Para fornecer uma boa experiência ao usuário, os sites devem se esforçar para ter uma First Input Delay de 100 milissegundos ou menos. Para garantir que você está atingindo essa meta para a maioria de seus usuários, um bom limite para medir é o 75º percentil de carregamentos de página, segmentado em dispositivos móveis e desktop.
Para determinar se certas interações performam melhor que outras podemos utilizar a query abaixo:
Median firstInputDelay by interactionType
SELECT percentile(firstInputDelay, 50)/1000
FROM PageViewTiming
SINCE 1 day ago
TIMESERIES
FACET interactionType
Encontre a diferença de performance por navegador e versão:
Median firstInputDelay by Browser/version
SELECT percentile(firstInputDelay, 50)/1000
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)'
SINCE 1 day ago
TIMESERIES
FACET userAgentName, userAgentVersion
Visual Stability metrics
Mede o quanto os elementos de uma página se movem ou alteram seus tamanhos afetando o posicionamento dos conteúdos ao seu redor.
Cumulative Layout Shift
SELECT percentile(cumulativeLayoutShift, 75)
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)' AND timingName = 'pageHide'
SINCE 1 week ago
Cumulative Layout Shift by Experience
SELECT percentage(count(*), WHERE cumulativeLayoutShift < 0.1) AS 'good', percentage(count(*), WHERE cumulativeLayoutShift >= 0.1 AND cumulativeLayoutShift < 0.25) AS 'needs improvement', percentage(count(*), WHERE cumulativeLayoutShift >= 0.25) AS 'poor', percentage(count(*), WHERE cumulativeLayoutShift is null) AS 'unknown'
FROM PageViewTiming
WHERE appName = 'MVC-Frontend (GCP)' AND timingName = 'pageHide'
SINCE 2 week ago