実施環境: Splunk Free 8.2.2
0. 概要
ログによっては、例えば以下のように複数のログが一連のイベントを表す場合があります。
10:21 ユーザ001 ログイン
10:23 ユーザ001 商品Aをかごに入れる
10:24 ユーザ001 商品Bをかごに入れる
10:28 ユーザ001 商品Aをかごから出す
10:29 ユーザ001 商品Cをかごに入れる
10:32 ユーザ001 購入
10:33 ユーザ001 ログアウト
このようなログについて、同じイベントを表すログを1つにまとめて解析したいことがあります。
そのようなときに用いるのが、 transaction コマンドです。
このコマンドは時間やフィールド値によって同じイベントを表すログをグループ化し、1つにまとめることができるコマンドです。
今回はこの transaction コマンドについて紹介します。
1. 基本
今回は以下のようなログを自作して使用しました。
index="test_index" sourcetype="test_access"
| sort _time
| table _time, _raw, host_name, user_name, action
transaction コマンドの基本的な文法は以下の通りです。
キーとなるフィールドを指定して、その値をもとにグループ化します。
transaction フィールド名1, フィールド名2, ...
試しに、「 user_name 」を指定して transaction コマンドを実行してみます。
index="test_index" sourcetype="test_access"
| transaction user_name
| sort _time
| table _time, _raw, host_name, user_name, action, closed_txn, duration, eventcount, field_match_sum
「 user_name 」が「 user1 」のデータと「 user2 」のデータで、2つにグループ化されました。
次に、「 host_name 」も追加で指定してみます。
index="test_index" sourcetype="test_access"
| transaction user_name, host_name
| sort _time
| table _time, _raw, host_name, user_name, action, closed_txn, duration, eventcount, field_match_sum
グループ化の条件に、「 host_name 」も追加されました。
2. 追加されるフィールド
さて、上記の SPL で、 table コマンドに指定しているフィールドが transaction コマンドを入れる前後で増えていることにお気付きでしょうか。
これは単に指定を増やしたのではなく、実際に transaction コマンドを通すとフィールドがいくつか増えるのです。
実際に詳細モードで SPL を実行して確認してみます。
index="test_index" sourcetype="test_access"
index="test_index" sourcetype="test_access"
| transaction user_name, host_name
「 closed_txn 」「 duration 」「 eventcount 」「 field_match_sum 」の4つのフィールドが追加されていることがわかります。
「 closed_txn 」は基本的に0ですが、後述の「 maxevents 」「 maxpause 」「 maxspan 」「 startswith 」のいずれかを指定し、それが適用された場合に1になります。
「 duration 」はそのデータにまとめられたログの、最初のログから最後のログまでの秒数です。今回は8:19:01から8:20:22までの81秒です。
「 eventcount 」はそのデータにまとめられたログの件数です。
「 field_match_sum 」はそのデータにまとめる際にヒットしたフィールドの個数です。今回は「 user_name 」「 host_name 」の2つのフィールドをコマンドで指定しているので、2×2=4個となります。
3. オプション
前述の SPL ではログをグループ化するのにフィールドを使用しました。
さらに transaction コマンドのオプションによって、時間やログデータの文字列をグループ化に使用することができます。
maxpause を指定した場合、ログとログの間の時間が指定した時間より大きいとその2つのログは別のグループとして扱います。
index="test_index" sourcetype="test_access"
| transaction maxpause=5m user_name, host_name
| sort _time
| table _time, _raw, host_name, user_name, action, closed_txn, duration, eventcount, field_match_sum
maxspan を指定した場合、グループの最初のログと特定のログの間の時間が指定した時間より大きいとその2つのログは別のグループとして扱います。
index="test_index" sourcetype="test_access"
| transaction maxspan=30m user_name, host_name
| sort _time
| table _time, _raw, host_name, user_name, action, closed_txn, duration, eventcount, field_match_sum
startswith を指定した場合、指定した文字列が含まれるログでグループが区切られ、該当のログはグループの最初のログとして扱われます。
index="test_index" sourcetype="test_access"
| transaction startswith="login" user_name, host_name
| sort _time
| table _time, _raw, host_name, user_name, action, closed_txn, duration, eventcount, field_match_sum
endswith を指定した場合、指定した文字列が含まれるログでグループが区切られ、該当のログはグループの最後のログとして扱われます。
index="test_index" sourcetype="test_access"
| transaction endswith="logout" user_name, host_name
| sort _time
| table _time, _raw, host_name, user_name, action, closed_txn, duration, eventcount, field_match_sum
4. stats コマンドでの代用
ここまで transaction コマンドについて紹介してきましたが、実のところ transaction コマンドは性能面等から見てあまり良いコマンドではなかったりします。
そのため、可能であれば以下のように stats コマンド等で代用することが好ましいです。
index="test_index" sourcetype="test_access"
| eval time = _time
| bin span=30m _time
| stats count AS eventcount, min(time) AS min_time, max(time) AS max_time BY _time, host_name, user_name
| eval _time = min_time
| eval duration = max_time - min_time
| sort _time
| table _time, host_name, user_name, duration, eventcount
transaction コマンドが必要となる場面は主に、フィールド値だけではログのグループ化が難しい場面(なおこの場合、前述のオプションが必要となることが多い)です。
そうでない場合は stats コマンドでの代用を検討することをおすすめします。