DataKit ログコレクターの性能テスト
環境とツール¶
- オペレーティング システム: Ubuntu 20.04.2 LTS
- CPU:Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
- メモリ: 16GB 速度 2133 MT/秒
- DataKit:1.1.8-rc1
- ログテキスト (nginx アクセスログ):
172.17.0.1 - - [06/Jan/2017:16:16:37 +0000] "GET /datadoghq/company?test=var1%20Pl HTTP/1.1" 401 612 "http://www.perdu.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36" "-"
- ログ数:100,000行
- Pipelineの使用: 以下を参照
テスト結果¶
| 試験条件 | 時間がかかる |
|---|---|
| Pipelineなし、純粋なログ テキスト処理 (エンコード、複数行およびフィールドの検出などを含む) | 3秒63 |
| Pipeline のフルバージョンを使用します (付録 1 を参照) | 43秒70 |
| access.log の場合のみ、NGINX エラー ログなどの完全バージョンと比較して複数の一致する形式を破棄し、単一の一致するPipelineを使用します (付録 2 を参照)。 | 16秒91 |
| 最適化された単一の一致するPipelineを使用して、パフォーマンスを大量に消費するパターンを置き換えます (付録 3 を参照) | 4秒40 |
Info
Pipelineの時間がかかる間、CPU の単一コアが全負荷で実行され、使用率は約 100% でした。 100,000 ログの処理が完了すると、CPU が低下しました。テスト中、メモリ消費量は安定しており、使用量の明らかな増加はありませんでした。消費時間は DataKit プログラムによって計算されており、環境によっては差異が生じる可能性があります。
比較¶
Fluentd を使用して同じ 100,000 行のログを収集すると、CPU 使用率は 3 秒以内に 43% から 77% に上昇し、その後低下しました。この時点で処理が終了していることが予想されます。
Fluentd はメタデータのキャッシュ機構を備えており、結果をバッチで出力するため、どのくらいの時間がかかるかを正確に計算することはできません。
Fluentd のPipeline マッチング モードは単一であり、同じデータ ソースからの複数形式のPipelineはありません (たとえば、nginx はアクセス ログのみをサポートし、エラー ログはサポートしません)。
結論¶
DataKit のログ収集、Pipeline シングルマッチングモードでは、Fluentd と比べて処理時間が 30% 程度異なります。
ただし、完全に一致するPipelineの完全バージョンを使用すると、消費時間は大幅に増加します。
付録(Pipeline)¶
完全版・すべてのパターンを照合する Pipeline¶
add_pattern("date2", "%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}")
# access log
grok(_, "%{IPORHOST:client_ip} %{NOTSPACE:http_ident} %{NOTSPACE:http_auth} \\[%{HTTPDATE:time}\\] \"%{DATA:http_method} %{GREEDYDATA:http_url} HTTP/%{NUMBER:http_version}\" %{INT:status_code} %{INT:bytes}")
# access log
add_pattern("access_common", "%{IPORHOST:client_ip} %{NOTSPACE:http_ident} %{NOTSPACE:http_auth} \\[%{HTTPDATE:time}\\] \"%{DATA:http_method} %{GREEDYDATA:http_url} HTTP/%{NUMBER:http_version}\" %{INT:status_code} %{INT:bytes}")
grok(_, '%{access_common} "%{NOTSPACE:referrer}" "%{GREEDYDATA:agent}')
user_agent(agent)
# error log
grok(_, "%{date2:time} \\[%{LOGLEVEL:status}\\] %{GREEDYDATA:msg}, client: %{IPORHOST:client_ip}, server: %{IPORHOST:server}, request: \"%{DATA:http_method} %{GREEDYDATA:http_url} HTTP/%{NUMBER:http_version}\", (upstream: \"%{GREEDYDATA:upstream}\", )?host: \"%{IPORHOST:ip_or_host}\"")
grok(_, "%{date2:time} \\[%{LOGLEVEL:status}\\] %{GREEDYDATA:msg}, client: %{IPORHOST:client_ip}, server: %{IPORHOST:server}, request: \"%{GREEDYDATA:http_method} %{GREEDYDATA:http_url} HTTP/%{NUMBER:http_version}\", host: \"%{IPORHOST:ip_or_host}\"")
grok(_,"%{date2:time} \\[%{LOGLEVEL:status}\\] %{GREEDYDATA:msg}")
group_in(status, ["warn", "notice"], "warning")
group_in(status, ["error", "crit", "alert", "emerg"], "error")
cast(status_code, "int")
cast(bytes, "int")
group_between(status_code, [200,299], "OK", status)
group_between(status_code, [300,399], "notice", status)
group_between(status_code, [400,499], "warning", status)
group_between(status_code, [500,599], "error", status)
nullif(http_ident, "-")
nullif(http_auth, "-")
nullif(upstream, "")
default_time(time)
単一パターンを照合する Pipeline¶
# access log
grok(_, "%{IPORHOST:client_ip} %{NOTSPACE:http_ident} %{NOTSPACE:http_auth} \\[%{HTTPDATE:time}\\] \"%{DATA:http_method} %{GREEDYDATA:http_url} HTTP/%{NUMBER:http_version}\" %{INT:status_code} %{INT:bytes}")
cast(status_code, "int")
cast(bytes, "int")
default_time(time)
最適化した単一パターン照合 Pipeline¶
この例では、パフォーマンスを大量に消費する IPORHOST が NOTSPACE に変更されます。