AWS LambdaでNew Relicに任意のメトリックデータを送信する

:::note info
この記事は[New Relic 使ってみた情報をシェアしよう！ by New Relicのカレンダー | Advent Calendar 2022 - Qiita](https://qiita.com/advent-calendar/2022/newrelic)12日目の記事です。
:::

# 概要

New Relicには、[New Relic Flex](https://docs.newrelic.com/jp/docs/infrastructure/host-integrations/host-integrations-list/flex-integration-tool-build-your-own-integration/)と呼ばれる任意のメトリックデータを定期的に送信できる機能があります。この機能により、APMやInfrastructure等では送信できないメトリックデータをNew Relicに送信することができ、送信した任意のメトリックデータはダッシュボードによる監視やAlerts等と組み合わせる事ができます。

しかし、New Relic Flexを利用するためにはInfrastructure agentが動作するサーバーが必要であり、ECS Fargateのようなフルマネージドサービスでは使う事ができません。

この記事では、こうしたNew Relic Flexが使えない環境でも任意のメトリックデータを送信するための代替手段として、AWS Lambda (サーバーレス) とNew Relic REST APIを使った方法を紹介します。

# 関連記事の紹介

私が所属するチームでは、以前にMackerelからNew Relicに移行する際にNew Relic Flexを使った内容について別の記事にまとめています。当時はワークロードにEC2サーバーを採用していたため、New Relic Flexを利用できる状況でした。

[MackerelのカスタムメトリックをNew Relicに移行する時はNew Relic Flexという機能がおすすめ - 弥生開発者ブログ](https://tech-blog.yayoi-kk.co.jp/entry/2021/04/07/110000)

この記事は、上述した内容の続編にあたります。それぞれ独立して読める内容となっていますが、気になる方は両方の記事を読んでいただけれると嬉しいです:grinning:

# 提案する方法について

New Relic Flexに代わり、[Metric API](https://docs.newrelic.com/docs/data-apis/ingest-apis/metric-api/introduction-metric-api/)を利用します。また、Metric APIへのリクエストや送信メトリックデータの作成処理はAWSが提供するサーバーレスサービスの[AWS Lambda](https://aws.amazon.com/jp/lambda/)を利用します。

また、New Relicが提供する[Telemetry SDK](https://docs.newrelic.com/docs/data-apis/ingest-apis/telemetry-sdks-report-custom-telemetry-data/)では一部プログラミング言語でMetric APIのサポートがあり、APIリクエストを容易にできるようにサポートされています。この記事ではGo言語でTelemetry APIを利用して紹介します。

[newrelic/newrelic-telemetry-sdk-go: Go library for sending telemetry data to New Relic](https://github.com/newrelic/newrelic-telemetry-sdk-go)

## :computer: コード例

Telemetry SDKを使ってNew Relic Metric APIに対してメトリックデータを送信する関数の例です。このコード単体では動作しない点について注意してください。

```go

import (
	"context"
	"os"
	"time"

	"github.com/newrelic/newrelic-telemetry-sdk-go/telemetry"
)

func RecordMetric(name string, value float64) {
	h, _ := telemetry.NewHarvester(telemetry.ConfigAPIKey(os.Getenv("NEW_RELIC_INSERT_API_KEY")))

	h.RecordMetric(telemetry.Count{
		Name:      name,
		Value:     value,
		Timestamp: time.Now(),
	})

	h.HarvestNow(context.Background())
}
```

`telemetry.Count` の他にも `Gauge` と `Summary` があります。送信したいメトリックデータの特性からどの型で送信するべきか判断してください。それぞれNew Relic側で対応する関数の違い等があります。

[Query the Metric data type | New Relic Documentation](https://docs.newrelic.com/docs/data-apis/understand-data/metric-data/query-metric-data-type/)

# :wrench: 利用例

AWS EventBridgeでAWS Lambdaを定期的に実行します。

AWS Lambdaは、まずAppサーバーのAPIエンドポイントにリクエストを送信し、New Relicにメトリックデータとして送信したいデータをレスポンスとして受け取ります。

その後、New Relic Metric APIで送信できるようにデータを整形し、New Relic Metric APIにリクエストを送信します。New Relic Metric APIは受け取ったデータをNRQLからクエリできる形式でデータを保存します。

```mermaid
sequenceDiagram
    participant ev as AWS EventBridge
    participant lambda as AWS Lambda
    participant app as App Server
    participant nr as New Relic Metric API
    ev->>lambda: スケジュール実行
    lambda->>app: APIリクエスト
    app->>lambda: レスポンス
    lambda->>lambda: 送信用メトリクスデータ作成処理
    lambda->>nr: メトリクスデータ送信
```

App ServerではNew Relicに送信したいデータをAPIエンドポイントとして公開して、AWS Lambda関数がデータを取得できるようにしています。これは **/hearthエンドポントパターン** と呼ばれています。

## :+1: 補足： /healthエンドポイントパターンについて

/hearthエンドポイントパターンについては、株式会社オライリー・ジャパンが出版する「入門 監視」という書籍で「7.3　healthエンドポイントパターン」という節の中で紹介されています。

[O'Reilly Japan - 入門 監視](https://www.oreilly.co.jp/books/9784873118642/)

App Serverは/healthエンドポイントパターンに従い、New Relicにメトリックデータとして送信したいデータをエンドポイントとして公開しています。

私が所属するチームでは、delayed jobやsidekiqといったバックグラウンドジョブのキュー毎のジョブ数を取得できるようにしています。AWS Lambda関数から取得できるようにエンドポイントを公開する事で、New Relicにジョブ数の監視ができるようになります。

# まとめ

AWS LambdaでNew Relicに任意のメトリックデータを送信する方法と、私のチームでの利用例を紹介しました。

この方法の強みはサーバーレスな環境でメトリックデータをNew Relicで送信できる事であり、New Relic Flexが使う事が難しい環境で代替手段として採用できます。

技術的には新しいものは何も無かった内容でしたが、サーバーレスで任意のメトリックデータを送信したいんだよな〜と考えていた方の1つのアイデアとして知っていただけたら嬉しく思います。

# おまけ

書いた後に知ったのですが、New Relic Flexをサーバーレスな環境で動かす事もできるんですね… :sweat_smile:

皆様の事情や状況に合わせて適切な方法を採用していただけたらと思います。

- [New Relic Flexによる独自データソースのデータ統合（サーバーレス編） | New Relic](https://newrelic.com/jp/blog/how-to-relic/flex-integration-serverless)

- [New Relic Flex を SAMで管理してLambdaで動かす](https://zenn.dev/tatsuo48/articles/9f724f6e3cdb84)