New Relic では、常に開発者のニーズに対応し、革新的なツール、フレームワーク、ライブラリとの統合を図っています。NestJS は、効率的で信頼性が高く、スケーラブルなサーバーサイドアプリケーションの構築を支援する、多くの新しい Node.js フレームワークの 1 つです。これまで、NestJS は TypeScript を使用しており、定義済みのビルドプロセスを使用して ES5 にトランスパイルされるため、New Relic One に統合することは容易ではありませんでした。
しかし、New Relic One observability platform では、Node.js エージェントが提供されており、これを利用すれば、弊社のエージェントとコードサンプルで NestJS を迅速に統合することが可能です。
New Relic Node.js APM エージェント
スケーラビリティというと、マイクロサービスがすぐに思い浮かびます。NestJSは、モジュール性、拡張性、汎用性を提供しますが、それに伴い、アプリケーションのパフォーマンスを観察することが複雑になっています。ここで、このNestJSの統合の出番となります。
このNode.jsエージェントは、Nodeアプリケーションの健全性を表示し、パフォーマンスを測定し、エラーを突き止めることができるだけでなく、サービスマップによってマイクロサービスの関係を可視化し、ディストリビューティッド(分散)トレーシングによってサービス間のリクエストを追跡することが可能です。
Node.jsエージェントとNestJSでマイクロサービスの可観測性を実現する
NestJS と New Relic Node.js エージェントの統合を実証するために、このサンプルアプリを使用します。これは、NestJS を使って書かれた 2 つの Node.js アプリケーションを含む Docker 化されたサービスです。両方のアプリには、NestJS インターセプターの概念を使用して統合された New Relic Node.js エージェントのインスタンスがあります。
親アプリが子インターセプターを呼び出すと、両方のアプリが新しいウェブトランザクションを開始します。アプリ間のリクエストが完了すると、New Relic One 内で利用できるディストリビューティッド(分散)トレーシングで、マイクロサービス間のリクエストのフルパスがわかります。次の画像は、表示されるであろうパスの例を示しています。
New Relic Node.js エージェントを使用した NestJS の統合
最新の JavaScript パターンを使用し、あらかじめ定義されたビルドプロセスを使用して TypeScript から ES5 にトランスパイルされるため、NestJS を New Relic One と統合する際には、いくつかの重要な注意点が存在します。
ファイル拡張子(.ts)
NestJSはTypeScriptを使用しているため、Agentが使用するnewrelic.ts(js)
設定ファイルは、標準の.js
拡張子ではなく、.ts
拡張子で保存することを覚えておくことが重要です。
/src ディレクトリ
通常、newrelic.ts
の設定ファイルは、プロジェクトのルートディレクトリに置くことが推奨されます。NestJSでは、/src
ディレクトリがアプリケーションのルートディレクトリとして扱われます。これは、エントリポイントであるmain.ts
ファイルを含んでいるからです。そのため、newrelic.ts
ファイルを/src
に配置することを忘れないでください。
NestJSインターセプター
次のコードでは、サービスが呼び出されるたびに New Relic エージェントのトランザクションを開始および終了する NestJS インターセプターの実装例を見ることができます。
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelic = require('newrelic');
@Injectable()
export class NewrelicInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return newrelic.startWebTransaction(context.getHandler().name, function () {
const transaction = newrelic.getTransaction();
return next.handle().pipe(
() => transaction.end());
});
}
}
Interceptors は HTTP リクエストを傍受し、この実装では New Relic One にデータを送信します。
この例で分析してみましょう。
- 9行目で
newrelic
モジュールをrequireします。 - アプリケーションに HTTP リクエストが送信されるたびに、インターセプターが起動します。
- 14行目で、
newrelic
モジュールはウェブトランザクションを開始します。また、startWebTransaction
第2引数として、無名関数が渡されているのが確認できます。 - この無名関数はハンドラー関数で、計装する関数を定義しています。
- 15行目で、現在のNew Relic/NestJSのトランザクションを取得します。
- 17行目で、NestJSのコールハンドラーである
next
を使います。 - キャプチャされたHTTPリクエストが呼び出し元に戻ってきたとき、
next.handle()
を呼び出します。 - このときHTTPリクエスト(トランザクション)が完了したことがわかります。New Relicエージェントにトランザクションが完了したことを知らせるために、18行目で
transaction.end()
を使います。
サンプルアプリケーション
NestJS と New Relic で遊んでみたい方は、nestjs-test-app GitHub リポジトリにアクセスし、詳細と手順をご覧ください。このリポジトリには、NestJS アプリケーションと New Relic One を統合するために必要なものがすべて揃っているため、JavaScript と observability の両方の世界における最新技術から恩恵を受けることができます。ご質問がある場合は、リポジトリの管理者にお気軽にお問い合わせください。
次のステップ
このブログ記事の GitHub サンプルを実行するために必要な New Relic One アカウントをまだお持ちでない場合は、無料でサインアップしてください。無料アカウントには、100GB/月の無料データ取り込み、1人の無料フルアクセスユーザー、そして無制限の無料ベーシックユーザーが含まれています。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。