a picture with three different rulers

本ブログでは、少し応用的な活用方法を紹介します。元となるアイデアは2つです。

  1. NRQL クエリは API 経由で実行することができる
  2. CustomEvent や MetricAPI を用いて、任意のデータをインジェストすることができる

スクリプト程度のコードを作成することで、API 経由で NRQL クエリを実行し、データの加工または評価を行い、その結果を利用することができます。CustomEvent として New Relic や他のツールにデータインジェストしたり、評価結果に応じて、次の操作コードを実行するという活用方法があります。NerdGraph API の mutation 機能で、issue をクローズしたり、変更や作成などの操作を行うことも可能です。

作成したスクリプトを定期的にジョブ実行するツールと組み合わせたり、メール受信/ Web アクセスなどをトリガーに実行するようにすることで、より細かな要望を実現できる可能性があります。

 

NerdGraph API を利用した NRQL の実行

NRQL は プラットフォーム UI のクエリビルダーや Dashboard の他、NerdGraph API でも使用することができます。NerdGraph API の場合、プラットフォーム UI でのクエリ実行よりもオプションが豊富で、クロスアカウントクエリ、非同期クエリなどを利用することもできます。実行は ブラウザでの NerdGraph API Explorer や コマンドラインでの cURL で実行することが可能です。

ドキュメントでは NerdGraphチュートリアル。NRQLを使ってデータを照会する に実行例が紹介されています。

NerdGraph API Explorer には、プラットフォーム UI より Apps > NerdGraph API explorer からアクセスします。

下記は、簡単な NRQL クエリの実行例です。
YOUR_ACCOUNT_ID には実際のアカウント ID を入力します。

{
  actor {
    account(id: YOUR_ACCOUNT_ID) {
      nrql(query: "SELECT count(*) FROM Metric SINCE 1 HOUR AGO") {
        results
      }
    }
  }
}

また、左上の Tools > ”Copy as CURL” にて、そのまま実行できる curl コマンドを取得することができます。

ターミナルからの実行で  NerdGraph API explorer と同じ結果を得ることができます。

$ curl https://api.newrelic.com/graphql \
  -H 'Content-Type: application/json' \
  -H 'API-Key: YOUR-API-KEY' \
  --data-binary '{"query":"{\n  actor {\n    account(id: YOUR-ACCOUNT-ID) {\n      nrql(query: \"SELECT count(*) FROM Metric SINCE 1 HOUR AGO\") {\n        results\n      }\n    }\n  }\n}", "variables":""}'

{"data":{"actor":{"account":{"nrql":{"results":[{"count":832}]}}}}}

API エンドポイントに NRQL クエリをポストするというシンプルなコマンドでなので、各言語で実装が可能です。
例えば、python スクリプトの作成例は 下記の github などに掲載があります。

license.py に API-Key を記載し、nerdgraph_nrql.py で アカウントID と NRQL クエリを記載し、実行すると同じ結果を得ることができます。

 

[PythonForDevOps-NerdGraph/nerdgraph_nrql]$ python nerdgraph_nrql.py
{'results': [{'count': 832}]}

また、API 経由の実行の場合、ユーザーごとに同時リクエストの数は 25 や 1 アカウントあたり 3000 クエリ/分など、いくつかの上限に関する制約は存在するので、実行数が多くなる場合は、ご注意ください。詳細は下記ドキュメントをご確認ください。

CustomEvent のインジェスト

Event API に json のデータをポストすることでカスタムイベントデータを New Relic に送信することができます。

実際の送信例を記載します。

ポストデータとして送信するイベントデータに 自分で決める eventType を記載します。
また、利用する API キーは、INGEST 用のキーを利用します (先の NerdGraph では USER キーでも可能でしたが、データのインサートには 、INGEST 型のキーが必要です)。

下記は curl コマンドでの送信例です。

 

$ ACCOUNT_ID="xxx"
$ INSERT_KEY="xxx"
$ curl -X POST https://insights-collector.newrelic.com/v1/accounts/$ACCOUNT_ID/events \
  -H "Content-Type: application/json" \
  -H "Api-Key: $INSERT_KEY" \
  -d @- <<EOS
{
  "eventType": "CustomEventTest",
  "value": 2000
}
EOS

{"success":true, "uuid":"dc4794f8-0001-****-****-************"}

送信されたデータは NRQL にて、指定した envetType をクエリすることで確認できます。

Metric API 経由のインジェスト

CustomEvent ではなく、Metric にカスタム値をインジェストすることも可能です。

実際の送信例を記載します。

CustomEvent のインジェストと同様に Api-Key は User 型ではなく、Intert key を使用する必要があります。
name の入力値が metricName に対応します。
また、timestamp は UNIX タイムで入力する必要があります。データ受付された場合はステータスコードとして 202 。requestId が表示されます。

下記は curl コマンドでの送信例です。

 

$ INSERT_KEY="xxx"
$ curl -X POST https://metric-api.newrelic.com/metric/v1 \
  -H "Content-Type: application/json" \
  -H "Api-Key: $INSERT_KEY" \
  -d @- <<EOS
[{
    "metrics":[{
        "name":"mycustomvalue",
        "type":"gauge",
        "value":1000,
        "timestamp": `date +%s`,
        "attributes":{
          "host.name":"`hostname`"
        }
    }]
}]
EOS

{"requestId":"8f3afffc-0001-****-****-************"}

送信されたデータは NRQL にて、指定した name を metricName の条件として指定します。
(画像での表示上の都合で Chart type として JSON を使用しています)

また、応答コードが 202 の場合でも、非同期の検証時にエラーとなり、インサートされない場合もあります。その場合は原因が NrIntegrationError イベントに記載されることがあります。

curl レスポンスの requesteId を WHERE 条件に指定すると特定しやすくなります。
(画像での表示上の都合で Chart type として JSON を使用しています)

5-alerts-using-jobscheduler

NerdGraph API で取得したデータをインジェスト ~アラート利用~

 

Nerdgraph API 経由で NRQL の結果を取得し、集計処理や判定の結果を CustomEvent や カスタムメトリックにインジェストする方法は、アラート設定などにも利用できます。アラートのオプションの制約に縛られることなく、情報を取得することができます。例えば  Window Duration の上限は 6時間ですが、NRQL で SINCE 24 hours AGO とすれば、24時間以内の出力で取得できます。アラート用 NRQL に対応していないサブクエリ結合や lookup テーブルなども利用が可能です。単一の NRQL では難しい場合は、複数の NRQL で取得し、必要な評価を書き慣れた言語で処理することができます。

NerdGraph API や他の ingest 用の API にポストアクセスできる言語であれば、作成が可能です。みなさんが慣れた言語が利用できます。

そうしてインジェストされた値に対して、アラートを設定すればより柔軟なアラート設定を実現することができます。
もちろん、追加の処理や実行環境が必要になりますが、デフォルトの動作だけで実現が難しい場合は、このような選択肢もあります。

 

Synthetic monitor を利用したアラート評価例

定期的に実行するツールや実行環境の問題に関しては、Synthetic monitoring で Scripted API を利用することも可能です。

また、Scripted API 利用であれば、取得値が閾値を超過していた場合などは、Synthetc モニターの結果を failed にするということも可能で、再インジェストも不要です。対象のモニター (SyntheticCheck の result) に対してアラートを設定するだけで済ませることができます。

下記は、著者が作成した実行例です。
(query (NRQL クエリ) と threshold (数値の閾値) を設定します。また NRQL で 'AS value' が必要です)

また、この NRQL は、アラート NRQL とは違う点もあるので、SINCE や LIMIT などを指定するようにしましょう。

 

var assert = require('assert');
const accountId = $secure.ACCOUNTID;
const userKey = $secure.USERKEY;

const query = "SELECT count(*) AS value FROM Log SINCE 24 hours AGO";
const threshold = xxx;

$http.post('https://api.newrelic.com/graphql',
    // Post data
    {
        headers: {
            'Content-Type': 'application/json',
            'API-Key': userKey
        },
        json: {
            query: '{ \
                 actor { \
                   account(id: ' + accountId + ') { \
                     nrql(query: "' + query + '") { \
                       results \
                     } \
                   } \
                 } \
               }'
        }
    },
    function(err, response, body) {
        assert.ok(!err, "Connection error!")
        assert.equal(response.statusCode, 200, 'Expected a 200 OK response');

        const results = body['data']['actor']['account']['nrql']['results']
        var value = 0;
        value = results[0]['value'];

        console.log("results:"); console.log(results);
        console.log("value: " + value);

        if (value > threshold) {
            assert.equal(value, threshold, "value > " + threshold);
        } else {
            assert.ok(threshold, "value <= " + threshold);
        }
    }
);
6-alerts-using-jobscheduler

最後に

NerdGraph API 経由で NRQL を実行する方法から、アラート機能への適用例を紹介しました。
デフォルトの アラート用 NRQL での取得が難しい場合や期間の制約上で難しい場合、より複雑な処理を行いたい場合など本方法を用いてコード内でデータ処理した方が簡易的な場合もありますね。
実行環境の準備やエラー処理、メンテナンス性などを考慮する必要はあるかもしれませんが、API の利用はより幅の広い活用方法を見出すことができると思いますので、お試しいただければと思います。