アプリケーションパフォーマンス監視(APM)とロギングはどちらも、エコシステムに関するクリティカルなインサイトをもたらします。APMトレースとログにコンテクスト情報を組み合わせ、アプリの問題を解決するための重要な手がかかりを得ることもできます。
近年、ログデータはますます複雑化しており、従来型のツールを使って分析に役立つ関連情報にたどりつくことが困難なケースもあります。しかしElastic Stackをベースに開発されたElasticオブザーバビリティを使えば、Kibanaで数回クリックするだけのシンプルな操作でログとAPMを相関付けることが可能です。たとえば、Webアプリ内の特定のトランザクションについて、エンドユーザーが行った特定のリクエストに関連するログを簡単に表示することもできます。
Elastic APMでトレースログを表示する
下の画像はElastic APMのスクリーンショットです。いまこの画面には、特定のトランザクションに関わるすべての操作の詳細情報が示されています。[Actions](アクション)ボタンをクリックすると、次のようになります。
次に[Show trace logs](トレースログを表示)を選択してみましょう。
このようになりました。
表示されたメッセージは、この特定のトランザクションに関連する付加的な詳細情報です。このような詳細はAPMやその他のタイプの監視には適さないため、ログから取得するしかありません。Elasticのテクノロジーはトランザクションデータに詳細情報を追加するといったフレキシブルな処理に対応しますが、それはElastic Stackが監視のさまざまな側面を1つに統合しているおかげです。つまり、異なるタイプのデータを1つのデータストアに格納することで、高度な調査をすばやく実行できる仕組みになっています。
Elastic APM Python Agentをインストール・設定する
ここまでお読みいただいて、「メリットがあるのはいいけど、自社のシステムにどのように導入すればいいのか?」という疑問をお持ちかもしれません。
早速、ログとAPMトレースを統合する手法の一例をご紹介します。以下に示すのは、先ほどのスクリーンショットにあったPythonアプリに関連するコードです。目的は、エンドユーザーがアプリに対して行った各リクエストに情報を追加する方法の確立です。
最初の手順は、Elastic APM Python Agentのインストールです。依存関係として追加しましょう。このエージェントはFlaskアプリなので、依存関係名の後に角括弧つきの[flask]
がつきます。各サポート対象フレームワークの詳細は、Python Agentドキュメントでご覧いただくことができます。
# requirements.txtに次のように入力します。 elastic-apm[flask]==5.3.3
はじめに、適切なインポートが確実に行われるようにしましょう。
# app.pyに次のように入力します。 import logging from elasticapm.contrib.flask import ElasticAPM from elasticapm.handlers.logging import Formatter
次に、APMサーバーに情報を送信するPython Agentを設定します。
# app.pyに次のように入力します。 app = Flask(__name__) # アプリを通常の手順で初期化します app.config['ELASTIC_APM'] = { 'SERVICE_NAME': 'foodbankhero', # カスタムのAPMサーバーURLを設定します(デフォルト:http://localhost:8200) 'SERVER_URL': 'http://localhost:8200' # APMサーバーにトークンが必要な場合に使います # セキュリティのため、APMサーバーがトークンを要求するよう設定できます。第三者によるランダムなデータで溢れるリスクを回避します。 # 'SECRET_TOKEN': '' } apm = ElasticAPM(app) # これがFlaskアプリにAPMをインストルメントする魔法の一行です
ログを設定する
次に、上のスクリーンショットのようにAPMトレースと関連付けることができるよう、ログの設定を行います。
# app.pyに次のように入力します。 fh = logging.FileHandler('foodbankhero.log') # 先行の手順で、Python AgentのカスタムFormatterをインポートしました。 formatter = Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") fh.setFormatter(formatter) logging.getLogger().addHandler(fh) # …アプリの奥深くのどこかで動作します… logging.getLogger().info(‘Foodbank {} needs {} items’.format(id, len(items))) logging.getLogger().info(‘Returning {} foodbank records’.format(len(results)))
以下に、この設定で表示されるログのサンプルを示します。
2020-05-12 01:57:14,029 - flask.app - INFO - 172.22.0.1 - - [12/May/2020 01:57:15] "GET / HTTP/1.1" 200 - | elasticapm transaction.id=f31f884b961a6089 trace.id=02bd57be0eff9979c94951d0d53e80c0 span.id=None
上記の設定を行うことで、あらゆるリクエストに関する1行のログをトレース情報で強化できます。静的なアセットへのリクエストの場合も同様です(アプリがサービスを提供するよう設定されている場合)。以下はその一例です。
2020-05-12 01:57:14,029 - werkzeug - INFO - 172.22.0.1 - - [12/May/2020 01:57:14] "GET /favicon.ico HTTP/1.1" 404 - | elasticapm transaction.id=f31f884b961a6089 trace.id=02bd57be0eff9979c94951d0d53e80c0 span.id=None
Elastic APMを実際に使ってみる
従来型のデータサイロを破壊してコンテクスト情報を活用すれば、問題解決を早期化できます。Elasticオブザーバビリティなら、データの相関付けや必要な情報の入手を思考と同じスピードで、シンプルな操作で行えます。
Elastic APMを立ち上げる方法はとても簡単です。プロジェクトに数行のコードを追加するだけで、Elasticsearchへのデータ送信を開始できます。Elastic Cloudの無料トライアルを活用して、ぜひログとAPMの相関付けに挑戦してみてください。