じゅのぶろ

社内SEが自宅でSOC/CSIRTするために色々頑張っていきたいブログ 画像が見れない場合はjavascriptを有効にするかデスクトップからご覧下さい。

Splunkでログを調べる(stats編)

この記事ではよく使うコマンドの一つ、statsを紹介します。

statsコマンド

出力結果を表にするコマンドです。
次のようなときに使います。

  • 統計関数を使いたい
  • 検索速度を上げたい

使い方

以下の画像の関数が利用できます(Splunk Docsより引用)

statsコマンドで使える関数の一覧

この中からよく使う関数を紹介します。

count() or c()

イベントの件数をカウントします。
イベントの件数をカウントした結果

by句を使うことでフィールドごとの件数を取得することもできます。
by句を用いてイベントの件数をカウントした結果

by句の後のフィールドは複数指定できます。
by句に複数のフィールドを指定してイベントの件数をカウントした結果

values()

フィールドの値をマルチバリュー(重複なし)で取得します。
countと組み合わせて以下のようにstatus_codeごとの件数とドメインの内訳が取得できます。
status_codeごとの件数とドメインの内訳

フィールド名がvalues(domain)になると扱いづらいのでas句を使って別名にすると後続の処理がある場合は楽になります。
例) | stats count values(domain) as values_domain by status_code

list()

フィールドの値をマルチバリュー(重複あり)で取得します。
ただし、valuesと異なり上限値があり、100件で打ち切られてしまいます。
この画像ではcountが987ですが、list_domainでは100個のマルチバリューとなっています。
status_codeごとの件数とドメインの内訳

distinct_count() or dc()

by句で指定したフィールドに対してdistinct_countで指定したフィールドの重複のない数を返します。
以下の画像では、byでdomainを指定し、distinct_countにsrc_ipを指定しています。
表の一番上から見ると、www.google.co.jpには3つのsrc_ipからのアクセスがあり、合計51件のアクセスがあるとわかります。
adservice.google.co.jpには2つのsrc_ipからのアクセスがあり、合計52件のアクセスがあるとわかります。
distinc_countコマンドの例

earliest/latest/range

どの時間範囲で発生したイベントなのか調査する際に使います。
rangeはlatest-earliestと同じになります。
distinc_countコマンドの例

null値に注意

statsコマンドではnull値が無視されてしまいます。
例えば、httpの通信はファイルパス(url_pathフィールド)がロギングされますが、connectの通信ではロギングされません。 そのため、url_pathフィールドをカウントすると次のように1255件なります。
fillnullなしではcountが1255件

fillnullコマンドでnull値を変換すると、次のようにcountが2536件に増加します。 fillnullありだとcountが2536件

null値はcount()内だけでなくby句の後でも同様に無視されてしまうので、statsに使用するフィールドは事前にfillnullコマンドを使っておくことが無難です。

おまけ

各関数内ではeval関数が使えます。
例えば特定の拡張子のみをcountする場合、以下のように使います。
count内でevalを使う例

| stats count(eval(if(like(url_path,"%.js"),1,NULL))) as js count(eval(if(like(url_path,"%.css"),1,NULL))) as css values(url_path) by domain
| search js!=0 AND css!=0

当然valuesにも使えます。
jsとcss以外の拡張子のファイルパスは「OTHER」に置き換える場合は以下のようにします。
values内でevalを使う例

| stats count(eval(if(like(url_path,"%.js"),1,NULL))) as js count(eval(if(like(url_path,"%.css"),1,NULL))) as css 
        values(eval(if(like(url_path,"%.css") OR like(url_path,"%.js"),url_path,"OTHER"))) as values_domain by domain
| search js!=0 AND css!=0