NRQLはNew Relicに集めたあらゆるTelemetry Dataを統一的にクエリできる機能です。NRQLを最大限に活用するために「Secrets of a NRQL Wizard」の抄訳にてその機能の一端を紹介したいと思います。

 

実は私は本物の魔法使いではありません。しかし、達人として、まだあなたが可能だと思ったことのないものをお見せすることができます。変装や不可視化の機能から、時間、空間、数学の複雑な操作まで、New Relic Query Language (NRQL)の新たな可能性の世界をご紹介します。

New Relicの主要なイノベーションの一つであるNRQL(”nerkel “と発音する)は、New Relicを使ってアプリケーションから収集したデータについて、New Relicデータベース(NRDB)に問い合わせを行うためのクエリ言語です。クエリ結果をNew Relic Insightsチャートに変換することで、データの内容を素早く簡単に解釈して行動に移すことができます。

NRDBチームの主任ソフトウェアエンジニアとして、私はNRQLがいかに強力なものであるかを学んできました。この7つのヒントと、データをクエリするための高度なテクニックで、NRQLクエリをレベルアップさせることができます。しかし、注意してください。この情報は New Relic をご利用のお客様には有用ですが、この投稿は NRQL の構文、コンポーネント、関数についての一般的な理解を前提としています。

#1:データを偽装する

「データを偽装する」というのは、実際のところは単純化するという意味です。

例えば、大容量のファイルの合計サイズをテラバイト単位で知りたいとします。次のようなクエリを書きます。

SELECT sum(fileSize) / 1e12

ファイルが例えば188TBの場合、チャートではファイルの合計サイズが次のように表示されます。

実際のところ、あまり役に立ちません。いったい、ゼロは何個あるんでしょう???

しかし、AS文を追加すると、測定値に名前を付けることができます。同じファイルでクエリを実行すると、以下のようになります。

SELECT sum(fileSize) / 1e12 AS 'TB'

するとチャートは次のように表示されるはずです。

188
TB

また、rate()関数を使用して、結果を特定の期間に合わせてスケーリングすることもできます。例えば、ストレージシステムに1日あたりに追加されたファイルのサイズをTB単位でクエリします。

SELECT rate(sum(fileSize), 1 day)

このように表示されるはずです。

27.02
TB/day

#2: データを無視する

SELECT句でサブセットの異なるデータを対象にしたい場合があるかもしれません。次のクエリは、filter機能を使用して、account 1のユーザーがクエリしたデータ量と、ユーザー全員がクエリした平均データ量を比較しています。

SELECT average(dataVolume), filter(average(dataVolume), WHERE account = 1)

結果のチャートを見ればわかるように、account 1のユーザーは本当に気に入っていて、平均的なユーザーの2~3倍のデータを照会している傾向があります。

percentage関数もまた、WHERE句を引数の一つとして取ります。 実際には、filterの例のように 2 つの結果の比率を表しています。

SELECT percentage(sum(fileSize), WHERE account = 1)

クエリの結果、収集したデータの2%近くがaccount 1からのものであることがわかりました。

#3: データを変換する

NRDBはレコードの変更ができないデータベースであり、UPDATE文はありませんが、NRQLのパワーユーザーは、最初は正しい形になっていなかったデータを変換することができます。

例えば、少し無意味ですが、以下のようなクエリを実行できます。

SELECT average(wallClockTime) FROM Query WHERE account < 1000

なんと0を返してしまいました。なぜでしょう?アカウントIDは文字列であり、数字ではないからです。しかし、これらの文字列を数値関数で数値に変換することができ、期待通りの結果を返します。

SELECT average(wallClockTime) FROM Query WHERE numeric(account) < 1000

プロレベルのアドバイスをもう一つ。ブール値を送ることができます。そして、true/falseを文字列として書いてしまうことがよくあります。

SELECT count(*) FROM Transaction WHERE chunked = 'true'

しかし、boolean関数を使用すると、これらの値をtrueまたはfalseの値に変換して IS TRUE でマッチさせることができます。

SELECT count(*) FROM Transaction WHERE boolean(chunked) IS TRUE

#4: データを切り出す

データを切り出す(facet)と、イベントをグループに分類し、それぞれが結果を生成します。ファセット化はNRQLの最もポピュラーな機能の1つですが、ファセット化でできることをすべて知っている顧客はほとんどいません。実際、これから説明する機能を使用しているファセットクエリは全体の1%未満です。

属性をファセットに指定すると、通常、クエリの結果が最も大きい値に基づいてファセットが選択されます。つまり、以下のクエリはすべてのアカウントに対してファセットを行います。

SELECT count(*) FROM FileCreated FACET account

しかし、いくつかのアカウントだけを見たい場合は、ファセットに明示的なIN句を指定することで興味のあるファセットを指定することができます。顧客はWHERE句を使ってこれを行うことが多いですが、実際にはこの方法の方が早いです。

SELECT count(*) FROM FileCreated FACET account IN (1, 313870)

NRQLには、時間に基づいてfacetを作成するための機能も多数あります。例えば、このクエリは、曜日ごとに結果を分割しています。

SELECT count(*) FROM Query SINCE 1 month ago FACET weekdayOf(timestamp)

一つ自慢させてください。みなさんのご期待通り、「われわれはかしこいので」結果の大きい順ではなく、曜日の順番でソートされています。

このようなfacetに利用できる、周期性をもつ関数としては次のものがあります。

  • hourOf
  • dateOf
  • weekdayOf
  • dayOfMonthOf
  • weekOf
  • monthOf
  • quarterOf
  • yearOf

facet化は、属性の個々の値に対して行う必要はありません。また、BUCKETSした値をファセットして、より強力なヒストグラムのようなものを得ることもできます。例えば、以下のとおりです。

SELECT sum(fileSize) FROM FileCreated FACET BUCKETS(durationMinutes/60)

そして、究極の柔軟性を実現するためにFACET CASESがあります。ここでは、NRQL WHERE句を使用して各facetの条件を正確に指定することができます。順番が重要であることに注意してください。定義しているWHERE句の条件を上から順に評価して、最初に一致した条件にカウントされます。

例えば、以下のクエリでは、処理速度とクエリ期間を調べています。

SELECT average(dataVolume/wallClockTime)
FROM Query
FACET CASES(
  WHERE durationHours <= 1 AS '1 hour',
  WHERE durationHours <= 24 AS '1 day',
  WHERE durationHours <= 168 AS '1 week'
)

#5: NRQLで予想外の(そして不自然な)組み合わせを使う

次の例では、NRQL の機能を予想外の方法で (もしかしたら不自然な方法で) 組み立てる方法を紹介します。

フィルタとイベントタイプ

よくある状況を考えましょう: 各ウィジェットが異なるタイプのイベントをクエリするダッシュボードを構築し、何かが起こったときに目を細めて、あるウィジェットの変化が別のウィジェットの変化と一致するかどうかを判断します。それらをすべて1つのチャートにまとめることができたらどうでしょうか? filtereventType関数を巧みに組み合わせることで、まさにそれが可能になります。

次のクエリは、ガベージコレクション時間がアプリの全体的なパフォーマンスに影響を与えているという仮説を探るのに役立ちます。

SELECT FILTER(sum(gcTime), where eventType() = 'NodeStatus'), FILTER(average(meps), where eventType() = 'Query') FROM Query, NodeStatus

eventType() 関数を使用すると、各データ系列を、問い合わせている2つのタイプのうちの1つに制限することができます。これにより、同じチャート上に両方をプロットして、仮説が偽であると判断することができます。それらは強く相関していません。

これは、両方のイベントで属性名が同じであっても動作します。eventType() 関数を使用すると、単一のタイプのイベントのみをマッチさせることができます。

SELECT filter(sum(fileSize),
WHERE eventType() ='FileCreated')
- filter(sum(fileSize),
WHERE eventType() ='FileDeleted')
 
FROM FileCreated, FileDeleted

このクエリは、新しいデータと削除されたデータが異なるイベントに記録されているにもかかわらず、1日に2.7TBのデータをシステムに追加していることを示してくれます。

時系列ヒストグラム

ヒストグラムも、データ全体の形を一度に見ることができるので、かなり人気があります。しかし、その形状が時間の経過とともに変化するとしたらどうでしょうか?それを可視化する方法はありますか?NRQL関数の巧妙な組み合わせを使えば可能ではあります。

SELECT histogram(duration)
FACET hourOf(timestamp)

時間ベースのfacet機能をヒートマップに適用することで、ヒストグラムが時間の経過とともにどのように変化していくのかを見ることができます。9時台になると、また午後になると、このアプリケーションの動作が遅くなりことがわかります。

#6: データの周りにバリアを張る

時には、データの周りに「フェンス」を張る必要があります。 そのための方法をいくつか見てみましょう。

正か負かではなく、値の大きさだけを気にしているとします。 絶対値関数を使用すると、0に沿って値をミラーリングして、正の結果だけを得ることができます。

SELECT abs(average(…))

さて、小数を整数に強制的に変換したいとしましょう。

  1. 黄で示されているように、floorで(正の数であれば)切り捨てられます。
  2. 赤で示されているように、ceilingを使って(正の数であれば)切り上げられます。
  3. 元の値を表す青のまわりにある緑で示されているように、roundを使って最も近い整数に丸めることができます。

曲線を最大値や最小値の範囲内に制限したい場合はどうしたらよいでしょうか。clamp_minclamp_maxというクランプ関数がその機能を提供します。この例では、最小値10と最大値12にクランプしています。

# 7:NRQLに高度な数学を適用する

最後に、NRQLクエリで高度な数学と統計を使ったテクニックをいくつか見てみましょう。まずはパーセンタイルから始めましょう。誰もがパーセンタイルが大好きです。しかし、現代のソフトウェアの時代には、99パーセンタイルでは十分ではないかもしれません。

そんなときのために、小数点以下のしきい値でパーセンタイルを計算できるようになりました。ここでは、99から99.9までのステップでパーセンタイルを計算してみました。

SELECT percentile(duration, 99, 99.1, 99.2, …, 99.9)

ご覧の通り、2ナインでの性能と3ナインでの性能には大きな差があります。

また、NRQLは計算に使用する数学関数も提供しています。例えば、平方根 sqrt(n)mod を使った剰余、2 種類の指数計算 pow(n,2)exp(n)log2(n) のような対数やその他の基底が自由に使えるようになりました。

対数関数は特に興味深いものです。例えば、SELECT percentile(duration, 5, 95)のクエリは、下の線が何をしているのか分からないほど異なる2つの測定値をもたらします。

これは本当にフラットなのでしょうか、それとも上のラインに吹き飛ばされた結果なのでしょうか?それらをログスケーリングしてみると、5 パーセンタイルが本当にフラットであることがわかります。

SELECT percentile(log10(duration), 5, 95)

あるいは、ロングテール分布のヒストグラムを見ようとしたことがあるなら、このようなチャートに遭遇したことがあるかもしれません。

そのテールにはたくさんのイベントがありますが、実際にはどこまで行くのでしょうか?繰り返しになりますが、ログスケーリングを使うと一度にすべてを見ることができます。

SELECT histogram(log10(duration))

これで末端が10^4、つまり10,000のあたりで終わっているのがわかります。

ここにもう一つのユースケースがあります。下図のようなクエリとチャートを見たことがある人は、「どのくらいの速さで増えているのか」と聞かれたことがあるでしょう。

SELECT average(diskUsed)

微積分ファンならば、関数の微分、つまり成長率を表すこの公式を知っているはずです。

NQRLでは、latestの関数とearliestの関数を使用して同じ計算を行うことができます。これらの関数は、その時間ウィンドウの属性の最初の値または最後の値を返します。

SELECT latest(diskUsed) -
earliest(diskUsed)

これで、ディスクの使用量がどのくらいの速さで増えているか、日によってどのように変化しているかがわかりました。

計算といえば、統計学の教科書「ピアソンの相関係数」で出てくるような公式があります。

相関係数は、2つの時系列間の相関関係を示す指標です。XとYは一緒に上がったり下がったりする傾向があるのでしょうか、それとも全く関係がないのでしょうか?ここで紹介したものはすべてNRQLで利用できるので、このようにまとめることができます。

読みやすくするために少しスタイルを変えましたが、これも有効なNRQLクエリです。

達人への道

この記事では、表示方法を変更する方法から、様々な軸に沿ってグループ化する方法、高度な統計関数を適用する方法まで、NRQLでのデータの問い合わせについてかなりの部分をカバーしています。しかし、この記事だけでは、適用可能な新しい組み合わせをすべて網羅しているわけではありません。

ぜひ実際にお使いになり、ドキュメントを参照し、NRQLの力を体感してください。

ソフトウェアエンジニア、インフラエンジニアなど自社開発や自社運用の現場で経験を積んだのち外資系ソフトウェアベンダーでのテクニカルサポートを経て現職。New Relicユーザーだった経験あり。コミュニティでの登壇活動も多く、Microsoft MVPを7年連続受賞中。Microsoft Certified Azure Solutions Architect Expert。得意分野はC#をはじめとするソフトウェア開発、Kubernetes関連技術およびパブリッククラウド。 View posts by .