- 引き続き
- Elasticsearch でも APM
— 本記事作成時の環境
— Python から Elasticsearch を扱う場合
— サンプルアプリケーション
— Patch
— tracer.wrap - さて、今日は何処で呑もうかな、何を食べようかな
— やっぱもつ鍋ばい
— 福岡で焼肉食べたいばってん、禁煙の席があるといいねえ - ということで
引き続き
github.com
を弄っています。
Elasticsearch でも APM
Elasticsearch でも簡単に始めることが出来ます。もちろん、Amazon Elasticsearch Service でも無問題(IAM の処理が必要となる場合があります)です。尚、dd-trace-py については導入済みという体で進めます。
本記事作成時の環境
本記事を書くにあたり利用した環境は以下の通りです。
$ python --version Python 2.7.13 $ pip list --format=columns | egrep 'elasticsearch|ddtrace' ddtrace 0.8.0 elasticsearch 5.3.0
尚、Amazon Elasticsearch Service のアクセスポリシーは IP アドレスによるアクセス制御で利用します。
Python から Elasticsearch を扱う場合
以下のモジュールを利用します。
github.com
Elastic 謹製です。
サンプルアプリケーション
今回は Elasticsearch に読み込ませた 20 万件程度のレストランデータを検索するコマンドラインツールを作ってみたので、そのコマンドラインツールを dd-trace-py を利用して各処理を追跡して可視化してみたいと思います。
超ざっくりで Elasticsearch のクエリチューニングは一切行っていませんが、一応、以下のように --name
や --location
オプションで指定したキーワードを含むレストランのリストがダーッと標準出力に表示されます。
$ python restaurant-search.py --name '焼き鳥' --location '福岡' 2> /dev/null 焼き鳥 一郎 | 福岡市博多区美野島2-11-14 | 焼き鳥の屋台 花山 | 福岡市東区箱崎1 | 焼き鳥 たかつ 三苫店 | 福岡市東区三苫1-16-44 | 焼き鳥 木鶏 | 福岡市中央区平尾4-5-15日之出第2平尾ビル | 炭火焼き鳥 ちびっこ大将 | 福岡市中央区高砂2-11-33北村コーポ 1F | 焼き鳥 いわた | 福岡市中央区渡辺通5-24-37レジデンス江崎 2F | 博多水炊きと焼き鳥 鳥善 | 福岡市中央区薬院2-15-2ルミエール薬院1F |
ちなみに、レストランデータは[こちら(https://github.com/livedoor/datasets)のデータを利用させて頂き、stream2es で Amazon Elasticsearch Service に放り込んでいます。
Patch
以下のように elasticsearch-py にパッチを当てるだけで Elasticsearch へのクエリを追跡出来るようになります。
from ddtrace import Pin, patch, patch_all patch(elasticsearch=True)
ソースコードを大幅に手をいれる必要が無いのが嬉しいですね。
tracer.wrap
今回は Elasticsearch へのクエリ以外に、検索処理を担う関数をはじめ、スクリプトの各種関数についてもパフォーマンスをトレースしてみたいと思いますので、tracer.wrap を利用してみたいと思います。
tracer.wrap は関数全体をトレースするデコレータで、以下のように関数の上にちょこんとのっけるだけで、関数の処理結果を Datadog に送信することが出来るようになります。
... @tracer.wrap('scroll_index', service='sample-app') def scroll_index(scroll_size, sid): try: while (scroll_size > 0): page = es().scroll(scroll_id=sid, scroll='2m') sid = page['_scroll_id'] scroll_size = len(page['hits']['hits']) output(page['hits']['hits']) except Exception, e: print e ...
ちなみに、デコレータとは対象となる関数をいじることなく、その関数の挙動にてを加える手法という認識で、上記だと scroll_index(scroll_size, sid):
という関数に対して、@tracer.wrap
という関数でデコレート(装飾)することになります。
さて、今日は何処で呑もうかな、何を食べようかな
やっぱもつ鍋ばい
もつ
と福岡
で検索してみます。
$ python restaurant-search.py --name 'もつ' --location '福岡' 2> /dev/null もつもつ天神店 | 福岡市中央区天神3−3−5久保田ビル2F | もつ壙 | 福岡市博多区中洲3-3-3 | ... ... 二十四 永徳屋 博多もつ鍋 | 福岡市博多区美野島1-4-32松永ビル1F |
さすが、もつ鍋王国の博多です。
span = tracer.current_span() span.set_tag('name', unicode(name, 'utf-8', 'ignore'))
上記のように span.set_tag
で Span に対して任意のタグを付与することが出来ます。
福岡で焼肉食べたいばってん、禁煙の席があるといいねえ
もつ
と 福岡
そして禁煙
で検索します。
$ python restaurant-search.py --name '焼肉' --location '福岡' --keyword '禁煙' 2> /dev/null 焼肉処 國 | 福岡市南区野間2-7-13ヴィラージュ野間 1F | 席数 25席 (掘りごたつ4つとカウンター5席) 駐車場 無 予約 予約可 貸切 可 (20人以下可) 禁煙・喫煙 全面喫煙可 カード 不可
一軒しかヒットしないのは寂しいですが、以下のように検索に利用したキーワードが span のタグとして確認することが出来ます。
Elasticsearch の検索が関数の殆どの時間を使っていることがひと目で判ります。
ということで
dd-trace-py を使うことで、アプリケーションの関数毎のパフォーマンスやデータベースへのアクセス時間をソースコードに殆ど手を加える事無く Datadog で監視出来るというのは嬉しい限りです。