Auth0のログをAmazon EventBrige経由でNew Relicに保存してみる #Auth0JP

2020.03.16

Auth0にはログストリームという機能があり、Amazon EventBridgeと連携することが可能です。

S3にログを集めることは以下のブログで紹介されています。

Amazon EventBridgeとAuth0を連携!S3にイベントログを格納する #reinvent #Auth0JP #Auth0アドカレ

今回はこれに加え、New Relicにログを格納することを行なってみたいと思います。

ケース

こういったケースを考えました。

  • コンプライアンスのためにログは全て保存しておかないといけないため -> S3
  • アプリケーションのレスポンスの改善や、障害の原因追求のため -> New Relic Logs

生ログは全てS3に保存し、分析などに使用するログはNew Relic Logsに送信します。

New Relic Logsに送信するログは永久に保存しません(MAX30日間)。

上記の構成の 分析用ログ を New Relicに送信するところを目指してみます。

Auth0の設定

ダッシュボード -> Logs -> Streams の画面からAmazon EventBridgeの新規Streamを作成します。

Lambda関数の作成

New Relicに送信するためのLambda関数を作成します。

Log APIを使って送信してみます。

Log POSTの例

POST /log/v1 HTTP/1.1
Host: log-api.newrelic.com
Content-Type: application/json
X-License-Key: <YOUR_LICENSE_KEY>
Accept: */*
Content-Length: 319
{
  "timestamp": <TIMESTAMP_IN_UNIX_EPOCH>,
  "message": "User 'xyz' logged in",
  "service_name": "<YOUT_SERVICE_NAME>",
  "hostname": "<YOUR_HOST_NAME>"
}
  • X-License-Key: NewRelicのライセンスキー
  • service_name: サービス名 (Auth0)
  • hostname: ホスト名 (Auth0のドメイン名)

POSTに必要な上表を環境変数で定義しておきます。

ソースコードは以下のような感じに。

const AWS = require('aws-sdk');
const request = require('request')

AWS.config.update({ region: 'us-east-1' });

const encrypted = process.env['NewRelic_License_Key'];
let decrypted;

exports.handler = async (event, context, callback) => {
    console.log(event)
    if (!decrypted) {
        // Decrypt code should run once and variables stored outside of the
        // function handler so that these are decrypted once per container
        const kms = new AWS.KMS();
        try {
            const req = { CiphertextBlob: Buffer.from(encrypted, 'base64') };
            const data = await kms.decrypt(req).promise();
            decrypted = data.Plaintext.toString('ascii');
        } catch (err) {
            console.log('Decrypt error:', err);
            callback(err);
        }
    }

    const promise = new Promise(function(resolve, reject) {
        const date = new Date() ;
        const unixtime = date.getTime() ;
        const options = {
          url: 'https://log-api.newrelic.com/log/v1',
          headers: {
            'Content-Type': 'application/json',
            'X-License-Key': decrypted
          },
          body: JSON.stringify({
            "timestamp": unixtime,
            "message": event.detail,
            "service_name": process.env['Service'],
            "hostname": process.env['Hostname']
          })
        };

        request.post(options, function(error, response, body){
          if (error) {
            console.error("error")
            console.error(error)
            reject(Error(error))
          }
          console.log(`statusCode: ${response.statusCode}`);
          console.log(body);
          resolve(body);
        });
    })
    return promise

};

EventBridgeの設定

Amazon EventBridge -> イベント -> パートナーイベントソースの画面から先ほど作成したStreamのEvent Source Nameを関連づけます。

関連付けが終わったらルールを作成します。

名前には適当な値を入力します。

パターンを定義の箇所にはイベントパターンを定義します。 カスタムパターンを定義することにより、コンテンツのフィルタリングが可能です。 これを行うことにより、Lambdaでのコード量を減らすことが可能です。

参考: Reducing custom code by using advanced rules in Amazon EventBridge

今回はAuth0の成功したログインイベントだけNew Relicに送信してみます。

参考: Auth0 Log Event Type Codes

イベントパターンは以下のように入力します。

{
  "detail": {
    "data.type": [
      "s"
    ]
  }
}

イベントバスを選択 には、関連付けを行なったパートナーイベントソースを洗濯します。

ターゲットを選択には作成したLambda関数を指定します。

これで設定は完了です。

New Relicでログの確認

Auth0のアプリケーションでログイン・ログアウトを行なってみると、New Relicにログが送信されているはずです。 今回はフィルタリングを行なっているのでログアウトのログは送信されていません。

New Relic ONEのLogsでは上記のように見えています。

各行をクリックすることによりログの詳細が確認できます。

messageに入れたログの中身での検索も可能です。

最後に

Amazon EventBridgeを使ってAuth0のログをNew Relicに送信しました。

EventBridgeを使うことによってS3に保存したり、サードパーティ製のログツールで可視化したりと色々なことが可能となります。 やりたい分析に必要なログだけを送信したいといったときは、ルールのイベントパターンによる振り分けが使えます。便利です。

New Relic Logsはログを溜め込むというよりは、障害時などの原因究明などに役に立つので、こういった場合にはとても有用です。 New Relic InsightsでNRQLを使って検索し、グラフ化することも可能です。

Auth0を使っていてログの永続化、可視化に悩んでいる方がいれヴァ参考にしていただけると幸いであります。