laboratório
Este procedimento faz parte de um laboratório que ensina como solucionar problemas do seu aplicativo da web com o New Relic Browser.
Cada procedimento no laboratório é baseado no anterior, portanto, certifique-se de ter concluído o último procedimento, instrumentar seu aplicativo com nosso agente browser, antes de iniciar este.
Até agora, seu aplicativo funcionou bem. usuário conseguiu fazer seus pedidos e ficou satisfeito com seu atendimento. Mas agora que você tem alguns insights sobre seu aplicativo, você percebe que ele está mostrando alguns erros de JavaScript.
Neste procedimento, você usa New Relic Browser para descobrir o que está causando esses erros e depurar seu aplicativo em tempo hábil.
Importante
Para ver seus dados no New Relic, você precisa ativar para este procedimento.
Se ainda não o fez, instrumente seu aplicativo com nosso agente browser.
Depurar erros de front-end
A má notícia é que você confirmou que há alguns erros no seu aplicativo. A boa notícia é que recentemente você instrumentou sua aplicação com nosso agente browser! Vá para New Relic e faça login em sua conta, caso ainda não o tenha feito.
Na página inicial do New Relic, navegue até Browser e escolha seu aplicativo Relicstaurants .
Aqui você vê todos os dados relacionados ao seu aplicativo de browser, incluindo Page views with JavaScript errors, Core web vitals, User time on the site, Initial page load and route changes e outros.
Dica
Não está vendo seus dados? Certifique-se de ativar o monitoramento do browser e de que seu gerador de carga esteja funcionando.
Observe Page views with javascript errors.
Aqui, você vê picos mostrando que seu aplicativo tem alguns erros de Javascript.
Clique em Page views with javascript errors.
Isso leva você à página JS errors , onde você vê todos os erros JS junto com a instância de erro total.
Clique no erro Cart cannot be empty para obter detalhes.
Aqui você vê errorMessage, INSTANCES, INTERACTIONS AFFECTED e outros detalhes relacionados ao seu erro.
Em seguida, navegue até a guia Error Instances .
Aqui você vê mais detalhes relacionados ao seu erro específico, incluindo Event Log, Stack trace e outros.
Role para baixo na página Error Instances para visualizar o Stack trace.
Aqui, você vê o stack trace do seu erro.
Observando os detalhes do erro acima, agora você conhece o erro específico que afeta seus serviços. No entanto, o stack trace mostrado aqui é reduzido e é difícil entender o que está causando esse erro. Para entender isso, precisamos fazer upload do mapa de origem para minimizar o erro.
Carregue o mapa de origem para desminificar o erro JS
JavaScript minificado resulta principalmente em rastreamento de pilha inútil e difícil de entender na página de erros do browser. O upload de mapas de origem converte esses erros em rastreamento de pilha compreensível. Ele também fornece uma referência útil para linhas de código e facilita a depuração. Você pode fazer upload do seu mapa de fontes para o New Relic via interface, API ou módulo npm.
Aqui, usamos a interface New Relic para fazer upload do mapa de origem e eliminar o erro JS.
Na página de erros JS, navegue até o stack trace do erro e expanda-o.
Aqui, você vê uma opção para fazer upload do mapa de origem.
Clique em find file.
Isso abre uma janela do explorador de arquivos para você fazer upload do mapa de origem do seu armazenamento local. Encontre e carregue seu mapa de origem no diretório build/static/js do seu projeto.
Dica
Os arquivos de mapa de origem têm uma extensão de arquivo .js.map
. Relicstaurants está configurado para gerar mapas de origem e você os encontra no diretório build/static/js . Se você estiver tendo problemas para gerar mapas de origem para o seu projeto, siga nossa documentação para saber como gerar um.
Depois que seu mapa de origem for carregado com sucesso, você verá seu erro não minimizado.
Aqui você vê o arquivo específico e a linha de código que está gerando esse erro. Observe que na linha 119, o Cart cannot be empty! está associado ao evento onClick no arquivo componentes/layouts/app/app-contêiner/header/app-contêiner-header.js e também está acionando um alerta para o usuário. Vamos dar uma olhada neste arquivo!
Abra o aplicativo no IDE de sua preferência e navegue até o arquivo src/components/layouts/app/app-container/header/app-container-header.js . Dê uma olhada mais de perto no código mostrado.
import { Button, Drawer, Table } from 'antd';import Text from 'antd/lib/typography/Text';import { orderList } from 'atoms/order-list.atom';import { useState } from 'react';import { Link } from 'react-router-dom';import { useRecoilState } from 'recoil';import { Logo, StyledHeader } from './app-header-styled';import Navi from './navi-items';import { useNavigate } from 'react-router';
const Header = () => { const [isSidebarVisible, setIsSidebarVisible] = useState(false); const [orderListState, setOrderList] = useRecoilState(orderList); const navigate = useNavigate();
const onClose = () => { setIsSidebarVisible(false); }; const handleSidebarOpen = () => { setIsSidebarVisible(true); };
const itemQuantity = (list) => { let totalItemQuantity = 0; list.forEach((item) => (totalItemQuantity += item.count));
return totalItemQuantity; };
const handleDeleteItem = (clickedRow) => { const reducedData = orderListState.filter((item) => item.name === clickedRow.name ? false : true ); setOrderList(reducedData); };
const columns = [ { title: 'Name', dataIndex: 'name', key: 'name', }, { title: 'Count', dataIndex: 'count', key: 'count', }, { title: 'Price', dataIndex: 'price', key: 'price', }, { title: 'Delete', render: (clickedRow) => ( <Button onClick={() => handleDeleteItem(clickedRow)}>-</Button> ), }, ];
return ( <StyledHeader> <Link to="/"> <Logo> <div>Relicstaurants</div> <p>by New Relic</p> </Logo> </Link> <Navi sidebarVisible={handleSidebarOpen} orderListLength={itemQuantity(orderListState)} /> <Drawer size="large" title="Cart" placement="right" onClose={onClose} visible={isSidebarVisible} > <Table dataSource={orderListState} columns={columns} pagination={false} summary={(pageData) => { let totalPrice = 0;
pageData.forEach( ({ price, count }) => (totalPrice += price * count) );
return ( <> <Table.Summary.Row> <Table.Summary.Cell colSpan={2}>Total</Table.Summary.Cell> <Table.Summary.Cell> <Text type="danger">{totalPrice.toFixed(2)}</Text> </Table.Summary.Cell> </Table.Summary.Row> <Table.Summary.Row> <Table.Summary.Cell colSpan={3}> <Button disabled={totalPrice > 0 ? false : true} primary onClick={() => { setOrderList([]); setIsSidebarVisible(false); }} > Clear Cart </Button> </Table.Summary.Cell> <Table.Summary.Cell> <Button id="pay" primary onClick={() => { if (!(totalPrice > 0)) { var err = new Error('Cart cannot be empty!'); newrelic.noticeError(err); alert(err) navigate('/') setIsSidebarVisible(false); } else { navigate(`/payment`, { state: totalPrice }); setIsSidebarVisible(false); } }} > PAY </Button> </Table.Summary.Cell> </Table.Summary.Row> </> ); }} /> </Drawer> </StyledHeader> );};
export default Header;
Aqui, observe que o erro Cart cannot be empty! só ocorre sempre que o usuário tenta acidentalmente finalizar a compra com o carrinho vazio. A função é codificada para alertar o usuário final de que ele não pode finalizar a compra com o carrinho vazio. Agora você sabe que esse erro não afetará seus serviços. No entanto, existem maneiras melhores de lidar com esse caso extremo e evitar o erro.
Pressione Ctrl+C
no terminal que está executando seu aplicativo para interromper a veiculação dele. Atualize src/components/layouts/app/app-container/header/app-container-header.js da seguinte maneira.
import { Button, Drawer, Table } from 'antd';import Text from 'antd/lib/typography/Text';import { orderList } from 'atoms/order-list.atom';import { Message } from 'components/common';import { useState } from 'react';import { Link } from 'react-router-dom';import { useRecoilState } from 'recoil';import { Logo, StyledHeader } from './app-header-styled';import Navi from './navi-items';import { useNavigate } from 'react-router';
const Header = () => { const [isSidebarVisible, setIsSidebarVisible] = useState(false); const [orderListState, setOrderList] = useRecoilState(orderList); const navigate = useNavigate();
const onClose = () => { setIsSidebarVisible(false); }; const handleSidebarOpen = () => { setIsSidebarVisible(true); };
const itemQuantity = (list) => { let totalItemQuantity = 0; list.forEach((item) => (totalItemQuantity += item.count));
return totalItemQuantity; };
const handleDeleteItem = (clickedRow) => { const reducedData = orderListState.filter((item) => item.name === clickedRow.name ? false : true ); setOrderList(reducedData); };
const columns = [ { title: 'Name', dataIndex: 'name', key: 'name', }, { title: 'Count', dataIndex: 'count', key: 'count', }, { title: 'Price', dataIndex: 'price', key: 'price', }, { title: 'Delete', render: (clickedRow) => ( <Button onClick={() => handleDeleteItem(clickedRow)}>-</Button> ), }, ];
return ( <StyledHeader> <Link to="/"> <Logo> <div>Relicstaurants</div> <p>by New Relic</p> </Logo> </Link> <Navi sidebarVisible={handleSidebarOpen} orderListLength={itemQuantity(orderListState)} /> <Drawer size="large" title="Cart" placement="right" onClose={onClose} visible={isSidebarVisible} > {orderListState.length > 0 ? ( <Table dataSource={orderListState} columns={columns} pagination={false} summary={(pageData) => { let totalPrice = 0;
pageData.forEach( ({ price, count }) => (totalPrice += price * count) );
return ( <> <Table.Summary.Row> <Table.Summary.Cell colSpan={2}>Total</Table.Summary.Cell> <Table.Summary.Cell> <Text type="danger">{totalPrice.toFixed(2)}</Text> </Table.Summary.Cell> </Table.Summary.Row> <Table.Summary.Row> <Table.Summary.Cell colSpan={3}> <Button disabled={totalPrice > 0 ? false : true} primary onClick={() => { setOrderList([]); setIsSidebarVisible(false); }} > Clear Cart </Button> </Table.Summary.Cell> <Table.Summary.Cell> <Button id="pay" disabled={totalPrice > 0 ? false : true} primary onClick={() => { navigate(`/payment`, { state: totalPrice }); setIsSidebarVisible(false); }} > PAY </Button> </Table.Summary.Cell> </Table.Summary.Row> </> ); }} /> ) : ( <Message>Nothing in cart</Message> )} </Drawer> </StyledHeader> );};
export default Header;
Aqui, você modificou o arquivo para mostrar uma mensagem Nothing in cart em vez de um erro quando o carrinho está vazio. O botão PAY permanece desabilitado até que o usuário final tenha itens em seu carrinho.
Reinicie seu aplicativo
Agora que você corrigiu seu aplicativo, é hora de reiniciar o servidor local.
$npm run build$npm run newstart
Reinicie seu gerador de carga também.
$python3 simulator.py
Importante
Certifique-se de executar esses comandos nas janelas de terminal corretas. Se você não tiver mais essas janelas, siga as etapas do procedimento de configuração.
Assim que o gerador de carga começar a enviar dados para o New Relic, observe que o aplicativo não está mais relatando erros de JavaScript.
Resumo
Para recapitular, você observou um erro em seu aplicativo e usou New Relic Browser para:
- Revise a porcentagem de erro
- Analise os erros de JS no seu aplicativo
- Entenda a instância do erro
- Depure o erro JS fazendo upload do mapa de origem
laboratório
Este procedimento faz parte de um laboratório que ensina como solucionar problemas do seu aplicativo da web com o New Relic Browser. A seguir, tente depurar a lentidão do frontend em seu aplicativo.