📊

Aurora MySQLのslow queryをNew Relicでいい感じにプロットする方法

2023/07/23に公開

概要

  • NRQLってSQLライクで書きやすいんですが、ログ周りで取りたい文字列が取れなくてハマったりしませんか?
  • そんな時はcapture関数を使えば正規表現で目的の文字列がさくっと取得できます。
  • capture関数でAurora MySQLのslow logをクエリ毎に積み上げ棒グラフでプロットする記事です。

グラフ

スロークエリの転送方法

最初にCloudWatch Logsに出力されたAurora MySQLのスロークエリをNew Relicに転送します。
以下のようにAWSマネージドサービスを繋ぎます。

構成図

この記事はNRQLメインなので詳しい設定手順はなしにして、公式ドキュメントのリンクを記載します。昔はlambdaを用意する必要があったのですが、kinesis Firehoseだけで良くなったので構築が楽になりました。

Kinesis Data Firehoseによるログのストリーミング

転送されたスロークエリはどこに?

New Relic Logsに以下の形式で転送されます。

logGroup = '/aws/rds/cluster/{Aurora cluster name}/slowquery'

message

[message]

# Time: 2023-07-22T02:10:17.177218Z
# User@Host: hoge @  [xx.x.x.xx]  Id: 6235867
# Query_time: 12.771031  Lock_time: 0.000095 Rows_sent: 0  Rows_examined: 267739
use fuga;
SET timestamp=1689991817;
update 
		piyo 
	set 
		hoge = 1
	where 
		fuga = 1 and 
		piyo = 0 and 
		date < unix_timestamp() and 
		flg = 0;

ちゃんと転送されてきていますがこのままではちょっとグラフにし辛いです。何とかしてクエリのみにしたい。。

capture関数の出番

NRQLで用意されているcapture関数を使ってクエリのみを抽出します。
正規表現で文字列を抽出できるので、今回のような複数行のログから一部分を抜き出すのに非常に便利です。

今回やりたいことは、

  • 一週間でクエリ種別毎に出現した回数を積み上げ棒グラフでプロットする

なのでグルーピングする FACET 句でcapture関数を使えばよさそうです。

SELECT count(*) FROM Log WHERE `logGroup` = '/aws/rds/cluster/my-aurora-cluster/slowquery' FACET {ここでゴニョゴニョする} TIMESERIES SINCE 1 week ago

実際の書き方

messageの構造は以下のようになっています。

# Time: 2023-07-22T02:10:17.177218Z
# User@Host: hoge @  [xx.x.x.xx]  Id: 6235867
# Query_time: 12.771031  Lock_time: 0.000095 Rows_sent: 0  Rows_examined: 267739
use fuga;
SET timestamp=1689991817;
update 
		piyo 
	set 
		hoge = 1
	where 
		fuga = 1 and 
		piyo = 0 and 
		date < unix_timestamp() and 
		flg = 0;

書式は cature({ゴニョゴニョする対象}, {正規表現パターン}) なので、まずはこのようになります。

capture(message, {正規表現パターン})

正規表現パターンにちょっと癖があり、名前付きのキャプチャグループを指定する必要があります。

capture(message, r'{正規表現}(?P<{キャプチャグループ名}>{正規表現}){正規表現}')

[例]
capture(request_url, r'.*/accounts/(?P<account>\d+).*')

-> request_urlから、~/accounts/xxxxxxxx/~のxxxxxxxxを抽出する(xxxxxxxxは数字のみで構成)、抽出するキャプチャグループ名はaccount。

今回は SET timestamp=1689991817; 以降の文字列を取得したいので、

  • SET timestamp=xxxxxxxxx; までは全部無視
  • 以降の文字列を全て取得する

となるので、以下のようになります。

capture(message, r'[\s\S]*SET timestamp=\d+;(?P<sql>.*)')

-> キャプチャグループ名はsql以外でもよい

完成したNRQL

SELECT count(*) FROM Log WHERE `logGroup` = '/aws/rds/cluster/my-aurora-cluster/slowquery' FACET capture(message, r'[\s\S]*SET timestamp=\d+;(?P<sql>.*)') TIMESERIES SINCE 1 week ago

最後に

NRQLは自分の望むようにデータを出力できる、とても強力なツールです。
キャプチャグループのところでちょっと苦労したので参考になればと思い記事にしました。
それでは素敵なNew Relicライフを!

参考

capture関数の公式ブログ

GitHubで編集を提案

Discussion