reizist's blog

ウェブ

apache drillが凄い

apache drillというツールが凄いので雑に使ってみました。

一言でいうと Treat your data like a table even when it's not なんですけど、もっというと jsonに対してsql実行できたりします。

公式のインストール方法の通りにできますが、

reizist@reizist ~/apache-drill-1.5.0 $ brew search apache-drill                                                                                                              [2.3.0]
apache-drill

の通りbrew経由でも落とせるみたいですね。

ちょっとサーバーのアクセスログの解析が必要だったんですけど、 気軽にやる方法ないかなーと思って(もっぱら最近はfluentd + kibanaとかBigQueryとかそこらへんが主流ですが)検討した結果、 「ltsv出力してあるnginxログをjsonに変換してapache drillに流す」ことをしてみようと思いました。 awkとか使いこなせる人にはあまり要らないのかな。

まず

gem install ltsv2json
ltsv2json production_access_log.log > production_access_log.json

などとしjsonを生成したあとおもむろにapache drillを起動します

reizist@reizist ~/apache-drill-1.5.0 $ bin/drill-embedded                        [2.3.0]
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512M; support was removed in 8.0
3 16, 2016 8:36:58 午後 org.glassfish.jersey.server.ApplicationHandler initialize
情報: Initiating Jersey application, version Jersey: 2.8 2014-04-29 01:25:26...
apache drill 1.5.0
"a drill is a terrible thing to waste"
0: jdbc:drill:zk=local> select * from dfs.`/tmp/production_lb_access.json` where uri='/';
+-----------------------------+-----------------+---------------+-------+---------+------+---------+-------+--------------------------+----------------------------------------------------------------------------------------------------------------+----------+--------+-----------+----------+--------------------+
|            time             |      host       | forwardedfor  | user  | method  | uri  | status  | size  |         referer          |                                                       ua                                                       | reqtime  | cache  |  runtime  | apptime  |       vhost        |
+-----------------------------+-----------------+---------------+-------+---------+------+---------+-------+--------------------------+----------------------------------------------------------------------------------------------------------------+----------+--------+-----------+----------+--------------------+
| 14/Mar/2016:05:42:24 +0900  | 111.11.11.111  | -             | -     | GET     | /    | 302     | 96    | -                        | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36  | 0.110    | -      | 0.107515  | 0.110    |  [censored]  |
| 14/Mar/2016:06:02:17 +0900  | 111.11.11.111   | -             | -     | GET     | /    | 302     | 96    | -                        | Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)                                        | 0.011    | -      | 0.008270  | 0.011    | [censored]  |
| 14/Mar/2016:06:47:02 +0900  | 111.11.11.111  | -             | -     | GET     | /    | 302     | 194   | -                        | Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12F70     | 0.055    | -      | 0.051819  | 0.055    | [censored]    |
+-----------------------------+-----------------+---------------+-------+---------+------+---------+-------+--------------------------+----------------------------------------------------------------------------------------------------------------+----------+--------+-----------+----------+--------------------+

おぉ凄い便利。

例えば実アクセスログから処理時間がかかっているリクエストを調べたい場合は以下のようにできますね。

0: jdbc:drill:zk=local> select * from dfs.`/tmp/production_lb_access.json` order by runtime desc limit 10;
+----------+--------+---------------+------------------+---------+----------+----------+-----------+-------+---------+-----------------------------+----------------------------------------------------------------------------------------------------------------+------------------------+-------+------------------+
| apptime  | cache  | forwardedfor  |       host       | method  | referer  | reqtime  |  runtime  | size  | status  |            time             |                                                       ua                                                       |          uri           | user  |      vhost       |
+----------+--------+---------------+------------------+---------+----------+----------+-----------+-------+---------+-----------------------------+----------------------------------------------------------------------------------------------------------------+------------------------+-------+------------------+
| 9.935    | -      | -             | 111.111.11.11   | POST    | -        | 9.979    | 9.932773  | 5666  | 200     | 14/Mar/2016:05:12:42 +0900  | Dalvik/1.6.0 (Linux; U; Android 4.4.4; 305SH Build/S0114)                                                      | /path/action           | -     | [censored]  |
| 9.914    | -      | -             | 111.111.11.11      | POST    | -        | 9.963    | 9.911458  | 9185  | 200     | 14/Mar/2016:12:34:58 +0900  | Dalvik/1.6.0 (Linux; U; Android 4.4.2; F-01F Build/V10R22A)                                                    | /path/action           | -     | [censored]  |
| 10.472   | -      | -             | 111.111.11.11   | GET     | -        | 10.472   | 9.910428  | 3611  | 200     | 14/Mar/2016:14:14:02 +0900  | Mozilla/5.0 (iPhone; CPU iPhone OS 9_2_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13D15  | /path/action     | -     | [censored]  |
| 9.901    | -      | -             | 111.111.11.11    | POST    | -        | 9.901    | 9.897920  | 8154  | 200     | 14/Mar/2016:14:13:03 +0900  | Dalvik/2.1.0 (Linux; U; Android 5.0.2; SC-05G Build/LRX22G)                                                    | /path/action           | -     | [censored]  |
| 14.933   | -      | -             | 111.111.11.11    | POST    | -        | 14.956   | 9.888321  | 3377  | 200     | 14/Mar/2016:14:39:21 +0900  | Dalvik/1.6.0 (Linux; U; Android 4.4.2; LGV31 Build/KVT49L.LGV3110f)                                            | /path/action           | -     | [censored]  |
| 9.884    | -      | -             | 111.111.11.11  | POST    | -        | 9.884    | 9.881206  | 5225  | 200     | 14/Mar/2016:13:19:43 +0900  | hoge/1.0.10 CFNetwork/758.2.8 Darwin/15.0.0                                                                | /path/action           | -     | [censored]  |
| 9.910    | -      | -             | 111.111.11.11   | POST    | -        | 9.910    | 9.869544  | 4398  | 200     | 14/Mar/2016:03:35:00 +0900  | Dalvik/1.6.0 (Linux; U; Android 4.1.2; SBM203SH Build/S0026)                                                   | /path/action        | -     | [censored]  |
| 10.186   | -      | -             | 111.111.11.11    | POST    | -        | 10.215   | 9.869021  | 4168  | 200     | 14/Mar/2016:03:40:30 +0900  | hoge/1.0.10 CFNetwork/758.2.8 Darwin/15.0.0                                                                | /path/action        | -     | [censored]  |
| 9.862    | -      | -             | 111.111.11.11   | POST    | -        | 9.862    | 9.859476  | 2938  | 200     | 14/Mar/2016:12:30:27 +0900  | Dalvik/2.1.0 (Linux; U; Android 5.1; KYV35 Build/103.0.2e00)                                                   | /path/action  | -     | [censored]  |
| 9.851    | -      | -             | 111.111.11.11      | POST    | -        | 9.871    | 9.847916  | 8592  | 200     | 14/Mar/2016:05:11:59 +0900  | Dalvik/2.1.0 (Linux; U; Android 5.1; KYT31 Build/100.0.1c10)                                                   | /path/action           | -     | [censored]  |
+----------+--------+---------------+------------------+---------+----------+----------+-----------+-------+---------+-----------------------------+----------------------------------------------------------------------------------------------------------------+------------------------+-------+------------------+

ちなみに上記クエリは3GBのjsonファイルに対して実行しかかった時間は 74.361 seconds でした。

上記程度であれば例えばNewRelicのようなものがあればこんなことをせずにすみますが、使い慣れたSQLでさらさらと手元で調べられるのは小回りがきいていいですね。