メインコンテンツまでスキップ
メインコンテンツまでスキップ

ClickHouseとVectorの統合

Community Maintained

リアルタイムでログを分析できることは、生産アプリケーションにとって非常に重要です。ClickHouseがログデータの保存と分析に優れているかどうか、考えたことはありますか? ELKからClickHouseへのログインフラの移行に関するUberの経験をチェックしてみてください。

このガイドでは、人気のデータパイプラインVectorを使用して、Nginxのログファイルをテールし、それをClickHouseに送信する方法を示します。以下のステップは、任意の種類のログファイルをテールする際にも似ています。すでにClickHouseが稼働しており、Vectorがインストールされていると仮定します(まだ起動する必要はありません)。

1. データベースとテーブルの作成

ログイベントを保存するためのテーブルを定義します:

  1. 新しいデータベース nginxdb から始めます:
CREATE DATABASE IF NOT EXISTS nginxdb
  1. 初めは、全ログイベントを単一の文字列として挿入します。明らかにこれはログデータの分析に適した形式ではありませんが、マテリアライズドビューを使用してその部分を後で解決します。
CREATE TABLE IF NOT EXISTS  nginxdb.access_logs (
    message String
)
ENGINE = MergeTree()
ORDER BY tuple()
注記

現時点では主キーは本当に必要ありませんので、ORDER BYは**tuple()**に設定されています。

2. Nginxの構成

Nginxの詳細をあまり説明するつもりはありませんが、すべての詳細を隠すつもりもありませんので、このステップではNginxのログ設定を行うために十分な詳細を提供します。

  1. 次の access_log プロパティは、combined形式でログを /var/log/nginx/my_access.log に送信します。この値は、nginx.conf ファイルの http セクションに入ります:
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    access_log  /var/log/nginx/my_access.log combined;
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}
  1. nginx.conf を変更した場合は、必ずNginxを再起動してください。

  2. ウェブサーバーのページを訪問して、アクセスログにいくつかのログイベントを生成します。combined形式のログは次のような形式を持っています:

192.168.208.1 - - [12/Oct/2021:03:31:44 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
192.168.208.1 - - [12/Oct/2021:03:31:44 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
192.168.208.1 - - [12/Oct/2021:03:31:49 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"

3. Vectorの構成

Vectorは、ログ、メトリクス、およびトレース(ソースと呼ばれます)を収集、変換し、多くの異なるベンダー(シンクと呼ばれます)にルーティングします。ClickHouseとの標準的な互換性があります。ソースとシンクは、vector.tomlという設定ファイルで定義します。

  1. 次の vector.toml は、my_access.log の末尾をテールする fileタイプのソースを定義し、上記で定義した access_logs テーブルを シンクとして定義しています:
[sources.nginx_logs]
type = "file"
include = [ "/var/log/nginx/my_access.log" ]
read_from = "end"

[sinks.clickhouse]
type = "clickhouse"
inputs = ["nginx_logs"]
endpoint = "http://clickhouse-server:8123"
database = "nginxdb"
table = "access_logs"
skip_unknown_fields = true
  1. 上記の設定を使用してVectorを起動します。ソースとシンクの定義についてはVectorのドキュメントを参照してください。

  2. アクセスログがClickHouseに挿入されているかどうかを確認します。次のクエリを実行すると、テーブルにアクセスログが表示されるはずです:

SELECT * FROM nginxdb.access_logs
テーブル形式でClickHouseのログを表示

4. ログの解析

ClickHouseにログがあるのは素晴らしいことですが、各イベントを単一の文字列として保存すると、あまりデータ分析ができません。マテリアライズドビューを使用してログイベントを解析する方法を見てみましょう。

  1. マテリアライズドビュー(MVの略)は、既存のテーブルに基づく新しいテーブルであり、既存のテーブルに挿入が行われると、新しいデータもマテリアライズドビューに追加されます。access_logsにログイベントの解析された表現を含むMVを定義する方法を見てみましょう、言い換えれば:
192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"

ClickHouseには文字列を解析するためのさまざまな関数がありますが、初めに見てみるべきはsplitByWhitespaceです。これは、空白で文字列を解析し、各トークンを配列として返します。デモンストレーションのために、次のコマンドを実行します:

SELECT splitByWhitespace('192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"')

返答は私たちが欲しいものにかなり近いことに気付いてください!いくつかの文字列には余分な文字があり、ユーザーエージェント(ブラウザの詳細)は解析する必要がありませんでしたが、次のステップでそれを解決します:

["192.168.208.1","-","-","[12/Oct/2021:15:32:43","+0000]","\"GET","/","HTTP/1.1\"","304","0","\"-\"","\"Mozilla/5.0","(Macintosh;","Intel","Mac","OS","X","10_15_7)","AppleWebKit/537.36","(KHTML,","like","Gecko)","Chrome/93.0.4577.63","Safari/537.36\""]
  1. splitByWhitespaceに似て、splitByRegexp関数は正規表現に基づいて文字列を配列に分割します。次のコマンドを実行すると、2つの文字列が返されます。
SELECT splitByRegexp('\S \d+ "([^"]*)"', '192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"')

返された2番目の文字列は、ログから正常に解析されたユーザーエージェントです:

["192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] \"GET / HTTP/1.1\" 30"," \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36\""]
  1. 最終的なCREATE MATERIALIZED VIEWコマンドを確認する前に、データをクリーンアップするために使用されるいくつかの関数を見てみましょう。たとえば、RequestMethod"GET という不要な二重引用符を持っています。次の trim 関数を実行すると、二重引用符を削除できます:
SELECT trim(LEADING '"' FROM '"GET')
  1. 時間文字列には先頭に角括弧があり、ClickHouseが日付に解析できる形式でもありません。しかし、区切り文字をコロン(:)からカンマ(,)に変更すれば、解析がうまくいきます:
SELECT parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM '[12/Oct/2021:15:32:43'), ':', ' '))
  1. マテリアライズドビューを定義する準備が整いました。私たちの定義には POPULATE が含まれており、これにより access_logs の既存の行がすぐに処理されて挿入されます。次のSQL文を実行します:
CREATE MATERIALIZED VIEW nginxdb.access_logs_view
(
    RemoteAddr String,
    Client String,
    RemoteUser String,
    TimeLocal DateTime,
    RequestMethod String,
    Request String,
    HttpVersion String,
    Status Int32,
    BytesSent Int64,
    UserAgent String
)
ENGINE = MergeTree()
ORDER BY RemoteAddr
POPULATE AS
WITH
    splitByWhitespace(message) as split,
    splitByRegexp('\S \d+ "([^"]*)"', message) as referer
SELECT
    split[1] AS RemoteAddr,
    split[2] AS Client,
    split[3] AS RemoteUser,
    parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM split[4]), ':', ' ')) AS TimeLocal,
    trim(LEADING '"' FROM split[6]) AS RequestMethod,
    split[7] AS Request,
    trim(TRAILING '"' FROM split[8]) AS HttpVersion,
    split[9] AS Status,
    split[10] AS BytesSent,
    trim(BOTH '"' from referer[2]) AS UserAgent
FROM
    (SELECT message FROM nginxdb.access_logs)
  1. 正常に機能したことを確認します。アクセスログがきれいにカラムに解析されて表示されるはずです:
SELECT * FROM nginxdb.access_logs_view
解析されたClickHouseのログをテーブル形式で表示
注記

上記のレッスンではデータを2つのテーブルに保存しましたが、最初の nginxdb.access_logs テーブルを Null テーブルエンジンを使用するように変更することもできます - 解析されたデータは依然として nginxdb.access_logs_view テーブルに入りますが、生のデータはテーブルに保存されません。

まとめ: シンプルなインストールと迅速な設定を必要とするVectorを使用することで、NginxサーバーからClickHouseのテーブルにログを送信できます。巧妙なマテリアライズドビューを使用することで、これらのログをカラムに解析し、より簡単に分析できるようになります。