全文検索SaaS「Algolia」のAPI利用状況をログから調べる
Algoliaは多言語に対応した全文検索SaaSです。使いやすい機能と明瞭な料金体系のため、かんたんにサイト導入できます。
Algoliaの運用を始めると気になるのが、APIの利用状況です。
ダッシュボードを見れば全体的な傾向をつかめますが、検索APIの内訳やエラー内容を確認したい場合は、個別ログを確認するのが手っ取り早いです。 AlgoliaはAPI数課金なのに、気づかずに無駄なAPIをたくさん読んでいた、なんてことになりたくないですしね。
今回は Get Logs API を使って、APIログを取得し、分析する方法を紹介します。
Get Logs API で生ログをログ取得
Algoliaは管理コンソールの API Monitoring メニューから、利用状況や、直近のリクエストの生ログなど、非常に多くの情報を取得できます。
一方で、ユーザーが特定の用途に向けてAPI呼び出しを分析したい場合、生ログを取得するのが確実です。
Get Logs APIを利用すると、過去7日のAPIログを取得できます。
やってみる
Python依存ライブラリを利用
Algolia のAPI実行には、Python SDKを利用します。
依存ライブラリをインストールします。
$ pip install --upgrade algoliasearch pandas
APIキーを作成
Get Logs API を利用するには、 logs ACL が必要です。
デフォルトの Write API キーを利用するか、logs
ACL だけを許可した専用のAPIキーを発行しましょう。
Get Logs APIを呼び出す
Get Logs APIを 呼び出します。
from algoliasearch.search_client import SearchClient client = SearchClient.create('APP-ID', 'KEY') client.get_logs()
client.get_logs()
のデフォルト値を明示する場合、以下の通りです。
client.get_logs({ // All the following parameters are optional 'offset' : 0, 'length': 1000, 'type' : 'all' })
offset
: 0 以上の値を指定し、0 は最新のログですlength
: オフセットからのログレコード数です。最大は1000です。type
: ログの種類を指定します。all
: 全てquery
: 検索build
: インデックス・レコード操作erro
: エラー
実行すると、以下のような JSON が返却されます。
{ "logs":[ { "timestamp":"2017-12-29T18:15:57Z", "method":"POST", "answer_code":"200", "query_body":"\n{\n \"requests\": [\n {\n \"indexName\": \"best_buy\",\n \"params\": \"query=&hitsPerPage=10&page=0&attributesToRetrieve=*&highlightPreTag=%3Cais-highlight-0000000000%3E&highlightPostTag=%3C%2Fais-highlight-0000000000%3E&getRankingInfo=1&facets=%5B%22brand%22%2C%22categories%22%2C%22free_shipping%22%2C%22type%22%5D&tagFilters=\"\n }\n ]\n}\n", "answer":"\n{\n \"results\": [\n {\n \"hits\": [\n {\n \"name\": \"Amazon - Fire TV Stick\",\n \"description\": \"Amazon Fire TV Stick connects to your TV's HDMI port. Just grab and go to enjoy Netflix, Prime Instant Video, Hulu Plus, YouTube.com, music, and much more.\",\n \"brand\": \"Amazon\",\n \"categories\": [\n \"TV & Home Theater\",\n \"Streaming Media Players\"\n ],\n \"hierarchicalCategories\": {\n \"lvl0\": \"TV & Home Theater\",\n \"lvl1\": \"TV & Home Theater > Streaming Media Players\"\n },\n \"type\": \"Streaming media plyr\",\n \"price\": 39.99,\n \"price_range\": \"1 - 50\",\n \"image\": \"https:\/\/cdn-demo.algolia.com\/bestbuy\/9999119_sb.jpg\",\n \"url\": \"http:\/\/www.bestbuy.com\/site\/amazon-fire-tv-stick\/9999119.p?id=1219460752591&skuId=9999119&cmp=RMX&ky=1uWSHMdQqBeVJB9cXgEke60s5EjfS6M1W\",\n \"free_shipping\": false,\n \"popularity\": 9843,\n \"rating\": 4,\n \"objectID\": \"9999119\"\n", "url":"\/1\/indexes\/*\/queries?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%203.24.7%3BAlgolia%20Dashboard%201.0.0%3Breact-instantsearch%204.1.3%3BJS%20Helper%202.23.0&x-algolia-application-id=AJ0P3S7DWQ&x-algolia-api-key=ce11****************************", "ip":"84.14.205.82", "query_headers":"Host: c1-de-3.algolianet.com\nConnection: keep-alive\nContent-Length: 308\naccept: application\/json\nOrigin: https:\/\/www.algolia.com\nUser-Agent: Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/63.0.3239.84 Safari\/537.36\ncontent-type: application\/x-www-form-urlencoded\nReferer: https:\/\/www.algolia.com\/apps\/AJ0P3S7DWQ\/explorer\/browse\/best_buy\nAccept-Encoding: gzip, deflate, br\nAccept-Language: fr,en;q=0.9\n", "sha1":"44c168cea54d2deca9a4724559cf15eccf15cf3e", "nb_api_calls":"1", "processing_time_ms":"1", "query_nb_hits":"10500", "index":"demo_index", "inner_queries":[ { "indexName":"best_buy", "queryID":313453231, "offset":0, "userToken":"user_1" } ] } ] }
エラーログを確認
失敗したAPIログだけを取得したい場合、'type':'error'
でフィルターします。
from algoliasearch.search_client import SearchClient from pprint import pprint client = SearchClient.create('APP-ID', 'KEY') logs = client.get_logs({ 'type':'error', }) for log in logs['logs']: pprint(log)
出力
{'answer': '\n' '{\n' ' "message": "Invalid Application-ID or API key",\n' ' "status": 403\n' '}\n', 'answer_code': '403', 'index': 'xxx', 'ip': '*.*.*.*', 'method': 'POST', 'processing_time_ms': '1', 'query_body': '\n{\n "query": "test"\n}\n', 'query_headers': '...', 'sha1': '2f3a6eefae711cda7fcf0f19f62485a63f0e6239', 'timestamp': '2022-06-16T09:17:23Z', 'url': '/1/indexes/xxx/query'}
ログをJSONからCSVに変換
スプレッドシートで分析できるよう、pandas を使い、JSONをCSVに変換して保存します。
import pandas as pd from algoliasearch.search_client import SearchClient from urllib.parse import urlparse client = SearchClient.create('APP-ID', 'KEY') logs = client.get_logs() df = pd.DataFrame.from_records(logs['logs']) df['path'] = df['url'].map(lambda s : urlparse(s).path) df.to_csv('algolia_logs.csv')
一部のAPIの url
フィールドは /1/indexes/xxx/query?x-algolia-agent=Algolia%20for%20JavaScript%20(4.12.1)%3B%20Browser
というように GET パラメーターも含まれることがあります。
API を抽出するために、 df['path'] = df['url'].map(lambda s : urlparse(s).path)
でURIのパス部のみを抽出しています。
API ごとの呼び出し数を集計
AlgoliaはAPI呼び出し数に応じて課金が発生します。
APIごとにGROUP BYして、API の呼び出し傾向を確認します。
import pandas as pd from algoliasearch.search_client import SearchClient from urllib.parse import urlparse client = SearchClient.create('APP-ID', 'KEY') logs = client.get_logs() df = pd.DataFrame.from_records(logs['logs']) df['path'] = df['url'].map(lambda s : urlparse(s).path) df_aggr = df.groupby(['path'])['path'].count() print(df_aggr)
出力
path /1/indexes/xxx/batch 31 /1/indexes/xxx/facets/_tags/query 23 /1/indexes/xxx/query 118 /1/indexes/xxx/rules/search 3 /1/indexes/xxx/settings 1 Name: path, dtype: int64
文字検索とタグ検索の割合がおよそ5:1であるとわかりました。
インデックスを更新する batch
も思いの外、呼び出されています。
最後に
Algolia の Get Logs APIを使い、ログを調査・分析する方法を紹介しました。 管理コンソールの API Monitoring では不十分な場合にご活用ください。
API の説明に "Retrieve the logs of your last 1,000 API calls. This helps with real-time debugging of your application." とあったり、ログの保存期間が7日なことからもわかるように、過去をさかのぼったログの調査には向いていません。
そのような要件がある場合、sha1
フィールドをキーに、データベースに永続的に保存すると良いかもしれません。
それでは。