TVer広告事業本部の髙品です。 こちらはTVer Advent Calendar 2023の21日目の記事です。
本記事では、New RelicのChange Trackingという機能について書きたいと思います。
本記事を書く背景
Change Trackingを説明する前に、本記事を書く背景をお話させてください。
私は、2023年11月にTVer広告事業本部のエンジニアチームに参加しました。広告事業本部のエンジニアチームは、主に「TVer」で配信される広告プロダクト「TVer広告」の配信システム・広告周辺領域のシステムを開発・保守しています。TVerのエンジニア組織に関心がある方は、弊社採用サイトのプロダクト職向けのページをご覧ください。
さて、入社したばかりの私は現在オンボーディングの最中でして、広告のドメイン用語や既存システムの構成をやっと覚えたばかりなので、業務を絡めた記事を書くことができない状況です。そんな中で、アドベントカレンダーに参加するために捻り出したネタが、いまチームで導入を進めているNew RelicのChange Trackingでした。
New Relicを使って私が目指すチームのあり方
私はこれまでインフラエンジニア、SREとして働いてきたので、システムの運用が比較的得意です。今までの経験を活かしてチームに貢献したいと考えたときに、システムの信頼性と開発の生産性を共に最適化できるチームをつくりたい、と考えました。そのために取り組みたいことの一つに、チームがオブザーバビリティツールを使いこなせるようにする、というものがあります。
SREやDevOpsに関心があるチームでは、何らかのオブザーバビリティツールを利用していると思いますが、私が所属するチームはNew Relicを使っています。New Relicは高機能なツールですが、所属チームではまだ一部の機能しか使えておらず、活用しているとは言えない状況です。また、普段からNew Relicを見ているメンバーは数名に限られています。
私は、信頼性と生産性を共に最適化できるチームにおいて、システムの状態はメンバー全員の関心事であるべきだと考えているので、チームの全員にNew Relicの画面を見てほしいと思っています。そこで、チームでNew Relicのダッシュボードを見て、アプリケーションのレイテンシーやスループット、エラー率といったパフォーマンス指標の傾向を知ることでシステムの状態を把握する定点観測の時間を作ろうとしています。いずれは、SREのサービスレベルの考え方をチームのシステム運用に導入することを見据えての活動です。
前置きが長くなりましたが、ダッシュボードを見てシステムの状態を把握しようと思うときに便利な機能が、New RelicのChange Trackingです。ここからは、Change Trackingの便利な点と、この機能の導入手順を紹介します。手軽に導入できるので、New Relicのユーザーにはぜひ試してほしい機能です。
Change Trackingの便利な点
まず、Change Trackingの便利な点を一言で述べると、アプリケーションの変更(アプリケーションのデプロイイベント)をグラフ上に表示することで、変更によるパフォーマンスへの影響があったかどうか分かりやすくなる、というものです。
あとで導入手順を紹介する際にキャプチャを貼りますが、New Relicのブログの説明を読んでいただくと、この機能について理解し易いと思います。リンク先の画像を見るとResponse time(ms)とThroughputのグラフの上に縦方向の点線が入っていますが、この時点でシステムに変更が加えられたことを意味しています。もし、ある点線を境にグラフに変化が生じた場合、その点線が指している変更と関連性があることがすぐに分かります。
とてもシンプルな機能ですが、これだけでグラフから読み取れる情報量が増えます。グラフを集めたダッシュボードを眺めていると、パフォーマンスは安定していることもあれば、悪くなったり良くなったりすることもあるでしょう。特に悪化した場合は原因を調査する必要がありますが、単にグラフがそこにあるだけでは、ある時点から悪くなった、ということしか読み取れません。そこから先は、アプリケーションのソースコードが置かれたリポジトリや、ログ・メトリクスなどが保存された場所などを見て回って、パフォーマンス悪化要因となるイベントがないか探すことになります。ところが、グラフ上にアプリケーションの変更も一緒に記録されていると、New Relicの画面からすぐに関連のあるイベントを特定することができます。
New Relicにアプリケーションの変更を記録するときはアプリケーションのバージョンの情報を送る必要があります。一般的にはコミットハッシュやタグがバージョン情報として使用されます。こちらのNew Relicのドキュメントに載っている1つ目のキャプチャのように、点線にマウスオーバーするとアプリケーションのバージョンが表示されるため、パフォーマンスを変化させた可能性がある変更がすぐに分かります。Change Trackingを使用することで、パフォーマンス悪化の要因を特定して修復するまでにかかる時間(MTTR)を短縮できる可能性があります。
Change Trackingの導入手順
基本的にはこちらのNew Relicのドキュメントに記載の手順に従えば、難なく導入できると思います。特にJenkinsもしくはGitHub Actionsを使用している場合は、New Relic社が提供しているpluginやactionを追加してパラメータを渡すだけで使うことができます。
本記事では、NerdGraph(GraphQL)APIを使用するユーザーに参考になる手順として、Bitbucket pipelinesからChange Trackingを使う方法を紹介したいと思います。紹介する手順は、いくつかの環境変数を除けばCIツールに依存しない方法です。
さて、NerdGraph APIにデータを送信するためにHTTPクライアントを準備する必要がありますが、多くの環境で追加インストールが不要であると思われるcurlコマンドを使います。New RelicのAPIエンドポイントにJSONをPOSTする必要があるので、まずはcurlコマンドを組み立てていきます。
ここからはcurlコマンドを組み立てる手順です。まず、New Relicにログインして、画面左のアイコン群から虫眼鏡を選んで、検索窓に「Apps」と入力して選択してください。Your appsと表示されているアプリの中に「NerdGraph API Explorer」があるので、選択して開いてください。私はこのアプリにスターをつけているので、Favorite appsに移動しています。
するとGraphQLのクエリを組み立てる画面が開くので、mutationの一覧から「changeTracking」を探して「changeTrackingCreateDeployment」にチェックを入れてください。
続いて、以下のキャプチャと同じようにチェックを入れてください。オプション属性ですが、本記事ではdeepLink
にもチェックを入れています。必須属性はentityGuid
とversion
です。指定可能な属性についてはこちらのNew Relicのドキュメントを参照してください。キャプチャではtestと入力していますが、実際のentityGuid
はNew Relicにおいてアプリケーションを特定するために振られた一意のID,version
はコミットハッシュ、タグ等が入ります。
画面左上の「tools」を押して、「Copy as CURL」を押すとクリップボードに以下のようなコマンドがコピーされます。
curl https://api.newrelic.com/graphql \ -H 'Content-Type: application/json' \ -H 'API-Key: your USER key' \ --data-binary '{"query":"mutation {\n changeTrackingCreateDeployment(\n deployment: {entityGuid: \"test\", version: \"test\", deepLink: \"test\"}\n ) {\n entityGuid\n version\n deepLink\n }\n}", "variables":""}'
API-Keyヘッダーの値、entityGuid
とversion
に適切な値が入力された状態でコマンドを実行すると、entityGuid
に対応するNew Relic APM, Browserのアプリケーションのグラフ上に点線が引かれたはずです。このようにNerdGraph API Explorerでcurlコマンドを生成すると楽ですから、使ってみてください。
ところで、Bitbucket pipelinesのようなCIツールでこのcurlコマンドを実行するときは、各属性値はパラメータにしておかないと使い物になりません。Bitbucket pipelinesで使いやすいようにコマンドを以下のように修正します。(ついでにシェルスクリプトファイルにします)
#!/usr/bin/env bash set -euo pipefail curl -X POST https://api.newrelic.com/graphql \ -H "Content-Type: application/json" \ -H "API-Key: $NEW_RELIC_USER_KEY" \ --data-binary '{"query":"mutation {\n changeTrackingCreateDeployment(deployment: {version: \"'"$BITBUCKET_COMMIT"'\", entityGuid: \"'"$NEW_RELIC_ENTITY_GUID"'\", deepLink: \"'"$BITBUCKET_GIT_HTTP_ORIGIN"/commits/"$BITBUCKET_COMMIT"'\"}) {\n deploymentId\n entityGuid\n deepLink\n }\n}"}'
BITBUCKET_
のprefixを持つ変数は、Bitbucket pipelines固有の変数です。使用可能な変数はBitbucketのこちらのドキュメントを参照してください。他のツール使う場合は、適当に書き替えてください。
$NEW_RELIC_USER_KEY
はBitbucket pipelinesのリポジトリ変数やデプロイ変数に、保護された変数としてセットしておきます。機密情報なので扱いに注意してください。
$BITBUCKET_COMMIT
はCI(パイプライン)を起動したブランチのコミットハッシュが入ります。
$NEW_RELIC_ENTITY_GUID
も、$NEW_RELIC_USER_KEY
と同様にします。
$BITBUCKET_GIT_HTTP_ORIGIN
には、リポジトリのURLが入ります。
$BITBUCKET_GIT_HTTP_ORIGIN
+commits+$BITBUCKET_COMMIT
を連結することで、コミットに含まれる内容が記されたURLを作成することができます。URLを動的に生成してdeepLink
の値に格納することで、New Relicの画面からリポジトリに移動しやすくします。
変数展開についても補足しておきます。シングルクォート内ではすべての文字が特別な意味を持たなくなるため、"$BITBUCKET_COMMIT"
と書くと変数展開が行われません。そのため、本記事では環境変数をシングルクォートで囲うことで変数展開されるようにしています。上記のJSON程度の長さであれば、個人的にはこの方法で構わないと感じますが、より複雑な構造のJSONをPOSTするときは他の書き方にしないと、可読性が悪くなると思います*1。
もう一つ、tipsを書いておきます。curlコマンドを、CIの定義ファイル内の別々の箇所に繰り返し書くのは筋が悪いです。コマンドを修正するときに、修正漏れしてしまう懸念があります。本記事では、処理を共通化するためにシェルスクリプトファイルに書いておき、各環境のCIを実行するときにsourceコマンドで呼び出すようにします。例えばBitbucket pipelinesでは以下のように記述できます。
- step: name: Send deployment event to NewRelic ChangeTracking deployment: develop script: - source ./scripts/newrelic_change_tracking.sh - step: name: Send deployment event to NewRelic ChangeTracking deployment: production script: - source ./scripts/newrelic_change_tracking.sh
deployment: env
の記述により、事前定義されたデプロイ変数が読み込まれます。デプロイ変数は、CIを実行するときに環境固有のパラメータを参照したいケース等で便利です*2。本記事の文脈では、$NEW_RELIC_USER_KEY
と$NEW_RELIC_ENTITY_GUID
は環境固有の値なので、これらをデプロイ変数としてセットしておくと、処理そのものはシェルスクリプトファイルに書いて共通化しながら、スクリプトの実行時に環境固有の値を参照することができます。
以上を設定してBitbucket pipelinesでCIを実行すると、以下のようにNew Relicに変更が記録されます。
おわりに
いかがでしょうか。Change Trackingが便利であることを伝えきるには情報が不足しているかもしれませんが、簡単に導入できることは伝わったと思いますので、試していただけたら幸いです。
最後に、個人的な決意表明ですが、所属チームにSREやDevOpsの文化・考え方を浸透させるために、New Relicを活用してきたいと思います。
*1:複雑な長いJSONをcurlコマンドでPOSTするときはヒアドキュメントを使うと便利です。 bashスクリプトでJSONを組み立ててcurlでPOSTする #Bash - Qiita
*2:https://support.atlassian.com/ja/bitbucket-cloud/docs/set-up-and-monitor-deployments/