クロスマート テックアドベントカレンダーの12/7の記事です🎄
はじめに
NewRelicでアプリケーション監視をしていると、自動的に多くのTransactionが記録されます。しかし、すべてのTransactionを同じように監視していても、本当に重要なAPIの挙動は見えてきません。
そこで今回は、NewRelicのKey TransactionsとWorkloadsを活用して、ビジネスクリティカルなエンドポイントを効率的に監視する仕組みをTerraformで構築してみました。
なぜKey TransactionsとWorkloadsが必要なのか
解決したかった課題
今回NewRelicを導入したアプリケーションには複数のTransactionがありますが、特に以下のような課題がありました。
-
重要なAPIの性能劣化を早期に検知したい
- 例えば「一覧取得API」が徐々に遅くなっているといった傾向を把握したい
-
週次・月次での性能比較をしたい
- 先週と比べてレスポンスタイムが悪化していないか確認したい
NewRelicさんに相談
上記の課題を解決すべく、NewRelicの担当者に相談したところ、Key TransactionsとWorkloadsを活用することでこれらの課題を解決できるという提案を受けました。
- Key Transactionsは個別のApdex1閾値設定が可能で、エンドポイントごとに異なるパフォーマンス基準を設定できる
- Workloadsで複数のKey Transactionsをグルーピングすることで、アプリケーション全体の健全性を一目で把握できる
Key Transactionsとは?
NewRelicはTransactionという単位で監視を行います。NewRelicをインストールすれば自動的にすべてのTransactionが記録されますが、それだけでは本当に重要なAPIの挙動を把握することは困難です。
そこで、Key Transactionsを使うことで、特定のTransactionに焦点を当てた監視が可能になります。
Key Transactionsを利用して確認できること
- 個別のApdex1閾値設定: エンドポイントごとに異なるパフォーマンス基準を設定
- 詳細なパフォーマンス分析: 特定トランザクションのレスポンスタイム・エラーレートを可視化
- SLO設定: 最低限守ってほしいDurationやSuccessの値を決定し、基準を下回った場合に視覚的に通知
Key Transactionsを設定することの効果
Key Transactionsを選定するプロセスで、チーム内でコミュニケーションが生まれ、改めて「このアプリケーションにとって重要な処理は何か」をメンバー間で明確にできるので、こういうプロセスは重要だと感じています。
ただし、Key Transactionsが何十個もあると、1つ1つの状態を確認するのは大変です。そこでWorkloadsの出番です。
Workloadsとは
Workloadsは、複数のKey TransactionsやAPMアプリケーション、SLOなどをまとめてグルーピングできる機能です。
活用方法
例えば「アプリケーションA」というWorkloadsを作成し、以下をまとめて表示できます。
- フロントエンドの監視
- バックエンドのKey Transactions群
- 設定したSLO
この中に1つでも基準を下回ったものがあれば、何か改善が必要な事象が発生していることを一目でわかるように視覚化できます。
Terraformで設定する
手動でこれらの設定を行うのは大変なので、Terraformで自動化してみました。
設計方針
今回は以下の方針で実装しました。
- シンプルさ優先: 環境は1つ(Production)のみなので、モジュール化や環境分離は不要
- YAGNI原則: 必要最小限の構成で開始し、必要に応じて拡張
-
locals変数で管理: Transaction名を
localsに定義し、for_eachで展開
ディレクトリ構成
terraform/
└── aws/
└── myapp/
├── provider.tf # Provider設定
└── key_transaction.tf # Key Transactions定義
実装例
provider.tf
まずはNewRelic Providerの設定です。
terraform {
required_version = ">= 1.13.3"
required_providers {
newrelic = {
source = "newrelic/newrelic"
version = "~> 3.75"
}
}
backend "s3" {
bucket = "newrelic-terraform-state"
key = "aws/myapp/terraform.tfstate"
region = "ap-northeast-1"
}
}
provider "newrelic" {
account_id = 12345678
api_key = var.newrelic_api_key # 環境変数で設定
region = "US"
}
variable "newrelic_api_key" {
description = "NewRelic User API Key"
type = string
sensitive = true
}
key_transactions.tf
Key Transactionsの定義です。
# ===========================================
# Key Transaction定義
# ===========================================
locals {
# NewRelicアカウント情報
newrelic_account_id = 12345678
application_name = "myapp"
# ===========================================
# Key Transaction定義(カテゴリ別)
# Purpose: カテゴリごとに共通設定とトランザクション名を定義
# ===========================================
transaction_definitions = {
api_read = {
prefix = "myapp"
apdex_target = 0.5
transactions = [
"app.routers.users.list:get_users",
"app.routers.users.detail:get_user",
"app.routers.products.list:get_products",
"app.routers.orders.list:get_orders",
]
}
api_write = {
prefix = "myapp"
apdex_target = 0.8
transactions = [
"app.routers.users.create:create_user",
"app.routers.orders.create:create_order",
]
}
batch = {
prefix = "myapp"
apdex_target = 5.0
transactions = [
"app.batch.daily_report:generate_report",
"app.batch.data_sync:sync_external_data",
]
}
# ... 他のカテゴリ
}
# トランザクション定義を展開
key_transactions = merge([
for category, config in local.transaction_definitions : {
for tx_name in config.transactions :
"${config.prefix}_${replace(replace(tx_name, "app.routers.", ""), ":", "_")}" => {
name = tx_name
apdex_target = config.apdex_target
category = category
prefix = config.prefix
}
}
]...)
}
# ===========================================
# Data Source: APMアプリケーション取得
# ===========================================
data "newrelic_entity" "app" {
name = local.application_name
type = "APPLICATION"
domain = "APM"
}
# ===========================================
# Resource: Key Transaction作成
# ===========================================
resource "newrelic_key_transaction" "main" {
for_each = local.key_transactions
name = "${each.value.prefix}_${each.value.name}"
metric_name = "WebTransaction/Function/${each.value.name}"
apdex_index = each.value.apdex_target
browser_apdex_target = each.value.apdex_target
application_guid = data.newrelic_entity.app.guid
}
Workloadsの設定
Workloadsも同様にTerraformで管理できます。
resource "newrelic_workload" "myapp" {
name = "myapp"
account_id = local.newrelic_account_id
# 動的クエリでmyapp関連のすべてのエンティティを自動的に含める
# (staging)がついているものは除外
entity_search_query {
query = "(name LIKE 'myapp' OR name LIKE 'myapp_app.routers.%') AND NOT name LIKE '%(staging)%'"
}
}
これにより、APMアプリケーション本体やフロント監視のBrowser、そしてSLO監視のService Levelsとあわせて複数のKey Transactionsがまとめて表示されようになりました!この六角形が赤くなったら異常だとすぐ気づけますね!
まとめ
NewRelicのKey TransactionsとWorkloadsを導入したことで、当初の課題を解決できました。
- 重要なAPIの性能劣化を早期に検知: 個別のApdex設定により、エンドポイントごとの性能基準で監視できるようになった
- 週次・月次での性能比較が容易に: Key Transactionsの履歴から、先週・先月との比較が一目で確認できるようになった
- Terraformによる管理: IaC化により、他のアプリケーションへの横展開や変更管理が容易になった
本当に重要なエンドポイントに焦点を当てた監視ができるようになり、アプリケーションの健全性を保つための第一歩を踏み出せたと感じています。今後もNewRelicの機能を積極的に活用し、より良い監視体制を構築していきたいと思います。
参考リンク
-
Apdexはアプリケーションのユーザー満足度を0〜1のスコアで表す指標です。1に近いほど、ユーザーが快適に使えていることを意味します。
https://docs.newrelic.com/jp/docs/apm/new-relic-apm/apdex/apdex-measure-user-satisfaction/ ↩ ↩2


