• EnglishEspañol日本語한국어Português
  • ログイン今すぐ開始

この機械翻訳は参考用に提供されます。

英語版と翻訳版に矛盾がある場合は、英語版が優先されます。詳細については、このページ を参照してください。

問題を作成する

ラボ パート 3: アプリケーションのエラーをデバッグする

ラボ

この手順は、New Relic ブラウザーを使用して Web アプリをトラブルシューティングする方法を説明するラボの一部です。

ラボの各手順は前回の手順に基づいているため、この手順を開始する前に、最後の手順で あるブラウザ エージェントを使用してアプリケーションをインストルメント化するを完了していることを確認してください。

これまで、アプリケーションは正常に動作していました。ユーザーは注文を行うことができ、サービスに満足しました。しかし、アプリケーションでいくつかの洞察を得たので、いくつかの JavaScript エラーが表示されていることに気付きました。

この手順では、New Relic ブラウザーを使用してこれらのエラーの原因を突き止め、アプリケーションをタイムリーにデバッグします。

重要

New Relic でデータを表示するには、以下を有効にする必要があります。 この手順のために。

まだ行っていない場合は、 ブラウザ エージェントを使用してアプリをインストルメント化します

フロントエンドエラーをデバッグする

悪いニュースは、アプリケーションにいくつかのエラーがあることを確認したことです。良いニュースは、最近、アプリケーションに当社のブラウザー エージェントを組み込んだことです。アカウントにまだサインインしていない場合は、New Relic に移動してサインインします。

New Relic ホームページから Browser に移動し、 Relicstaurants アプリケーションを選択します。

ここには、ブラウザ アプリケーションに関連するすべてのデータが表示されます。これには、 JavaScript エラーのあるページ ビュー主要なウェブ バイタルサイトでのユーザー時間最初のページの読み込みとルートの変更などがあります。

ヒント

データが表示されませんか?ブラウザーの監視が有効になっており、Load Generator が実行されていることを確認してください。

JavaScript エラーのあるページビューに注意してください。

ここでは、アプリケーションに Javascript エラーがあることを示すスパイクが表示されます。

Page views with javascript errors[JavaScript エラーのあるページ ビュー]をクリックします。

これにより、 JS errors[JS エラー] ページが表示され、すべての JS エラーと合計エラー インスタンスが表示されます。

詳細については 、Cart cannot be empty[カートを空にすることはできません] エラーをクリックしてください。

ここには、 errorMessageINSTANCESINTERACTIONS AFFECTED 、およびエラーに関連するその他の詳細が表示されます。

次に、 Error Instances[エラー インスタンス] タブに移動します。

ここには、 イベント ログスタック トレースなど、特定のエラーに関連する詳細が表示されます。

Error Instances[エラー インスタンス] ページを下にスクロールして、 Stack trace[スタック トレース]を表示します。

ここに、エラーのスタック トレースが表示されます。

上記のエラーの詳細を見ると、サービスに影響を与える特定のエラーがわかります。ただし、ここに示すスタック トレースは縮小されているため、このエラーの原因を理解するのは困難です。これを理解するには、ソース マップをアップロードしてエラーの縮小を解除する必要があります。

ソース マップをアップロードして JS エラーを非縮小化する

縮小された JavaScript は、ほとんどの場合、ブラウザーのエラー ページにわかりにくく、役に立たないスタック トレースが表示されます。ソース マップをアップロードすると、これらのエラーがわかりやすいスタック トレースに変換されます。また、コード行への便利なリファレンスを提供し、デバッグを容易にします。UI、API、または npm モジュールを介してソース マップを New Relic にアップロードできます。

ここでは、New Relic UI を使用してソース マップをアップロードし、JS エラーを縮小解除します。

JS エラー ページから、エラーのスタック トレースに移動し、展開します。

ここに、ソース マップをアップロードするオプションが表示されます。

find file[ファイルを検索]をクリックします。

これにより、ローカル ストレージからソース マップをアップロードするためのファイル エクスプローラー ウィンドウが開きます。プロジェクトの build/static/js ディレクトリからソース マップを見つけてアップロードします。

ヒント

ソース マップ ファイルのファイル拡張子は.js.mapです。Relicstaurants はソース マップを生成するように設定されており、 build/static/jsディレクトリにあります。プロジェクトのソース マップの生成に問題がある場合は、 ドキュメントに従ってソース マップを生成する方法を学習してください。

ソース マップが正常にアップロードされると、縮小されていないエラーが表示されます。

ここに、このエラーを生成している特定のファイルとコード行が表示されます。119 行目で、Cart cannot be empty!components/layouts/app/app-container/header/app-container-header.js ファイルの onClick イベントに関連付けられていることに注意してください。ユーザーへのアラートのトリガー。このファイルを詳しく見てみましょう。

選択した IDE でアプリケーションを開き、 src/components/layouts/app/app-container/header/app-container-header.js ファイルに移動します。表示されたコードを詳しく見てください。

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;
src/components/layouts/app/app-container/header/app-container-header.js

ここで、エラー Cart cannot be empty!に注意してください ユーザーが空のカートで誤ってチェックアウトしようとした場合にのみ発生します。この関数は、カートが空の状態ではチェックアウトに進むことができないことをエンド ユーザーに警告するようにコーディングされています。このエラーがサービスに影響しないことがわかりました。ただし、この特殊なケースを処理してエラーを回避するためのより良い方法があります。

アプリケーションを実行している端末で Ctrl+C を押して、サービスの提供を停止します。 src/components/layouts/app/app-container/header/app-container-header.js を 次のように更新します。

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;
src/components/layouts/app/app-container/header/app-container-header.js

ここでは、カートが空である場合にエラーの代わりにメッセージ Nothing in cart を表示するようにファイルを変更しました。エンド ユーザーがカートにアイテムを入れるまで、 PAY ボタンは無効のままです。

アプリケーションを再起動します

アプリケーションを修正したので、ローカル サーバーを再起動します。

bash
$
npm run build
$
npm run newstart

Load Generator も再起動します。

bash
$
python3 simulator.py

重要

これらのコマンドを正しいターミナル ウィンドウで実行していることを確認してください。これらのウィンドウが表示されなくなった場合は、 セットアップ手順の手順に従ってください。

Load Generator が New Relic へのデータ送信を開始すると、アプリケーションが JavaScript エラーを報告しなくなったことに注意してください。

概要

要約すると、アプリケーションでエラーを確認し、New Relic ブラウザーを使用して次のことを行いました。

  1. エラー率を確認する
  2. アプリケーションの JS エラーを分析する
  3. エラーインスタンスを理解する
  4. ソース マップをアップロードして JS エラーをデバッグする

ラボ

この手順は、New Relic ブラウザーを使用して Web アプリのトラブルシューティングを行う方法を説明するラボの一部です。次に、 アプリケーションのフロントエンドの遅さをデバッグしてみてください。

Copyright © 2024 New Relic株式会社。

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.