🪣

Next.jsのJavaScrpitエラーをNewRelicで記録する方法

2024/02/22に公開

前回の記事の続きです。
クライアント側のJavaScriptのエラーを監視したかったため、実装方法を確認してみました。

https://zenn.dev/collabostyle/articles/337329e62cff2f

導入手順

前回の設定では足りなかったコードを追記しています。

pagesフォルダ内

pagesフォルダ内にある_document.tsx_error.tsxに対して、以下のコードを記載します。
ファイルがなければ作成してください。

pages/_document.tsx
import newrelic from "newrelic";
import Document, {
  DocumentContext,
  DocumentInitialProps,
  Html,
  Head,
  Main,
  NextScript,
} from "next/document";

type NewRelicProps = {
  browserTimingHeader: string;
};

class MyDocument extends Document<NewRelicProps> {
  static async getInitialProps(
    ctx: DocumentContext
  ): Promise<DocumentInitialProps & NewRelicProps> {
    const initialProps = await Document.getInitialProps(ctx);

    if (!newrelic.agent.collector.isConnected()) {
      await new Promise((resolve) => {
        newrelic.agent.on("connected", resolve);
      });
    }

    const browserTimingHeader = newrelic.getBrowserTimingHeader({
      hasToRemoveScriptWrapper: true,
      allowTransactionlessInjection: true,
    });

    return {
      ...initialProps,
      browserTimingHeader,
    };
  }

  render() {
    return (
      <Html>
        <Head>
          <script
            type="text/javascript"
            dangerouslySetInnerHTML={{ __html: this.props.browserTimingHeader }}
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;
pages/_error.tsx
import { NextPage, NextPageContext } from "next";

type Props = {
  statusCode: number | undefined;
};

const Error: NextPage<Props> = ({ statusCode }) => {
  return (
    <p>
      {statusCode
        ? `An error ${statusCode} occurred on server`
        : "An error occurred on client"}
    </p>
  );
};

Error.getInitialProps = async ({ res, err }: NextPageContext) => {
  if (typeof window == "undefined") {
    const newrelic = await import("newrelic");
    newrelic.noticeError(err);
  } else {
    window.newrelic.noticeError(err);
  }

  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode };
};

export default Error;

JavaScriptコード

クライアントサイドで動作するJavaScirptについて、エラー時にnewrelic.noticeErrorメソッドを利用して、エラー情報を通知することができます。
エラー関連のコンポーネントに組み込んで利用した方が良さそうです。

SampleCode
try {
  throw new Error("Error in button click");
} catch (error) {
  newrelic.noticeError("Error in button click", error);
}

Log出力

また、winstonを利用して、LogをNew Relicに出力することも可能です。

https://github.com/winstonjs/winston

Loggerコンポーネントを作成しておきます。

components/Logger.tsx
import winston from "winston";

const logger = winston.createLogger();

export { logger };

_documents.tsxに以下のコードを追記します。

_documents.tsx
import { logger } from "../components/Logger";

...

logger.info("NextJs New Relic redirecting to a page", {
   application: "NextJs NewRelic app logging",
   test: "Testing logging with Winston",
   pathname: ctx.pathname,
});

New Relic側での確認

New RelicのLog画面を表示して、ログが出力されていることを確認します。

まとめ

ブラウザ側のエラーはnewrelic.noticeErrorを利用して、必要最低限のエラーログを出力する方法が良さげなんでしょうかね🧐

Node.js側の細かな動作ログは、winstonを利用した方法を活用して調査に活用もできそうです。
フレームワークによってNew Relicの導入方法や取得できるデータが異なるので、調査・実装していて面白いです。

コラボスタイル Developers

Discussion