こんにちは。株式会社フィックスポイントのよしだです。
初回のこの記事では、Fixpoint 技術情報ブログの内容についてご紹介します!
続きを読むこの記事は New Relic Advent Calendar 2025 の 15 日目の記事です。
こんにちは。株式会社フィックスポイントの KI です。
先日、私が所属しているプロダクトデベロップメント部で開発しているKompira cloudのAPI監視をDatadogからNew Relicに移行しました。
そこで、以下についてご紹介します。
この記事の前半では実際の移行の背景と、移行を通じて感じたDatadogとNew RelicのAPI監視機能の特徴と比較について紹介します。
後半では、New Relic でのAPI監視(Synthetic API tests)をTerraformで設定する場合のおすすめの書き方を紹介します。
監視SaaSでAPI監視をこれから設定する方や、New Relicでより自由度の高いAPI監視を設定していきたいと考えている方の参考になれば幸いです。
DatadogではSynthetic test機能でAPIテストを書いていました。
DatadogのSynthetic testにはSingle API testとMultistep API testsの二種類があります。
Kompira cloudでは両方の利用をしており、以下のようなテストをしていました。
Single API test は GET エンドポイントの監視に向いています。
/api/<省略> に GET リクエストを実行Multistep API tests は PUTエンドポイントなどの、現在のリソースを変更するようなエンドポイントの監視に向いています。
/api/<省略>/items に GET リクエストを実行/api/<省略>/items のレスポンスタイムが 30 秒以内であることを確認/api/<省略>/items のレスポンスボディをパースして特定の要素を持つ配列があることを確認/api/<省略>/items のレスポンスボディをパースして取得した配列のはじめの要素から ID を取得
$.items[0].id のような JSON パスで指定して取得が可能/api/<省略>/<id> に決められた内容の PUT リクエストを実行/api/<省略>/<id> のレスポンスタイムが 30 秒以内であることを確認/api/<省略>/<id> のレスポンスのステータスコードが 200 であることを確認New Relicへの移行理由ですが、DatadogでのAPI監視に課題があったわけではありません。
前提として、総合的な判断の結果として既にここ数年のAPI監視以外のKompira cloudの監視はNew Relicで実施していました。
よってAPI監視をNew Relicに移行して利用SaaSを一本化すると、利用料金や認知コストの削減に繋がるため、New Relicへ移行することにしました。
API Testingという機能名で提供されています。
以下のテストに対応しています。
Datadogの料金体系は「どの機能を」「どれくらいの量」利用したかで決定します。
そのため、API 監視機能についても実行回数で料金が決まっていました。
Synthetic API tests ( UI では Scripted API monitor とも)という機能名で提供されています。
Scripted API monitorの名の通り、Node.jsスクリプトを記述することでAPI監視を実現するものです。
以下でサポートされている Node.js ライブラリが利用可能です。
WebSocket に対応するためのwsライブラリや、gRPC関係のprotocol-buffers, Pingのnet-pingなども対応しています。
New Relic自体の料金体系は「転送データ量」「課金ユーザー数」で決定します。
そのため、すでにNewRelicの利用があれば API 監視を追加しても利用料金は変わりません。(※1)
※1 Proプランの場合1,000,000 (100 万) チェックまでがプラン内に含まれ、超過分は1回ごとに $0.005かかります。100 万チェックは、 5 分ごとのチェックの外形監視 115 個分に相当します。
ただNew Relicのユーザー区分として「課金ユーザー」と「Basicユーザー」があり、「課金ユーザー」はそこそこの値段がかかります。
そして「課金ユーザー」のみがこの API監視機能のWeb画面での編集権限を持つことに注意が必要です。
以下のような印象を持ちました。
逆の移行は仕様上も無理なケースもありますし、New Relicの自由度の高さに助けられました。
GUIに関しては圧倒的にDatadogのほうが体験が良いです。
以下のような画面で「どのURLにアクセスするか」「どのような確認をするか」を設定します。

開発者や開発スキルがある人が時間をかけてじっくり設定するのではなく「何も監視がないところに、今すぐ監視を入れたい」みたいな場合はDatadogのほうがマッチしているだろうと感じました。
New Relicの画面は実行頻度や実行ロケーションの設定以外はスクリプト入力画面があるのみです。

他のIaCの方法もあるのかも知れませんが、すでに開発チーム内ではTerraformを利用しているため、TerraformでのIaCをしました。
Kompira cloudの場合は「GET のテストならこういったことを確認する」「PUTの場合は○○を確認する」といったようにHTTP リクエストメソッドごとに確認していることは同様のものが多かったので、テンプレートモジュールを作成することで事足りました。
もしエンドポイントごとに確認方法が異なる場合は多数のスクリプトを用意する必要があるので、その部分が負担になる可能性はあるかも知れません。
このセクションでは、New RelicでのAPI 監視のTerraform定義について具体的なソースコードを挙げ共有いたします。 これからTerraformでの設定をしたい方の役に立てば幸いです。
Synthetic API testsはNewRelic上に設定したNode.jsスクリプトを定期実行するものです。
利用可能な最新のNode.js のバーションは22で、利用可能なサードパーティーライブラリに制限があります。
また、スクリプト内でパスワードなどのセンシティブなデータを読み込みたい場合はsecure credentials機能があります。
以下のように$secure.<name>という記法で変数にクレデンシャル値を格納し、利用が可能です。
const applicationId = $secure.APP_ID;
newrelic/newrelic provider のnewrelic_synthetics_script_monitor resource は以下のようなリソースです。
resource "newrelic_synthetics_script_monitor" "monitor" { status = "ENABLED" name = "script_monitor" type = "SCRIPT_API" locations_public = ["AP_SOUTH_1", "AP_EAST_1"] period = "EVERY_6_HOURS" script = "console.log('it works!')" script_language = "JAVASCRIPT" runtime_type = "NODE_API" runtime_type_version = "16.10" tag { key = "some_key" values = ["some_value"] } }
上記で分かる通り、script 属性にスクリプトを含める必要があります。
このままだとスクリプトが書きにくいので、別ファイルに切り出し等をし、以下のようなテンプレートを作成しました。
terraform { required_providers { newrelic = { source = "newrelic/newrelic" } } } resource "newrelic_synthetics_script_monitor" "main" { # DISABLED にした際 diff が少なくなるよう定義を書いておくのがオススメです status = "ENABLED" name = var.monitor_name type = "SCRIPT_API" locations_public = var.monitor_locations period = var.monitor_period script = var.script script_language = "JAVASCRIPT" runtime_type = "NODE_API" runtime_type_version = var.node_version dynamic "tag" { for_each = var.tags[*] content { key = tag.value.key values = tag.value.values } } } variable "monitor_name" { type = string } variable "monitor_locations" { type = list(string) } variable "monitor_period" { type = string validation { condition = contains(["EVERY_MINUTE", "EVERY_5_MINUTES", "EVERY_10_MINUTES", "EVERY_15_MINUTES", "EVERY_30_MINUTES", "EVERY_HOUR", "EVERY_6_HOURS", "EVERY_12_HOURS", "EVERY_DAY"], var.monitor_period) error_message = "The monitor period must be one of the following: EVERY_MINUTE, EVERY_5_MINUTES, EVERY_10_MINUTES, EVERY_15_MINUTES, EVERY_30_MINUTES, EVERY_HOUR, EVERY_6_HOURS, EVERY_12_HOURS, EVERY_DAY." } } variable "script" { type = string } variable "node_version" { type = string # 2025-11-05 に 22.20.0 が利用可能になりましたたが # terraform provider が対応済みかは未確認のため # 確認済みの 16.10 をデフォルトにしています default = "16.10" } variable "tags" { type = list(object({ key = string values = list(string) })) default = null }
上記テンプレートモジュールの利用側は以下のように書きます。
この定義は、以下のようなテストを作成しています。
https://example.com/api/foo/bar にアクセスして、レスポンスステータスが 200 であることを確認
script属性で指定しているスクリプトによってmodule "bar_monitor" { source = "../../modules/synthetics_script_monitor" monitor_name = "GET /api/foo/bar" monitor_locations = ["AP_NORTHEAST_1"] monitor_period = "EVERY_5_MINUTES" script = templatefile("${path.module}/scripts/get_test_template.js", { # js 内の `${env}` 内を置換 # New Relic の credential は大文字なので合わせる env = "DEV" # js 内の `${path}` 内を置換 path = "api/foo/bar" # NOTE: `${clientSecret}` という文字列を残すために `$${...}` としている clientSecret = "$${clientSecret}" }) tags = [ { key = "some_key" values = ["some_value"] } ] }
var assert = require('assert'); // ENV が DEV の場合、New Relic 上に保存している TOKEN_DEV credential から値が読み取られて変数に格納される const clientSecret = $secure.TOKEN_${env}; const requestURL = "https://example.com/${path}" const headers = { accept: "application/json", "Authorization": `Bearer ${clientSecret}`, } const options = { headers: headers, timeout: { request: 30 * 1000, }, } const res = await $http.get( requestURL, options, (err) => { if (err) { throw new Error("HTTP request failed: " + err.message); } } ); assert.equal(res.statusCode, 200);
Terraformのtemplatefile関数は ${...}という文字列がある箇所について、指定した文字列に変換します。
JavaScriptのテンプレートリテラルも${...}のため、templatefile関数の引数に指定したファイル内の${...}箇所は全て何に置換するか指定が必要です。
※指定しないとエラーになります。
そのため上記のJavaScript${clientSecret}を${clientSecret}として残すために"$${clientSecret}"とする必要があります。
上記のモジュールを利用すると、以下のようなJavaScriptを5分ごとに実行するよう設定できます。
var assert = require('assert'); // ENV が DEV の場合、New Relic 上に保存している TOKEN_DEV credential から値が読み取られて変数に格納される const clientSecret = $secure.TOKEN_DEV; const requestURL = "https://example.com/api/foo/bar" const headers = { accept: "application/json", "Authorization": `Bearer ${clientSecret}`, } const options = { headers: headers, timeout: { request: 30 * 1000, }, } const res = await $http.get( requestURL, options, (err) => { if (err) { throw new Error("HTTP request failed: " + err.message); } } ); assert.equal(res.statusCode, 200);
上記の例では Bearer ${clientSecret} というコードのためにTerraformでclientSecret = "$${clientSecret}"のように書く必要が出てきてしまっています。
そのため、以下のように変更するのも手です。
const headers = { accept: "application/json", "Authorization": "Bearer " + clientSecret, }
このようなことに気を遣いながらJavaScriptを書く必要性がありますが、自由度の高い条件で監視を設定できるのが魅力です。
DatadogからNew RelicへのAPI監視の移行を通じて、両サービスの設計思想の違いを改めて実感しました。
Datadogは「誰でも迷わず適切な設定ができる」ことを重視した設計で、初めて監視を設定する方にも優しい作りになっています。
一方、New Relicは「どんな要件にも対応できる自由度」を提供する設計で、エンジニアがコードで細かく制御できることを強みとしていると感じました。
Kompira cloudの場合は、すでにNew Relicを活用しており、Terraformでのコード管理も定着していたため、New Relicへの移行がスムーズに進みました。
この記事が、API監視の選定やNew Relicでの監視設定に取り組む方の参考になれば幸いです。
この記事は New Relic Advent Calendar 2024 の 19 日目の記事です。
こんにちは。株式会社フィックスポイントの KI です。
この記事では、私が所属しているプロダクトデベロップメント部での New Relic の利用、特に分散トレースについて紹介します。
前半では分散トレースを試験環境に実際に導入し、その結果として監視体験がどのように変化したかを紹介します。
後半では、 Go 言語でのメッセージキューを経由するようなトレースの実装においての工夫や、 OpenTelemetry 導入時のおすすめの設定を紹介します。
2024 年 11 月より、弊社製品 Kompira AlertHub の一部に分散トレースを導入しました。
Kompira AlertHub はマイクロサービスアーキテクチャを採用しており、複数のサービスによって構成されています。
Kompira AlertHub は非常に簡略化すると、以下のようなサービスです。

サービスは上記の「アーキテクチャ図 A」のように実装されています。
※実際にはもう少し複雑ですが、簡略化しています
この図で障害ポイントを考えたとき、下記のように障害を起こす可能性のあるポイントが複数あります。
現在、外形監視によって「Pod A→ Message Queue → Pod B の処理が正常に終了しているか」といった監視をしています。
ですが、障害状態であることが判明した後にも、具体的にどの箇所が要因となって障害が発生しているのかの問題の切り分けが必要です。
「熟練のメンバーなら障害対応が可能でも、新規メンバーでは障害対応が難しい」などの課題があります。
前述の運用課題について、オブザーバビリティを実現することが解決になると考えました。
オブザーバビリティとは、以下のような能力です。
簡単に言うと、私たちが考えるソフトウェアシステムの「オブザーバビリティ」とは、 システムがどのような状態になったとしても、それがどんなに斬新で奇妙なものであっても、(中略)事前にデバッグの必要性を定義したり予測したりすることなく、 システムの状態データのあらゆるディメンションやそれらの組み合わせについてアドホックに調査し、よりデバッグが可能であるようにする必要があります。 もし、 新しいコードをデプロイする必要がなく 、どんな斬新で奇妙な状態でも理解できるなら、オブザーバビリティがあると言えます。
オブザーバビリティ・エンジニアリング 1.2
New Relic は公式サイトにも記載がある通り、オブザーバビリティプラットフォームです。
New Relicオブザーバビリティプラットフォーム | New Relic
New Relic をオブザーバビリティバックエンドとして利用するためには、サービスのデータを New Relic にエクスポートする必要がありますが、エクスポートする手段を New Relic APM か OpenTelemetry から選択できます。
私たちのサービスでは、以下の理由により OpenTelemetry (以下 OTel ) を選択しました。
📖 New Relic と OTel に関しての公式記事は こちら
上述の通り Kompira AlertHub を構成するサービスについて OTel の導入を決め、まずは分散トレースの計装をサービスに追加することにしました。
トレースの計装はまだ本番環境への適用が完了しておらず、試験環境での変化ですが、下記のような変化が見られました。
トレースデータがあると、複数のサービスを経由する一連の処理の中で、特定のサービスでの処理にかかった時間を簡単に求めることができます。
たとえば、あるトレースについて、サービスごとの処理時間は NRQL では以下のようなクエリで求めることができます。
SELECT (max(timestamp + duration.ms) - min(timestamp)) / 1000 as 'sec' FROM Span WHERE service.namespace = '{{ service_namespace }}' FACET trace.id, service.name LIMIT MAX
※タイムスタンプが 13 桁のエポックミリ秒で記録されていたため、 timestamp を 1000 で割って sec に変換しています
https://docs.newrelic.com/jp/docs/logs/ui-data/timestamp-support/
ヒストグラムで集計する場合は以下のようなクエリで求めることができます。
SELECT histogram(sec) FROM ( SELECT (max(timestamp + duration.ms) - min(timestamp)) / 1000 as 'sec' FROM Span WHERE service.namespace = '{{ service_namespace }}' FACET trace.id, service.name LIMIT MAX ) FACET service.name

今回、サービス内で以下のような箇所にのみトレースを計装しました。
これだけでも、以下のようなことがトレースデータを閲覧するだけで分かるようになりました。
🤔「この外部エンドポイントを叩くとどのサービスをどんな順番で処理がされてるんだろう…?」
→「トレースデータによって、どのサービスがどの順番で処理しているか分かる!」
→「Span をちゃんと計装したら、どの処理がどのファイルで実装されているかも分かるので、コードも追いやすい」
🤔「構成図ではこのサービス間は HTTP リクエストで連携しているけど、実際にどんなエンドポイントを叩いているんだろう…?」
→「http ハンドラにもトレースの計装を追加したことで、実際に叩いているエンドポイントが分かる!」
トレースの計装があることで
といった、新規メンバーがサービス理解をするのに非常に頼もしい変化がありました。
このセクションでは、実際にサービスコードに OTel の計装を追加するにあたり、工夫した点や、おすすめの実装を紹介します。
「アーキテクチャ図 A」のように、製品内でメッセージキューを利用しています。
メッセージキューを経由した場合でもトレースを維持するには、トレースコンテキストをメッセージに含める必要があります。
OTel において、トレースコンテキストの伝搬は Propagators API を利用して行いますが、現在この実装として TextMap Propagator が存在します。
The Propagators API currently defines one Propagator type:
- TextMapPropagator is a type that injects values into and extracts values from carriers as string key/value pairs. https://opentelemetry.io/docs/specs/otel/context/api-propagators/
つまり TextMap Propagator は何かというと、Map に対してトレースコンテキストを注入したり、抽出ができるものです。
TextMap Propagator を利用してキューのメッセージにトレースコンテキストを含めると、キューのメッセージでもトレースコンテキストの伝搬ができるようになります。
そこで製品に OTel トレースを導入するにあたり、以下のような Carrier を実装しました。
※ OpenTelemetry トレースを導入したサービスは Go で実装されているため、Go での実装です
メッセージキューとして Azure Service Bus Queue を利用しているため、関数名などに AZServicebus を含んでいますが、 // type of azsb.Message.ApplicationProperties というコメントの箇所をお使いのメッセージキューにあわせて変更いただければ他のメッセージキューでも利用いただけると思います。
package tracer import ( "strings" ) func getWithPrefix(prefix, key string, p map[string]any) string { value := p[prefix+key] str, ok := value.(string) if !ok { return "" } else { return str } } func keysWithPrefix(prefix string, p map[string]any) []string { var keys []string for k := range p { if strings.HasPrefix(k, prefix) { keys = append(keys, strings.TrimPrefix(k, prefix)) } } return keys } // NOTE: // AZServicebusMessageCarrier のメソッド経由で // map の値を操作すると強制的に prefix が付与されるので trace context propagation 以外の用途では利用しないこと type AZServicebusMessageCarrier struct { metadata map[string]any // type of azsb.Message.ApplicationProperties } func (c *AZServicebusMessageCarrier) Get(key string) string { return getWithPrefix("otel-", key, c.metadata) } func (c *AZServicebusMessageCarrier) Set(key string, value string) { c.metadata["otel-"+key] = value } func (c *AZServicebusMessageCarrier) Keys() []string { return keysWithPrefix("otel-", c.metadata) } // NOTE: // OpenTelemetry の Propagator(に含まれるCarrier) を Azure Service Bus のため独自定義する // NewAZServicebusMessageCarrier() の返り値を azsb.Message.ApplicationProperties にセットすることで // Azure Service Bus に trace context を埋め込む func NewAZServicebusMessageCarrier(p map[string]any) *AZServicebusMessageCarrier { return &AZServicebusMessageCarrier{metadata: p} }
この実装の工夫ポイントとして、この Carrier を利用した際、トレースコンテキストに otel- prefix を付与するようにしたことが挙げられます。
Azure Service Bus Queue の ApplicationProperties には、トレースコンテキスト以外のメタデータを格納したいケースがあるかもしれません。
万が一でも他のメタデータを格納した際に衝突しないよう、prefix を付与しました。
補足:
carrier の計装については以下の記事にとても助けられました。ありがとうございます!
https://ymtdzzz.dev/post/opentelemetry-async-tracing-with-custom-propagator/
https://zenn.dev/google_cloud_jp/articles/20230626-pubsub-trace
OTel Resource の Attribute は様々なものがありますが、Service Attribute の service.namespace を指定しておくと、New Relic での体験が良かったので紹介です。
New Relic の OTel のテレメトリを表示する画面で APM & Services 画面があります。
ここには様々な環境のサービスが全て並ぶかと思います。

この状態では複数の環境に OTel 計装をデプロイした際に、目的のサービスを探すのが大変です。
ですが、 Attribute で service.namespace を指定しておくと、画面上部の 「+」 から service.namespace でのフィルタができ、特定の namespace のサービスのみ表示することが出来ます。


画面上部の「 Save view」より、フィルタ状態に名前をつけて保存することも可能です。

このように活用できるので、service.namespace を指定しておくのをオススメします。
分散トレースの導入にあたっては New Relic 社のテクニカルサポートも利用しました。
APM 画面の仕様の問い合わせや、 細かい疑問の解消など、お世話になりました。
ありがとうございました!
New Relic Advent Calendar 2024 のナイストライ賞をいただきました!

こんにちは。株式会社フィックスポイントのきむらです。
先日、社内の有志メンバーで開発合宿をしてきました!
今まで合宿イベントをしたことはなかったのですが、社内メンバーの一人が発起人となって企画を立ち上げ、実現に至りました🥳
今回はその合宿の様子をお届けします✨
そもそもなぜ今回合宿をすることになったのでしょうか?
実は業務中にこんなツールがあったら便利だなというアイデアがあっても、なかなかまとまった時間をツールの開発にとれないといった思いがありました。
具体的に今回のターゲットになったのは、弊社製品の独自言語であるジョブフローを、エディタ上で手軽に整形するツールです。
そこで、2泊3日の合宿でさながら文化祭のように一気に作っちゃおう!となりました。
その結果、普段はリモートで対面する機会のない遠方のメンバーも楽しめる合宿企画ができあがりました🥳
今回の合宿は、静岡県伊豆半島の山の中に位置するコテージ1棟を貸し切って行いました!
自然豊かな場所で、天候にも恵まれ穏やかな日差しの中3日間を過ごしました✨


弊社では毎月オンラインで社内勉強会を開催しています。 このブログでも過去の勉強会の様子を紹介していますね。
今回の合宿では現地メンバーが発表テーマを持ち寄り、よりラフな雰囲気で勉強会を行いました!
他のメンバーが発表した内容に触発されて、突発的に新たな発表が生まれたりと、対面ならではの盛り上がりを見せました。
合宿といえばおいしいご飯! 夜は外のテラスでBBQをしました。
料理が得意な我がエンジニア部門の部長がコテージのキッチンでアボカドと卵を使ったソースを作ってくれ、とても美味しかったです🍽️

今回の合宿で開発したツールは、その後社内の定例会議でエンジニアの皆さんに紹介しました。
今までコードを整形するためには少しだけ操作が必要だったのですが、今回のツールによりエディタ上で保存するだけで自動で整形されます🎉
少しの手間ですが、その手間がゼロになる自動化は、やはりエンジニアのストレスを下げてくれますね。
今回初の試みだった合宿は、無事成功に終わりました!
弊社では、社内で実際に自動化したい業務を募集し、新人に解決してもらうというユニークな新人研修があります。
困っている社員にヒアリングをし、要件定義、設計から実装まで一通り経験できるうえ、 実際に社内に導入されて皆に使ってもらえる楽しい研修です。
ただ、どうしても新人研修用には難易度や開発期間が合っていないネタは後回しにされがち……
今回の合宿はそういった要望とも非常に相性のいいものとなりました。
ぜひ今後も第2回、第3回と継続して開催していきたいですね。
こんにちは。株式会社フィックスポイントのよしだです。
今回はエンジニアの技術に関わる発表というより、一般的な社会人スキルについての発表がありました!
社会人として職場で円滑な人間関係を構築するには、適切なコミュニケーションが必要不可欠ですよね。
最近社内でもホットな話題でしたので、いつもと毛色は違いますが取り上げさせていただきます✨
続きを読むこんにちは。株式会社フィックスポイントのよしだです。
今回は、2023年度の新入社員技術研修をご紹介します!
フィックスポイントでは、新入社員のエンジニアに対して毎年部署配属の前に2ヶ月ほど研修を行っています。
本記事では、研修の終盤に行う個人開発タスクに焦点を当てて取り上げたいと思います!
全体的な研修の内容や体制については、前年度の記事に詳しく記載しておりますので、気になる方は見てみてくださいね😊
続きを読むこんにちは。株式会社フィックスポイントのよしだです。
今回は、前回に引き続き新入社員が勉強したテスト内容と実際に行ったテストについてご紹介します。
前回の記事は下の通りですので、興味のある方は前編から見てみてくださいね!
それでは早速、テストのお勉強の続きから内容に入っていきましょう♪
続きを読む