SplunkでJSONを扱うと配列(array[]
)のところでイベントとして取り込みたい時があります。
その時は_props.conf_でLINE_BREAKER
を指定する必要があります。
何かとSPLUNK>Answersでも質問があるし、以前正規表現で書いてあったことも少し足りていなかったので、まとめてみます。
オフィシャル
-
LINE_BREAKER = <regular expression>
- デフォルト値は
([\r\n]+)
なのでSHOULD_LINEMERGE=false
(←ここ重要)の時に各行で区切られる。
- デフォルト値は
以下機械翻訳
- 行のマージが行われる前に、生のテキストストリームを初期イベントに分割する方法を決定する正規表現を指定します。
- 正規表現には、キャプチャグループ(一致の識別されたサブコンポーネントを定義する括弧のペア)が含まれている必要があります。
- マイクロソフトのサイトが詳しい
- 正規表現が一致する場合は常に、Splunkソフトウェアは、最初のキャプチャグループの開始を前のイベントの終了と見なし、最初のキャプチャグループの終了を次のイベントの開始と見なします。
- 最初のキャプチャグループの内容は破棄され、どのイベントにも存在しません。このテキストは行の間にあることをSplunkソフトウェアに伝えています。
このあと、いろいろな使い方が載っている。
解説
2021年01月08日 金曜日 10:07:54 AM
Employee3
Project Project Name Project Owner
------ ---------- -----------
A Y: \\Owner1\owner2
B Z: \\owner_1\owner 2
C g: \\owner11\owner12\owner 13
07 January 2021 18:21:56
Employee1
Project Project Name Project Owner
------ ---------- -----------
A Y: \\Owner1\owner2
B Z: \\owner_1\owner 2
C g: \\owner11\owner12\owner 13
Friday, January 8, 2021 10:04:44 AM
Employee2
Project Project Name Project Owner
------ ---------- -----------
A Y: \\Owner1\owner2
B Z: \\owner_1\owner 2
C g: \\owner11\owner12\owner 13
Thu Jan 7 22:33:44 EST 2021
Employee3
Project Project Name Project Owner
------ ---------- -----------
A Y: \\Owner1\owner2
B Z: \\owner_1\owner 2
C g: \\owner11\owner12\owner 13
Multiple timestamps in a file@Splunk>Answersから
要件は
- ログには複数の項目が記載されていて、それを時間でイベントに分けたい
- ただし時間のフォーマットは複数あり
props.conf
[many_datetime]
DATETIME_CONFIG =
LINE_BREAKER = (?m)([\r\n]+).*\d\d\:\d\d\:\d\d($| [AP]M| \w{3} \d{4})
NO_BINARY_CHECK = true
SHOULD_LINEMERGE = false
category = Miscellaneous
pulldown_type = true
-
LINE_BREAKER
は最初のキャプチャーだけしか反応しないので、($| [AP]M| \w{3} \d{4})
には反応しない。 -
(?m)
は正規表現のオプション_Multiline_。複数行のログを相手にする時にはつけると全体から探してくれるようになる。- 今回も行頭からログが始まっているからつけなくても大丈夫だと思っていたら日本語の時刻だと、
(?m)
がないとダメだった。 - 複数行のログを一括で扱う時には
(?s)
Singleline。.(ドット)
が\n(改行)
を無視して全体で一致してくれるオプションと同時に使うと便利その分正規表現が大変ですが
- 今回も行頭からログが始まっているからつけなくても大丈夫だと思っていたら日本語の時刻だと、
JSON
{ [-]
glossary: { [-]
GlossDiv: { [-]
GlossList: { [-]
GlossEntry: { [-]
Abbrev: ISO 8879:1986
Acronym: SGML
GlossDef: { [-]
GlossSeeAlso: [ [-]
GML
XML
]
para: A meta-markup language, used to create markup languages such as DocBook.
}
GlossSee: markup
GlossTerm: Standard Generalized Markup Language
ID: SGML
SortAs: SGML
}
}
title: S
}
title: example glossary
}
}
Splunkで取り込んだJSONをみるとこんな感じに見える。
でも実際は
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
これは、イベントの構文を強調表示
やrawテキストとして表示
をクリックすることで切り替えることが可能
実際にログの取り込みについて検討する時は、rawテキストでみていく必要がある。
上の例もAPIのレスポンスだと
{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}
と1行
これを前提にイベントの区切りを考える必要がある。
{"fruits":[{"fruit":"orange","location":"tray1","date":"6/20/2014","instances_1":[{"name":"orange","type":"citrus","shape":"round","status":"ok"}],"instances_2":[{"name":"orange","type":"citrus","shape":"round","status":"ok"},{"name":"orange","type":"citrus","shape":"round","status":"ok"},{"name":"orange","type":"citrus","shape":"round","status":"ok"}]},{"fruit":"lemon","location":"tray2","date":"6/20/2015","instances_1":[{"name":"a","type":"citrus","shape":"round","status":"ok"}],"instances_2":[{"name":"a","type":"citrus","shape":"round","status":"ok"},{"name":"b","type":"citrus","shape":"round","status":"ok"},{"name":"c","type":"citrus","shape":"round","status":"ok"}]},{"fruit":"clementine","location":"tray3","date":"6/20/2016","instances_1":[{"name":"a","type":"citrus","shape":"round","status":"ok"}],"instances_2":[{"name":"a","type":"citrus","shape":"round","status":"ok"},{"name":"b","type":"citrus","shape":"round","status":"ok"},{"name":"c","type":"citrus","shape":"round","status":"ok"}]}]}
サンプルとしてHow to configure props.conf to parse JSON data structures?のJSONを取り込んでみる。
いい感じで日付も入っているのでわかりやすい。
取り込み設定
[ example_json ]
CHARSET=UTF-8
KV_MODE=JSON
SHOULD_LINEMERGE=false
category=Structured
description=JavaScript Object Notation format.
disabled=false
pulldown_type=true
LINE_BREAKER=(.){\"fruit\"
SEDCMD-json=s/(?m)]}$// s/\"}$/"}]}/ s/{\"fruits\"://
TIME_FORMAT=%m/%d/%Y
TIME_PREFIX=date\":\s*\"
MAX_DAYS_AGO=4000
解説
-
INDEXED_EXTRACTIONS
は何も加工しない時に使用できる。SEDCMD
等でログそのものを加工する際は使えない。-
KV_MODE=JSON
を使用しましょう
-
-
LINE_BREKER
は{\"fruit\"
の前の一文字で区切りを指定。今回は,
だったり[
- 分割すると余計な部分が出てくるので、それを
SEDCMD
で削除かつ追加して正規なJSONフォーマットにしてあげている。- JSONフォーマットにしてあげるのは重要。きちんとしたフォーマットになればリスト表示で
構文を強調表示
の項目が出てくれる。 -
SEDCMD
についてはrexの_sed mode_と一緒。なので置換側が正規表現じゃないことには注意
- JSONフォーマットにしてあげるのは重要。きちんとしたフォーマットになればリスト表示で
サーチでの確認方法
データの取り込み画面でいろいろと試すのもありですが、正規表現の確認だとサーチ画面でやったほうがいろいろと試しやすい。
自分もSplunk>Answersで回答する場合、取り込まなくても設定が作れるので重宝しています。
詳しくは別途。
その他いろいろ
- 区切る場所のキャプチャーする文字がない時は
LINE_BREAKER = ()何かの文字列
でもキチンと切ってくれる。 - キャプチャーする場所・区切る場所は
|
で区切って複数記述できる。なのであまり正規表現にこだわる必要はない。-
LINE_BREAKER = end(\n)begin|end2(\n)begin2|begin3
の例のとおり -
(?=なにか)
とか(?<=なにか)
で頑張る必要はありません。フィールド抽出は違いますが。
-
- 複数行のログでなんかキャプチャーできないなという時は
(?ms)
を使ってみよう。- props.confにおけるLINE_BREAKERについてでは自動って書いたけど、ログによるので。
- 逆になんか反応多すぎって時は
(?-ms)
でオプションを明示的に外してみる。
適用の順番
Index time versus search timeによると
The following processes occur during index time:
- Default field extraction (such as host, source, sourcetype, and timestamp)
- Static or dynamic host assignment for specific inputs
- Default host assignment overrides
- Source type customization
- Custom index-time field extraction
- Structured data field extraction
- Event timestamping
- Event linebreaking
- Event segmentation (also happens at search time)
の順番。LINE_BREAKER
が動くのは8番目
加工したJSONがINDEXED_EXTRACTIONS
で読み込めない理由がよくわかる。
まとめ
LINE_BREAKER
で適切にログを区切ってやると、読みやすくなるだけでなく、Splunkにも優しくなります。
今回は触れませんでしたが、_transforms.conf_で不要な部分とかは取り込まない設定ができますので、_props.conf_でやらなくても問題はないと思います。