【学習メモ】Swatchのthresholdの使い方-track_byの挙動-

#はじめに
swatchのthreshold track_byには、正規表現で文字列を指定する解説ページが多いですが、manの```track_by="$2:$4"```がどう使うのかわからなかったので挙動を確認しました。

環境
CentOS6.9
Linux 2.6.32-696.20.1.el6.x86_64 GNU/Linux
Swatch 3.2.3

#まとめ
thresholdの設定に対しtrack_byは以下のように動作しました。
カウントの対象は1つだけではなく、track_byによりグループに分割されるようです。(概念なのでグループでなくても良いです)
thresholdを設定すると、watchforにヒットしtrack_byにヒットしないものもグループとみなされ、ヒットするものとは別にカウントするようです。

```:設定例
watchfor/(a)|(b)|(c)|(d)/i 
threshold track_by=????,type=limit,count=3,seconds=20
```

|track_byの内容|カウントのグループ|カウントのグループ数|挙動|
|:--:|:--:|:--:|:--|
|$_|a&#124;A&#124;b&#124;B&#124;c&#124;C&#124;d&#124;D|無限|対象の行をまるごとユニークなものとしてカウントします。時刻を含むログの場合は、同時刻のエラーでない限り、内容が同一でも別にカウントされます。*1|
|$1|a&#124;A&#124;b or B or c or C or d or D|3|\$1(aとA)以外のグループにも、thresholdの設定が適用されます。|
|$2|b&#124;B&#124;a or A or c or C or d or D|3|\$2(bとB)以外のグループにも、thresholdの設定が適用されます。|
|/\$1&#124;\$2/|a&#124;A&#124;b&#124;B&#124;c or C or d or D|5|\$1(aとA)と\$2(bとB)以外のグループにも、thresholdの設定が適用されます。|
|/a/|a or A or b or B or c or C or d or D|1|watchforにヒットすればtrack_byの内容に関係なくカウントします(```track_by=,```のように設定無しでも同様)|
- *1 ```trace_by=/$_/i```でiオプションを設定しても、対象行内の大文字小文字は区別されます。e.g. ```error was detected```と```Error was detected```と```Error was Detected```はそれぞれ別にカウント。
- 監視対象に複数のキーワードが書かれたときは、行頭に近いキーワードのみがカウントされます。


#検証
## 0.インストールのつまずき
Bit-Vector-7.1のmakeで以下のようなエラーが出ましたが、
```Vector.xs```ファイルの中間にある```#include "BitVector.h"```を先頭に持ってくればmakeが通るようになりました。
```
ToolBox.h:96:24: エラー: expected identifier before numeric constant bit-vector
make: *** [Vector.o] Error 1
```

参考資料
[Re: [perl #99408] Bleadperl v5.15.2-436-gbd31be4 breaksSTBEY/Bit-Vector-7.1.tar.gz(perl.org)](https://www.nntp.perl.org/group/perl.perl5.porters/2011/09/msg177494.html)

## 1.事前の情報収集と調査
#### thresholdで指定する値
|変数|値|
|:--:|:--:|
|track_by|**今回の調査対象**|
|type|limit / threshold / both|
|count|watchforに合致するキーワードを検出した回数|
|secounds|threshold機能で使用する秒数|
#### typeの挙動
|文字列|type|
|:--:|:--:|
|limit|検出からsecoundsで指定された間、limitで指定された回数だけアクションする。*1|
|threshold|初回検出からsecondsで指定された間、countの回数に達したときアクションする。アクションするとcountは0に戻る。*1 *2|
|both|thresholdと同じ条件で1度アクションしたら、secondsで指定された間はアクションしない。|
- \*1 count=0のときはアクションしません
- \*2 count=1のときは常時アクションします

参考資料
[swatch threshold設定のtypeパラメータ(wiki.bit-hive.com/tomizoo)](http://wiki.bit-hive.com/tomizoo/pg/swatch%20threshold%C0%DF%C4%EA%A4%CEtype%A5%D1%A5%E9%A5%E1%A1%BC%A5%BF)

## 2.track_byの挙動確認
### テストパターン
- 書き込み文字列は4パターン
```error occurred```, ```error detected```, ```ERROR ocurred```, ```warn occurred```

- watchforは2パターン
```/(error|warn)/```, ```/(error|warn)/i```

- track_byは4パターン
```$_```, ```$1```, ```/error/```. ```/error/i```

#### 変数の内容
exec echoで確認すると以下の結果になりました。

|変数|内容|
|:--:|:--|
|$_|検出した一行すべて|
|$0|```/.swatch_script.10000``` 数字はPIDが入る|
|$1|watchforに合致した、検出対象行の文字列。(watchforが```/error/i```でERRORが検出されたとき```ERROR```が格納される)|

#### 結果

書き込み文字列4パターンが、track_byの設定によりどのように判別されるか確認しました。

|track_byの内容|watchfor/(error&#124;warn)/|watchfor/(error&#124;warn)i/|
|:--:|:--:|:--|
|$_|すべて別にカウント|すべて別にカウント|
|$1|すべて別にカウント|```error occurred```と```error detected```は一緒にカウント、他は別にカウント*1 |
|/error/|検索対象がヒットすれば区別なくカウント|検索対象がヒットすれば区別なくカウント|
|/error/i|検索対象がヒットすれば区別なくカウント|検索対象がヒットすれば区別なくカウント|
- \*1 ```type=limit```のとき、countの回数を超えてアクションする場合がありました。threshold、bothではそういったことは起こりませんでした。

~~結局、\$2、\$4は何が格納されるのかわかりませんでした。~~
~~watchfor /(a|b|c|d)/でabcdをヒットさせても、\$2や\$4に検索の文字列は格納されませんでした。~~

### 追加検証(2018/2/16追記)

#### $2の検証

良くmanを読むとwatchforで囲まれたカッコが、\$の数ににあたるようです。

```watchfor/(error)|(panic)|(fatal)|(down)/i ```に変更して確認しました。
```type=limit```、```count=3```、```seconds=20```で試しています。

|track_byの内容|watchfor/(error)&#124;(panic)&#124;(fatal)&#124;(down)/i|
|:--:|:--|
|$_|すべて別にカウント *1|
|$1|error*1、panic/fatal/down*2 *3のグループでそれぞれカウントし、それぞれアクションする。|
|$2|panic*1、error/fatal/down*2 *3のグループでそれぞれカウントし、それぞれアクションする。|
|/\$1&#124;\$2/|error*1、panic*1、fatal/down*2 *3のグループでそれぞれカウントし、それぞれアクションする。|
- *1 大文字と小文字は区別され、別のグループとしてカウントされる。
- *2 大文字と小文字は区別されない
- *3 trace_byにiオプションを付けても区別されない
- typeがthreshold、bothのときも同様でした。
- watchforやtrack_byのキーワードを```/$1|$2/g```のように設定し、1行に複数のキーワードが含まれる場合でも、カウントは先頭に近いキーワードのみで、\$1/\$2のグループのカウントがそれぞれ増える仕様ではありませんでした。

#### $_の追加検証
検出対象の文で、大文字小文字がどのように区別されるか確認しました。
```watchfor /error/i```とします。
検出の対象文は```error detected```、```ERROR detected```、```error DETECTED```、```ERROR DETECTED```としました。

|track_byの内容|挙動|
|:--:|:--|
|\$_|4つとも別パターンとしてアクション|
|/\$_/i|4つとも別パターンとしてアクション|
- track_byにiオプションは効果がないようです。