世界一便利なログ閲覧インターフェース*を開発中

世界一便利なログ閲覧インターフェース*を開発中 Web インターフェイスを使用してログを表示したことがある場合は、これらのインターフェイスが一般的に扱いにくく、(多くの場合) 利便性や応答性があまり良くないことに気づいたでしょう。 慣れることができるものもあれば、まったくひどいものもありますが、すべての問題の原因は、ログを表示するタスクへのアプローチが間違っていることにあるように思えます。つまり、CLI (コマンド ライン インターフェイス) を使用する Web インターフェイスを作成しようとしているからです。より良く機能します。 私は個人的に、tail、grep、awk などを使用することに非常に慣れています。そのため、ログを操作するための理想的なインターフェイスは、tail と grep に似たものですが、多くのサーバーからのログを読み取るためにも使用できるものです。 それはもちろん、ClickHouse から読むことです。

※habraユーザーの個人的な意見による ユーロック

ログクライの紹介

インターフェイスの名前は思いつきませんでした。正直に言うと、インターフェイスはプロトタイプの形で存在していますが、すぐにソース コードを見たい場合は、次のリンクを参照してください。 https://github.com/YuriyNasretdinov/logscli (選択された Go コードの 350 行)。

機能

私の目標は、tail/grep に慣れている人にとって馴染みのあるインターフェースを作成することでした。つまり、次のことをサポートすることでした。

  1. フィルタリングせずにすべてのログを表示します。
  2. 固定部分文字列を含む行を残します (フラグ -F у grep).
  3. 正規表現に一致する行を残します (フラグ -E у grep).
  4. デフォルトでは、通常は最新のログが最初に対象となるため、表示は新しい順に行われます。
  5. 各行の横にコンテキストを表示します (オプション -A, -B и -C у grep、一致する各行の前、後、および周囲にそれぞれ N 行を出力します)。
  6. フィルタリングの有無にかかわらず、受信ログをリアルタイムで表示します (基本的に tail -f | grep).
  7. インターフェースは以下と互換性がある必要があります less, head, tail その他 - デフォルトでは、結果は数の制限なしで返される必要があります。 ユーザーが受信したいと考えている限り、行はストリームとして出力されます。 信号 SIGPIPE 彼らと同じように、ログストリーミングをサイレントに中断する必要があります tail, grep およびその他の UNIX ユーティリティ。

具現化

ClickHouse にログを配信する方法をすでに何らかの方法で知っていると仮定します。 そうでない場合は、試してみることをお勧めします LSD и 子猫小屋ログ配信に関するこの記事.

まず、基本的なスキームを決定する必要があります。 通常、時間順にソートされたログを受け取りたいので、そのように保存するのが論理的だと思われます。 多くのログ カテゴリがあり、それらがすべて同じタイプである場合は、ログ カテゴリを主キーの最初の列として作成できます。これにより、複数のテーブルではなく 1 つのテーブルを作成できるようになり、次のような場合に大きな利点になります。 ClickHouse への挿入 (ハードドライブを備えたサーバーでは、データの挿入は XNUMX 秒あたり最大 XNUMX 回までにすることをお勧めします) サーバー全体に対して).

つまり、およそ次のようなテーブル スキームが必要になります。

CREATE TABLE logs(
    category LowCardinality(String), -- категория логов (опционально)
    time DateTime, -- время события
    millis UInt16, -- миллисекунды (могут быть и микросекунды, и т.д.): рекомендуется хранить, если событий много, чтобы было легче различать события между собой
    ..., -- ваши собственные поля, например имя сервера, уровень логирования, и так далее
    message String -- текст сообщения
) ENGINE=MergeTree()
ORDER BY (category, time, millis)

残念ながら、取得してダウンロードできる現実的なログを含むオープンソースはすぐには見つかりませんでした。そのため、代わりにこれを例として取り上げました。 2015 年以前の Amazon の製品のレビュー。 もちろん、その構造はテキスト ログの構造とまったく同じではありませんが、説明のためにこれは重要ではありません。

Amazon レビューを ClickHouse にアップロードする手順

テーブルを作成しましょう:

CREATE TABLE amazon(
   review_date Date,
   time DateTime DEFAULT toDateTime(toUInt32(review_date) * 86400 + rand() % 86400),
   millis UInt16 DEFAULT rand() % 1000,
   marketplace LowCardinality(String),
   customer_id Int64,
   review_id String,
   product_id LowCardinality(String),
   product_parent Int64,
   product_title String,
   product_category LowCardinality(String),
   star_rating UInt8,
   helpful_votes UInt32,
   total_votes UInt32,
   vine FixedString(1),
   verified_purchase FixedString(1),
   review_headline String,
   review_body String
)
ENGINE=MergeTree()
ORDER BY (time, millis)
SETTINGS index_granularity=8192

Amazon データセットにはレビューの日付のみがあり、正確な時間がないため、このデータをランドンで埋めてみましょう。

10 GB の RAM に収まらないかなり大きなデータ セットを取得するために、すべての tsv ファイルをダウンロードして最初の 20 ~ 16 に制限する必要はありません。 TSV ファイルをアップロードするには、次のコマンドを使用しました。

for i in *.tsv; do
    echo $i;
    tail -n +2 $i | pv |
    clickhouse-client --input_format_allow_errors_ratio 0.5 --query='INSERT INTO amazon(marketplace,customer_id,review_id,product_id,product_parent,product_title,product_category,star_rating,helpful_votes,total_votes,vine,verified_purchase,review_headline,review_body,review_date) FORMAT TabSeparated'
done

Google Cloud の 1000 GB の標準永続ディスク (HDD) 上でアップロード速度は 75 コアで約 ~ 4 MB/秒でした。

  • 私は Google で働いていることをお断りしておく必要がありますが、私は個人アカウントを使用しており、この記事は会社での私の仕事とは何の関係もありません

手元にあるのはこれだけなので、この特定のデータセットを使用してすべてのイラストを作成します。

データスキャンの進行状況を表示する

ClickHouse では、ログのあるテーブルに対してフル スキャンを使用します。この操作にはかなりの時間がかかり、一致するものがほとんど見つからない場合は長期間結果が得られない可能性があるため、結果を含む最初の行が受信されるまでクエリが進行します。 これを行うには、HTTP ヘッダーで進行状況を送信できるようにする HTTP インターフェースのパラメーターがあります。 send_progress_in_http_headers=1。 残念ながら、標準の Go ライブラリは受信時にヘッダーを読み取ることができませんが、HTTP 1.0 インターフェイス (1.1 と混同しないでください!) は ClickHouse によってサポートされているため、ClickHouse への生の TCP 接続を開いて送信することができます。 GET /?query=... HTTP/1.0nn エスケープや暗号化を行わずに応答ヘッダーと本文を受信するため、この場合は標準ライブラリを使用する必要さえありません。

ClickHouse からのストリーミング ログ

ClickHouse は比較的長い間 (2019 年以降?) ORDER BY を使用したクエリの最適化を行ってきたため、次のようなクエリは

SELECT time, millis, message
FROM logs
WHERE message LIKE '%something%'
ORDER BY time DESC, millis DESC

スキャンの終了を待たずに、メッセージ内に部分文字列「something」を含む行を即座に返し始めます。

また、ClickHouse への接続が閉じられたときに ClickHouse 自体がリクエストをキャンセルできれば非常に便利ですが、これはデフォルトの動作ではありません。 リクエストの自動キャンセルは、オプションを使用して有効にできます。 cancel_http_readonly_queries_on_client_close=1.

Go での SIGPIPE の正しい処理

たとえば、次のコマンドを実行すると、 some_cmd | head -n 10、コマンドの正確な方法 some_cmd 次の場合に実行を停止します head 10行引いた? 答えは簡単です:いつ head 終了するとパイプが閉じ、some_cmd コマンドの標準出力が条件付きで「どこにもない」ことを指し始めます。 いつ some_cmd 閉じたパイプに書き込もうとしますが、 SIGPIPE シグナルを受信すると、デフォルトでプログラムがサイレントに終了します。.

Go ではこれもデフォルトで発生しますが、SIGPIPE シグナル ハンドラーは最後に「signal: SIGPIPE」または同様のメッセージも出力します。このメッセージをクリアするには、SIGPIPE を自分で希望どおりに、つまり黙って処理するだけで済みます。出口:

ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGPIPE)
go func() {
    <-ch
    os.Exit(0)
}()

メッセージコンテキストを表示

多くの場合、何らかのエラーが発生したコンテキスト (たとえば、どのリクエストがパニックを引き起こしたか、クラッシュ前にどのような関連問題が発生していたかなど) を確認したいことがあります。 grep これは、-A、-B、および -C オプションを使用して実行され、それぞれメッセージの後、前、および前後の指定された行数を表示します。

残念ながら、ClickHouse で同じことを行う簡単な方法が見つからなかったため、コンテキストを表示するには、このような追加のリクエストが結果の各行に送信されます (詳細は並べ替えとコンテキストが前に表示されるかどうかによって異なります)またはそれ以降):

SELECT time,millis,review_body FROM amazon
WHERE (time = 'ВРЕМЯ_СОБЫТИЯ' AND millis < МИЛЛИСЕКУНДЫ_СОБЫТИЯ) OR (time < 'ВРЕМЯ_СОБЫТИЯ')
ORDER BY time DESC, millis DESC
LIMIT КОЛИЧЕСТВО_СТРОК_КОНТЕКСТА
SETTINGS max_threads=1

ClickHouse が対応する行を返した直後にリクエストが送信されるため、リクエストはキャッシュに残り、一般にリクエストは非常に迅速に実行され、CPU を少し消費します (通常、私の仮想マシンではリクエストに約 6 ミリ秒かかります)。

新しいメッセージをリアルタイムで表示する

受信メッセージを (ほぼ) リアルタイムで表示するには、以前に遭遇した最後のタイムスタンプを記憶しながら、数秒に XNUMX 回リクエストを実行するだけです。

コマンド例

一般的な logscli コマンドは実際にはどのようなものですか?

記事の冒頭で説明した Amazon データセットをダウンロードした場合は、次のコマンドを実行できます。

# Показать строки, где встречается слово walmart
$ logscli -F 'walmart' | less

# Показать самые свежие 10 строк, где встречается "terrible"
$ logscli -F terrible -limit 10

# То же самое без -limit:
$ logscli -F terrible | head -n 10

# Показать все строки, подходящие под /times [0-9]/, написанные для vine и у которых высокий рейтинг
$ logscli -E 'times [0-9]' -where="vine='Y' AND star_rating>4" | less

# Показать все строки со словом "panic" и 3 строки контекста вокруг
$ logscli -F 'panic' -C 3 | less

# Непрерывно показывать новые строки со словом "5-star"
$ logscli -F '5-star' -tailf

リファレンス

ユーティリティ コード (ドキュメントなし) は、github で入手できます。 https://github.com/YuriyNasretdinov/logscli。 ClickHouse に基づいてログを表示するためのコンソール インターフェイスに関する私のアイデアについてご意見をいただければ幸いです。

出所: habr.com

コメントを追加します