メインコンテンツへスキップ
メインコンテンツへスキップ

データ収集のための OpenTelemetry の統合

あらゆるオブザーバビリティソリューションには、ログおよびトレースを収集してエクスポートする手段が必要です。この目的のために、ClickHouse は OpenTelemetry (OTel) プロジェクト を推奨しています。

「OpenTelemetry は、トレース、メトリクス、ログなどのテレメトリデータを作成および管理するために設計されたオブザーバビリティフレームワーク兼ツールキットです。」

ClickHouse や Prometheus とは異なり、OpenTelemetry はオブザーバビリティのバックエンドではなく、テレメトリデータの生成、収集、管理、およびエクスポートに特化しています。OpenTelemetry の当初の目的は、言語固有の SDKS を用いてアプリケーションやシステムを容易にインスツルメンテーションできるようにすることでしたが、現在では OpenTelemetry collector を通じたログ収集も含むように拡張されています。OpenTelemetry collector は、テレメトリデータを受信、処理、およびエクスポートするエージェントまたはプロキシです。

ClickHouse 関連コンポーネント

OpenTelemetry は複数のコンポーネントで構成されています。データおよび API 仕様、標準化されたプロトコル、フィールドやカラムの命名規則を提供するだけでなく、OTel は ClickHouse を用いてオブザーバビリティソリューションを構築するうえで不可欠な 2 つの機能を提供します。

  • OpenTelemetry Collector は、テレメトリーデータを受信・処理・エクスポートするプロキシです。ClickHouse を基盤とするソリューションでは、このコンポーネントを、バッチ処理および挿入前のログ収集とイベント処理の両方に利用します。
  • Language SDKs は、仕様・API・テレメトリーデータのエクスポートを実装します。これらの SDK により、アプリケーションコード内でトレースが正しく記録され、構成要素となる span が生成され、メタデータを通じてサービス間でコンテキストが伝播されます。これにより分散トレースが形成され、span を相関付けられるようになります。さらに、これらの SDK は、一般的なライブラリやフレームワークを自動的に組み込むエコシステムによって補完されているため、ユーザーはコードを変更する必要がなく、そのまま利用可能なインスツルメンテーションを得られます。

ClickHouse を基盤としたオブザーバビリティソリューションでは、これら 2 つのツールをいずれも活用します。

ディストリビューション

OpenTelemetry Collector には複数のディストリビューションがあります。ClickHouse ソリューションに必要となる filelog receiver と ClickHouse exporter は、OpenTelemetry Collector Contrib Distro にのみ含まれています。

このディストリビューションには多くのコンポーネントが含まれており、さまざまな構成を試すことができます。ただし本番環境で実行する場合は、その環境に必要なコンポーネントのみに Collector を限定することを推奨します。理由としては次のようなものがあります:

  • Collector のサイズを削減し、Collector のデプロイ時間を短縮できる
  • 利用可能な攻撃対象領域を減らすことで、Collector のセキュリティを向上できる

カスタム Collector は、OpenTelemetry Collector Builder を使用してビルドできます。

OTel を使ったデータ取り込み

コレクターのデプロイメントロール

ログを収集して ClickHouse に挿入するためには、OpenTelemetry Collector の利用を推奨します。OpenTelemetry Collector は、主に次の 2 つのロールでデプロイできます。

  • Agent - Agent インスタンスは、エッジ(例: サーバー上や Kubernetes ノード上)でデータを収集したり、OpenTelemetry SDK で計装されたアプリケーションからイベントを直接受信します。後者の場合、Agent インスタンスはアプリケーションと同一プロセス内、またはアプリケーションと同じホスト上(sidecar や デーモンセット など)で動作します。Agent は、収集したデータを直接 ClickHouse に送信することも、ゲートウェイインスタンスに送信することもできます。前者の場合、これは Agent deployment pattern と呼ばれます。
  • Gateway - Gateway インスタンスは、スタンドアロンのサービス(たとえば Kubernetes のデプロイメント)として、通常はクラスタ単位、データセンター単位、またはリージョン単位で提供されます。これらは、単一の OTLP エンドポイント経由で、アプリケーション(または Agent として動作する他のコレクター)からイベントを受信します。通常、複数の Gateway インスタンスがデプロイされ、それらの間で負荷を分散するために既存のロードバランサーが利用されます。すべての Agent とアプリケーションがこの単一エンドポイントにシグナルを送信する場合、これは Gateway deployment pattern と呼ばれることがよくあります。

以下では、シンプルな Agent ロールのコレクターがイベントを直接 ClickHouse に送信する構成を前提とします。ゲートウェイの利用方法とそれが適用されるシナリオについては、Scaling with Gateways を参照してください。

ログの収集

Collector を使用する主な利点は、サービス側がデータをすばやくオフロードでき、その後のリトライ、バッチ処理、暗号化、さらには機密データのフィルタリングといった追加処理を Collector 側に任せられる点です。

Collector では、3 つの主要な処理ステージを receiverprocessorexporter という用語で表現します。Receiver はデータ収集のために使用され、pull 型と push 型のいずれにも対応します。Processor はメッセージの変換および付加情報の付与(enrichment)を行う機能を提供します。Exporter はデータを下流のサービスへ送信する役割を担います。この下流サービスは理論上は別の Collector でも構いませんが、以下の説明では、すべてのデータが直接 ClickHouse に送信されることを前提とします。

ログの収集

ユーザーは、すべての receiver、processor、exporter について一通り理解しておくことを推奨します。

Collector はログ収集のために、主に 2 種類の receiver を提供します。

OTLP 経由 - この場合、ログは OpenTelemetry SDK から OTLP プロトコル経由で Collector に直接(push で)送信されます。OpenTelemetry demo はこの方式を採用しており、各言語の OTLP exporter はローカルの Collector エンドポイントを前提としています。この場合、Collector 側では OTLP receiver を有効にするよう設定しておく必要があります(上記 デモの設定例 を参照してください)。この方式の利点は、ログデータに自動的に Trace ID が含まれるため、特定のログに対応するトレース、あるいはその逆を後から容易にたどれる点です。

OTLP 経由でのログ収集

この方式では、対象のコードを 利用するプログラミング言語に対応した SDK で計装(インストルメント)する必要があります。

  • Filelog receiver によるスクレイピング - この receiver はディスク上のファイルを tail してログメッセージを生成し、それらを ClickHouse に送信します。この receiver は、複数行メッセージの検出、ログローテーションの取り扱い、再起動に対する堅牢性を高めるためのチェックポイント処理、構造の抽出といった複雑なタスクに対応します。さらに、この receiver は Docker および Kubernetes コンテナのログを tail することもでき、Helm チャートとしてデプロイでき、これらのログから構造を抽出 し、ポッドの詳細を付加してログを拡充できます。
Filelog receiver

多くのデプロイメントでは、上記の receiver を組み合わせて使用します。ユーザーには、collector のドキュメント を読み、基本概念に加えて 設定構造インストール方法 に慣れておくことをお勧めします。

注記
Tip: otelbin.io

otelbin.io は設定の検証と可視化に役立ちます。

構造化ログと非構造化ログ

ログには、構造化されたものと非構造化のものがあります。

構造化ログでは JSON などのデータ形式を用いて、HTTP コードや送信元 IP アドレスといったメタデータフィールドを定義します。

{
    "remote_addr":"54.36.149.41",
    "remote_user":"-","run_time":"0","time_local":"2019-01-22 00:26:14.000","request_type":"GET",
    "request_path":"\/filter\/27|13 ,27|  5 ,p53","request_protocol":"HTTP\/1.1",
    "status":"200",
    "size":"30577",
    "referer":"-",
    "user_agent":"Mozilla\/5.0 (compatible; AhrefsBot\/6.1; +http:\/\/ahrefs.com\/robot\/)"
}

非構造化ログは、多くの場合、正規表現パターンで抽出可能なある程度の構造を持ってはいますが、ログはあくまで文字列として表現されます。

54.36.149.41 - - [22/Jan/2019:03:56:14 +0330] "GET
/filter/27|13%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,27|%DA%A9%D9%85%D8%AA%D8%B1%20%D8%A7%D8%B2%205%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,p53 HTTP/1.1" 200 30577 "-" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" "-"

可能な限り構造化ログを採用し、JSON(ndjson など)形式でログを出力することを推奨します。これにより、後続のログ処理が簡素化されます。具体的には、Collector processors を使用して ClickHouse に送信する前、または insert 時に materialized view を用いて処理することが容易になります。構造化ログを使用することで、後段の処理に必要なリソースを最終的に削減でき、ClickHouse ソリューションで必要となる CPU も抑制できます。

本節の例として、構造化(JSON形式)および非構造化の2種類のログデータセットを用意しています。いずれも約 1,000 万行で、以下のリンクから取得できます。

以下の例では構造化されたデータセットを使用します。以降の例を再現できるよう、このファイルをダウンロードして解凍しておいてください。

次は、これらのファイルをディスクから読み取り、filelog receiver を使用して処理し、結果のメッセージを stdout に出力する、OTel collector のシンプルな構成例です。ログが構造化されているため、json_parser operator を使用します。access-structured.log ファイルへのパスは適宜変更してください。

解析には ClickHouse の利用も検討

以下の例では、ログからタイムスタンプを抽出します。これは、ログの 1 行全体を JSON 文字列に変換して結果を LogAttributes に格納する json_parser operator の使用を必要とします。この処理は計算コストが高くなりますが、ClickHouse でより効率的に実行できます - Extracting structure with SQL。同等の非構造化ログの例として、regex_parser を使用して同様の処理を行うものをこちらで参照できます。

config-structured-logs.yaml

receivers:
  filelog:
    include:
      - /opt/data/logs/access-structured.log
    start_at: beginning
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time_local
          layout: '%Y-%m-%d %H:%M:%S'
processors:
  batch:
    timeout: 5s
    send_batch_size: 1
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch]
      exporters: [logging]

公式手順に従って、ローカル環境に collector をインストールできます。重要な点として、手順の中で contrib distributionfilelog receiver を含んでいます)を使用するようにしてください。例えば、otelcol_0.102.1_darwin_arm64.tar.gz の代わりに otelcol-contrib_0.102.1_darwin_arm64.tar.gz をダウンロードします。リリースはこちらから確認できます。

インストールが完了したら、OTel Collector は次のコマンドで実行できます。

./otelcol-contrib --config config-logs.yaml

構造化ログを使用している場合、出力されるメッセージは次の形式になります:

LogRecord #98
ObservedTimestamp: 2024-06-19 13:21:16.414259 +0000 UTC
Timestamp: 2019-01-22 01:12:53 +0000 UTC
SeverityText:
SeverityNumber: Unspecified(0)
Body: Str({"remote_addr":"66.249.66.195","remote_user":"-","run_time":"0","time_local":"2019-01-22 01:12:53.000","request_type":"GET","request_path":"\/product\/7564","request_protocol":"HTTP\/1.1","status":"301","size":"178","referer":"-","user_agent":"Mozilla\/5.0 (Linux; Android 6.0.1; Nexus 5X Build\/MMB29P) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/41.0.2272.96 Mobile Safari\/537.36 (compatible; Googlebot\/2.1; +http:\/\/www.google.com\/bot.html)"})
Attributes:
        -> remote_user: Str(-)
        -> request_protocol: Str(HTTP/1.1)
        -> time_local: Str(2019-01-22 01:12:53.000)
        -> user_agent: Str(Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html))
        -> log.file.name: Str(access.log)
        -> status: Str(301)
        -> size: Str(178)
        -> referer: Str(-)
        -> remote_addr: Str(66.249.66.195)
        -> request_type: Str(GET)
        -> request_path: Str(/product/7564)
        -> run_time: Str(0)
Trace ID:
Span ID:
Flags: 0

上記は、OTel collector によって出力された 1 つのログメッセージを表しています。同じメッセージを、後続のセクションで ClickHouse に取り込みます。

ログメッセージの完全なスキーマと、他の receiver を使用している場合に存在しうる追加カラムは こちら で管理されています。このスキーマには必ず目を通し、内容を理解しておくことを強く推奨します。

ここで重要なのは、ログ行自体は Body フィールド内の文字列として保持されている一方で、json_parser によって JSON が自動的に抽出され、Attributes フィールドに格納されている点です。同じ operator を使用して、タイムスタンプも適切な Timestamp カラムに抽出しています。OTel を用いたログ処理の推奨事項については Processing を参照してください。

Operators

Operators はログ処理の最も基本的な単位です。各 Operator は、ファイルから行を読み取る、あるフィールドから JSON をパースするなど、単一の責務を果たします。Operators は、その後パイプライン内で連結され、目的とする結果を得るために利用されます。

上記のメッセージには TraceIDSpanID フィールドが存在しません。これらが存在する場合、たとえばユーザーが 分散トレーシング を実装しているケースでは、先ほどと同様の手法を用いて JSON から抽出することができます。

ローカルまたは Kubernetes のログファイルを収集する必要があるユーザーは、filelog receiver で利用可能な設定オプション、および offset複数行ログのパース方法 について理解しておくことを推奨します。

Kubernetes ログの収集

Kubernetes ログの収集には、OpenTelemetry documentation guide を参照することを推奨します。Kubernetes Attributes Processor は、ポッドのメタデータでログとメトリクスを拡張するために推奨されます。これにより、ラベルなどの動的メタデータが ResourceAttributes カラムに保存される可能性があります。ClickHouse では現在、このカラムに Map(String, String) 型を使用しています。この型の扱いや最適化の詳細については、Using Maps および Extracting from maps を参照してください。

トレースの収集

コードを計装してトレースを収集したいユーザーは、公式の OTel ドキュメント を参照してください。

ClickHouse にイベントを送信するには、適切な receiver を介して OTLP プロトコル経由でトレースイベントを受信する OTel collector をデプロイする必要があります。OpenTelemetry のデモでは、サポートされている各言語の計装例 と、イベントを collector に送信する方法を示しています。イベントを stdout に出力する collector 設定の一例を以下に示します。

トレースは OTLP 経由で受信する必要があるため、トレースデータを生成するために telemetrygen ツールを使用します。インストール手順はこちらを参照してください。

次の設定では、OTLP レシーバーでトレースイベントを受信し、それらを標準出力 (stdout) に送信します。

config-traces.xml

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
processors:
  batch:
    timeout: 1s
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [logging]

この構成は次のコマンドで実行します:

./otelcol-contrib --config config-traces.yaml

telemetrygen を使用してトレースイベントをコレクターに送信します:

$GOBIN/telemetrygen traces --otlp-insecure --traces 300

これにより、次の例に示すようなトレースメッセージが stdout に出力されます。

Span #86
        Trace ID        : 1bb5cdd2c9df5f0da320ca22045c60d9
        Parent ID       : ce129e5c2dd51378
        ID              : fbb14077b5e149a0
        Name            : okey-dokey-0
        Kind            : Server
        Start time      : 2024-06-19 18:03:41.603868 +0000 UTC
        End time        : 2024-06-19 18:03:41.603991 +0000 UTC
        Status code     : Unset
        Status message :
Attributes:
        -> net.peer.ip: Str(1.2.3.4)
        -> peer.service: Str(telemetrygen-client)

上記は、OTel collector が生成した単一のトレースメッセージです。同様のメッセージを、後続のセクションで ClickHouse に取り込みます。

トレースメッセージの完全なスキーマはこちらで公開されています。このスキーマには事前に目を通しておくことを強く推奨します。

Processing - filtering, transforming and enriching

前の例でログイベントのタイムスタンプを設定したように、イベントメッセージをフィルタリング・変換し、付加情報を与えてエンリッチしたくなる場面は必ず発生します。これは、OpenTelemetry が持つ複数の機能を利用することで実現できます。

  • Processors - Processors は、receivers によって収集されたデータを exporters に送信する前に変更または変換 します。Processors は collector の設定ファイル内の processors セクションで定義された順序で適用されます。必須ではありませんが、最小限のセットが一般的に推奨されています。ClickHouse と組み合わせて OTel collector を使用する場合、processors は次のようなものに限定することを推奨します。

    • memory_limiter は、collector におけるメモリ不足(Out Of Memory)の発生を防ぐために使用されます。推奨値については Estimating Resources を参照してください。
    • コンテキストに基づいてエンリッチメントを行う processor。たとえば Kubernetes Attributes Processor は、k8s メタデータを用いて spans、metrics、logs の resource 属性を自動的に設定できます。例として、イベントにその発生元のポッド ID を付与してエンリッチできます。
    • トレースに対して必要な場合の tail または head サンプリング
    • Basic filtering - 下記の operator では実施できない場合に、不要なイベントをドロップします。
    • Batching - データをバッチ単位で送信できるようにするため、ClickHouse と連携する際には不可欠です。"Exporting to ClickHouse" を参照してください。
  • Operators - Operators は、receiver で利用可能な最も基本的な処理単位を提供します。ここでは Severity や Timestamp といったフィールドを設定できる基本的なパースがサポートされています。JSON および正規表現によるパースに加え、イベントフィルタリングや基本的な変換が可能です。イベントフィルタリングはここで行うことを推奨します。

operators や transform processors を用いた過度なイベント処理は避けることを推奨します。特に JSON パースは、メモリと CPU に大きなオーバーヘッドを招く可能性があります。いくつかの例外を除いて、materialized view とカラムを用いることで、ClickHouse 側で挿入時にすべての処理を実行することが可能です。具体的には、コンテキストに依存するエンリッチメント、たとえば k8s メタデータの付与などが例外です。詳細については Extracting structure with SQL を参照してください。

処理を OTel collector で行う場合、変換処理は gateway インスタンス側で実施し、agent インスタンス側での処理を最小限に抑えることを推奨します。これにより、サーバー上のエッジで稼働する agent が必要とするリソースを可能な限り少なくできます。一般的に、ユーザーは agent ではフィルタリング(不要なネットワーク使用を最小化するため)、タイムスタンプ設定(operators 経由)、およびコンテキストを必要とするエンリッチメントのみを実行しています。たとえば、gateway インスタンスが別の Kubernetes クラスターに存在する場合、k8s によるエンリッチメントは agent 内で行う必要があります。

次の設定は、非構造化ログファイルを収集する例です。ログ行から構造を抽出してイベントをフィルタリングするオペレーター(regex_parser)と、イベントをバッチ処理してメモリ使用量を制限するプロセッサーの利用方法に注目してください。

config-unstructured-logs-with-processor.yaml

receivers:
  filelog:
    include:
      - /opt/data/logs/access-unstructured.log
    start_at: beginning
    operators:
      - type: regex_parser
        regex: '^(?P<ip>[\d.]+)\s+-\s+-\s+\[(?P<timestamp>[^\]]+)\]\s+"(?P<method>[A-Z]+)\s+(?P<url>[^\s]+)\s+HTTP/[^\s]+"\s+(?P<status>\d+)\s+(?P<size>\d+)\s+"(?P<referrer>[^"]*)"\s+"(?P<user_agent>[^"]*)"'
        timestamp:
          parse_from: attributes.timestamp
          layout: '%d/%b/%Y:%H:%M:%S %z'
          #22/Jan/2019:03:56:14 +0330
processors:
  batch:
    timeout: 1s
    send_batch_size: 100
  memory_limiter:
    check_interval: 1s
    limit_mib: 2048
    spike_limit_mib: 256
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch, memory_limiter]
      exporters: [logging]
./otelcol-contrib --config config-unstructured-logs-with-processor.yaml

ClickHouse へのエクスポート

Exporter は、1 つ以上のバックエンドまたは送信先にデータを送信します。Exporter には、pull 型と push 型があります。イベントを ClickHouse に送信するには、push 型の ClickHouse exporter を使用する必要があります。

OpenTelemetry Collector Contrib を使用

ClickHouse exporter は OpenTelemetry Collector Contrib の一部であり、コアディストリビューションには含まれていません。contrib ディストリビューションを使用するか、独自の Collector をビルド することができます。

完全な設定ファイルを以下に示します。

clickhouse-config.yaml

receivers:
  filelog:
    include:
      - /opt/data/logs/access-structured.log
    start_at: beginning
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time_local
          layout: '%Y-%m-%d %H:%M:%S'
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
processors:
  batch:
    timeout: 5s
    send_batch_size: 5000
exporters:
  clickhouse:
    endpoint: tcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1
    # ttl: 72h
    traces_table_name: otel_traces
    logs_table_name: otel_logs
    create_schema: true
    timeout: 5s
    database: default
    sending_queue:
      queue_size: 1000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 300s

service:
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch]
      exporters: [clickhouse]
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [clickhouse]

次の重要な設定項目を確認してください:

  • pipelines - 上記の設定では、pipelines の使用が重要になります。これは一連の receiver、processor、exporter から構成され、ログ用とトレース用にそれぞれ 1 つずつ定義されています。
  • endpoint - ClickHouse との通信は endpoint パラメータで設定します。接続文字列 tcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1 により、通信は TCP 経由で行われます。トラフィック切り替えなどの理由で HTTP を利用したい場合は、この接続文字列をこちらで説明されているとおりに変更してください。ユーザー名とパスワードをこの接続文字列内で指定する方法を含む、完全な接続方法の詳細はこちらで説明されています。

Important: 上記の接続文字列では、圧縮 (lz4) と非同期インサートの両方が有効になっています。常に両方を有効にすることを推奨します。非同期インサートの詳細については Batching を参照してください。圧縮は常に明示的に指定する必要があり、古いバージョンの exporter ではデフォルトでは有効になりません。

  • ttl - この値はデータの保持期間を決定します。詳細は「Managing data」を参照してください。単位付き時間 (例: 72h) で指定する必要があります。以下の例では、データが 2019 年のものであり、挿入すると ClickHouse によって即座に削除されてしまうため、有効期限 (TTL) を無効にしています。
  • traces_table_namelogs_table_name - ログテーブルとトレーステーブルの名前を決定します。
  • create_schema - 起動時にデフォルトスキーマでテーブルを作成するかどうかを決定します。初期セットアップではデフォルトで true です。準備ができたら false に設定し、自分でスキーマを定義してください。
  • database - 対象のデータベース。
  • retry_on_failure - 失敗したバッチを再試行するかどうかを決定する設定です。
  • batch - batch processor はイベントをバッチとして送信します。約 5000 件、タイムアウト 5s 程度の設定を推奨します。これらのいずれかに達した時点で、バッチがフラッシュされ exporter に送信されます。これらの値を小さくすると、データがより早くクエリ可能になる低レイテンシなパイプラインになりますが、その分、多数の接続およびバッチが ClickHouse に送信されます。非同期インサート を使用していない場合、これは ClickHouse でパーツが多すぎる問題を引き起こす可能性があるため推奨されません。逆に、非同期インサートを使用している場合、クエリ可能になるまでのデータ可用性は非同期インサートの設定にも依存しますが、コネクタからのフラッシュ自体はより早く行われます。詳細は Batching を参照してください。
  • sending_queue - 送信キューのサイズを制御します。キュー内の各要素は 1 つのバッチを含みます。たとえば ClickHouse に到達できない状態が継続する一方でイベントが到着し続け、このキューが溢れた場合、バッチは破棄されます。

ユーザーが構造化ログファイルを展開済みで、(デフォルト認証の) ローカルの ClickHouse インスタンス が稼働していることを前提に、この設定は次のコマンドで実行できます。

./otelcol-contrib --config clickhouse-config.yaml

このコレクターにトレースデータを送信するには、telemetrygen ツールを使用して次のコマンドを実行してください。

$GOBIN/telemetrygen traces --otlp-insecure --traces 300

起動後、簡単なクエリを実行してログイベントが取り込まれていることを確認します。

SELECT *
FROM otel_logs
LIMIT 1
FORMAT Vertical

Row 1:
──────
Timestamp:              2019-01-22 06:46:14.000000000
TraceId:
SpanId:
TraceFlags:             0
SeverityText:
SeverityNumber:         0
ServiceName:
Body:                   {"remote_addr":"109.230.70.66","remote_user":"-","run_time":"0","time_local":"2019-01-22 06:46:14.000","request_type":"GET","request_path":"\/image\/61884\/productModel\/150x150","request_protocol":"HTTP\/1.1","status":"200","size":"1684","referer":"https:\/\/www.zanbil.ir\/filter\/p3%2Cb2","user_agent":"Mozilla\/5.0 (Windows NT 6.1; Win64; x64; rv:64.0) Gecko\/20100101 Firefox\/64.0"}
ResourceSchemaUrl:
ResourceAttributes: {}
ScopeSchemaUrl:
ScopeName:
ScopeVersion:
ScopeAttributes:        {}
LogAttributes:          {'referer':'https://www.zanbil.ir/filter/p3%2Cb2','log.file.name':'access-structured.log','run_time':'0','remote_user':'-','request_protocol':'HTTP/1.1','size':'1684','user_agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0','remote_addr':'109.230.70.66','request_path':'/image/61884/productModel/150x150','status':'200','time_local':'2019-01-22 06:46:14.000','request_type':'GET'}

1 row in set. Elapsed: 0.012 sec. Processed 5.04 thousand rows, 4.62 MB (414.14 thousand rows/s., 379.48 MB/s.)
Peak memory usage: 5.41 MiB.

Likewise, for trace events, you can check the `otel_traces` table:

SELECT *
FROM otel_traces
LIMIT 1
FORMAT Vertical

Row 1:
──────
Timestamp:              2024-06-20 11:36:41.181398000
TraceId:                00bba81fbd38a242ebb0c81a8ab85d8f
SpanId:                 beef91a2c8685ace
ParentSpanId:
TraceState:
SpanName:               lets-go
SpanKind:               SPAN_KIND_CLIENT
ServiceName:            telemetrygen
ResourceAttributes: {'service.name':'telemetrygen'}
ScopeName:              telemetrygen
ScopeVersion:
SpanAttributes:         {'peer.service':'telemetrygen-server','net.peer.ip':'1.2.3.4'}
Duration:               123000
StatusCode:             STATUS_CODE_UNSET
StatusMessage:
Events.Timestamp:   []
Events.Name:            []
Events.Attributes:  []
Links.TraceId:          []
Links.SpanId:           []
Links.TraceState:   []
Links.Attributes:   []

すぐに利用できるスキーマ

デフォルトでは、ClickHouse exporter はログとトレースの両方に対して、出力先のログテーブルを作成します。これは create_schema 設定で無効化できます。さらに、ログおよびトレーステーブルの名前は、前述の設定によりデフォルトである otel_logsotel_traces から変更できます。

注記

以下のスキーマでは、有効期限 (TTL) を 72時間に設定しているものと仮定しています。

ログのデフォルトスキーマは以下のとおりです(otelcol-contrib v0.102.1):

CREATE TABLE default.otel_logs
(
    `Timestamp` DateTime64(9) CODEC(Delta(8), ZSTD(1)),
    `TraceId` String CODEC(ZSTD(1)),
    `SpanId` String CODEC(ZSTD(1)),
    `TraceFlags` UInt32 CODEC(ZSTD(1)),
    `SeverityText` LowCardinality(String) CODEC(ZSTD(1)),
    `SeverityNumber` Int32 CODEC(ZSTD(1)),
    `ServiceName` LowCardinality(String) CODEC(ZSTD(1)),
    `Body` String CODEC(ZSTD(1)),
    `ResourceSchemaUrl` String CODEC(ZSTD(1)),
    `ResourceAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
    `ScopeSchemaUrl` String CODEC(ZSTD(1)),
    `ScopeName` String CODEC(ZSTD(1)),
    `ScopeVersion` String CODEC(ZSTD(1)),
    `ScopeAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
    `LogAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
    INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1,
    INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1
)
ENGINE = MergeTree
PARTITION BY toDate(Timestamp)
ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId)
TTL toDateTime(Timestamp) + toIntervalDay(3)
SETTINGS ttl_only_drop_parts = 1

ここで示すカラムは、ログに関するOTelの公式仕様としてこちらに文書化されている内容と対応しています。

このスキーマに関する重要な注意点をいくつか示します:

  • デフォルトでは、テーブルは PARTITION BY toDate(Timestamp) によって日付でパーティション分割されます。これにより、有効期限切れのデータを効率的に削除できます。
  • 有効期限 (TTL) は TTL toDateTime(Timestamp) + toIntervalDay(3) によって設定されており、これはコレクターの設定で指定した値に対応します。ttl_only_drop_parts=1 は、含まれているすべての行が期限切れになったときに、テーブルのパーツ全体のみを削除することを意味します。これは、パーツ内の行だけを削除する場合と比べて、コストの高い削除処理を避けられるため、より効率的です。常にこの設定にすることを推奨します。詳細については、Data management with TTL を参照してください。
  • テーブルは従来型の MergeTree engine を使用しています。これはログやトレースに推奨されるものであり、通常は変更する必要はありません。
  • テーブルは ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId) によって並べ替えられています。これは、ServiceNameSeverityTextTimestampTraceId に対するフィルターにクエリが最適化されることを意味します。リストの先頭にあるカラムほど後ろのカラムよりも高速にフィルタリングされます。例えば、ServiceName でのフィルタリングは TraceId でのフィルタリングよりも有意に高速になります。想定されるアクセスパターンに応じて、この並び順を調整してください。詳細は Choosing a primary key を参照してください。
  • 上記のスキーマでは、カラムに ZSTD(1) が適用されています。これはログに対して最も優れた圧縮を提供します。より良い圧縮を得るために、ZSTD の圧縮レベル(デフォルト値 1 より大きい値)を上げることもできますが、メリットが出るケースは多くありません。この値を上げると、挿入時(圧縮処理中)の CPU オーバーヘッドが増加しますが、伸張(ひいてはクエリ)の性能は概ね同等のままです。詳細はこちらを参照してください。さらに Timestamp に対しては、ディスク上のサイズを削減する目的で追加の delta encoding が適用されています。
  • ResourceAttributesLogAttributesScopeAttributes が map であることに注意してください。これらの違いを理解することは重要です。これらの map へのアクセス方法および内部のキーアクセスを最適化する方法については、"Using maps" を参照してください。
  • ServiceName を LowCardinality にしていることなど、ここに挙がっているほとんどの型は最適化されています。例のログでは JSON である Body は String として保存される点に注意してください。
  • Bloom フィルターが map のキーおよび値、さらに Body カラムに適用されています。これらは、これらのカラムにアクセスするクエリの実行時間を改善することを目的としていますが、通常は必須ではありません。詳細は Secondary/Data skipping indices を参照してください。
CREATE TABLE default.otel_traces
(
        `Timestamp` DateTime64(9) CODEC(Delta(8), ZSTD(1)),
        `TraceId` String CODEC(ZSTD(1)),
        `SpanId` String CODEC(ZSTD(1)),
        `ParentSpanId` String CODEC(ZSTD(1)),
        `TraceState` String CODEC(ZSTD(1)),
        `SpanName` LowCardinality(String) CODEC(ZSTD(1)),
        `SpanKind` LowCardinality(String) CODEC(ZSTD(1)),
        `ServiceName` LowCardinality(String) CODEC(ZSTD(1)),
        `ResourceAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
        `ScopeName` String CODEC(ZSTD(1)),
        `ScopeVersion` String CODEC(ZSTD(1)),
        `SpanAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
        `Duration` Int64 CODEC(ZSTD(1)),
        `StatusCode` LowCardinality(String) CODEC(ZSTD(1)),
        `StatusMessage` String CODEC(ZSTD(1)),
        `Events.Timestamp` Array(DateTime64(9)) CODEC(ZSTD(1)),
        `Events.Name` Array(LowCardinality(String)) CODEC(ZSTD(1)),
        `Events.Attributes` Array(Map(LowCardinality(String), String)) CODEC(ZSTD(1)),
        `Links.TraceId` Array(String) CODEC(ZSTD(1)),
        `Links.SpanId` Array(String) CODEC(ZSTD(1)),
        `Links.TraceState` Array(String) CODEC(ZSTD(1)),
        `Links.Attributes` Array(Map(LowCardinality(String), String)) CODEC(ZSTD(1)),
        INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1,
        INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_duration Duration TYPE minmax GRANULARITY 1
)
ENGINE = MergeTree
PARTITION BY toDate(Timestamp)
ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId)
TTL toDateTime(Timestamp) + toIntervalDay(3)
SETTINGS ttl_only_drop_parts = 1

ここでも、こちら に記載されているトレース向けの OTel 公式仕様で定義されたカラムと整合するようになっています。ここでのスキーマは、上記のログ用スキーマと多くの設定を共有しつつ、Span 固有の Link カラムを追加で使用します。

自動スキーマ作成機能を無効にし、テーブルを手動で作成することを推奨します。これにより、プライマリキーおよびセカンダリキーを変更できるほか、クエリのパフォーマンスを最適化するための追加カラムを導入することも可能になります。詳細については Schema design を参照してください。

挿入の最適化

OTel collector 経由でオブザーバビリティデータを ClickHouse に挿入する際に、高い挿入パフォーマンスを維持しつつ強い一貫性保証を得るには、いくつかの簡単なルールに従ってください。OTel collector を正しく構成すれば、次に挙げるルールには容易に従えるはずです。これにより、ClickHouse を初めて使用するユーザーが直面しがちな一般的な問題を回避するのにも役立ちます。

バッチ処理

デフォルトでは、ClickHouse に送信された各 insert に対して、ClickHouse は、その insert で送られたデータと保存が必要なその他のメタデータを含むストレージのパートを即座に作成します。したがって、少量の insert にそれぞれ多くのデータを含めて送信する方が、多数の insert でそれぞれ少量のデータを送信する場合と比べて、必要な書き込み回数を削減できます。データは、一度に少なくとも 1,000 行以上という、比較的まとまったバッチで挿入することを推奨します。詳細はこちらを参照してください。

デフォルトでは、ClickHouse への insert は同期的に行われ、かつ内容が同一であれば冪等です。MergeTree エンジンファミリーのテーブルでは、ClickHouse はデフォルトで自動的に deduplicate inserts を行います。これは、insert が次のようなケースでも問題なく扱えることを意味します。

  • (1) データを受け取ったノードに問題がある場合、insert クエリはタイムアウト(または、より具体的なエラー)となり、確認応答(ACK)は返されません。
  • (2) ノードがデータを書き込んだものの、ネットワークの中断によりクエリ送信元へ ACK を返せない場合、送信元はタイムアウトまたはネットワークエラーを受け取ります。

コレクターの視点からは、(1) と (2) を区別するのは難しい場合があります。しかし、どちらの場合でも ACK を受け取っていない insert は、そのまま即座に再試行して構いません。再試行された insert クエリが同じ順序で同じデータを含んでいる限り、未 ACK の元の insert が成功していた場合には、ClickHouse は再試行された insert を自動的に無視します。

上記を満たすために、前の構成例で示した batch processor を使用することを推奨します。これにより、上記要件を満たす行の一貫したバッチとして insert が送信されることが保証されます。コレクターが高スループット(毎秒イベント数)が想定され、各 insert で少なくとも 5000 イベントを送信できる場合、これは通常パイプラインで必要となる唯一のバッチ処理です。この場合、コレクターは batch processor の timeout に達する前にバッチをフラッシュし、パイプラインのエンドツーエンドレイテンシを低く保ちつつ、バッチサイズの一貫性を確保します。

非同期インサートを利用する

通常、コレクタのスループットが低い場合、ユーザーはより小さなバッチを送信せざるを得ませんが、それでもエンドツーエンドのレイテンシーを最小限に抑えて ClickHouse にデータが到達することを期待します。この場合、バッチプロセッサの timeout が有効期限切れになると、小さなバッチが送信されます。これが問題を引き起こすことがあり、そのような場合に非同期インサートが必要となります。このケースは、エージェントロールのコレクタが ClickHouse に直接送信するよう構成されているときによく発生します。Gateway はアグリゲータとして動作することでこの問題を軽減できます。詳細は Gateway によるスケーリング を参照してください。

大きなバッチを保証できない場合は、非同期インサート を使用してバッチ処理を ClickHouse に委譲できます。非同期インサートでは、データはまずバッファに挿入され、その後データベースストレージに、後から(または非同期に)書き込まれます。

Async inserts

非同期インサートを有効化 した場合、ClickHouse が ① INSERT クエリを受信すると、そのクエリのデータは ② まずインメモリバッファに即座に書き込まれます。③ 次のバッファフラッシュが行われると、バッファ内のデータはソート され、1 つのパーツとしてデータベースストレージに書き込まれます。注意点として、データベースストレージにフラッシュされるまでは、そのデータはクエリから検索できません。バッファフラッシュは設定可能です。

コレクタで非同期インサートを有効にするには、接続文字列に async_insert=1 を追加します。確実な配信保証を得るために、wait_for_async_insert=1(デフォルト)の使用を推奨します。詳細はこちらを参照してください。

非同期インサートからのデータは、ClickHouse のバッファがフラッシュされたときに挿入されます。これは、async_insert_max_data_size を超えた場合、または最初の INSERT クエリから async_insert_busy_timeout_ms ミリ秒経過した場合のいずれかで発生します。async_insert_stale_timeout_ms がゼロ以外の値に設定されている場合、最後のクエリから async_insert_stale_timeout_ms ミリ秒経過後にデータが挿入されます。これらの設定を調整することで、パイプラインのエンドツーエンドレイテンシーを制御できます。バッファフラッシュの調整に使用できる追加の設定はこちらに記載されています。一般的には、デフォルト値で問題ありません。

適応的非同期インサートの検討

利用中のエージェント数が少なく、スループットも低い一方でエンドツーエンドレイテンシーに厳しい要件がある場合には、adaptive asynchronous inserts が有用な場合があります。一般的に、これは ClickHouse を用いた高スループットなオブザーバビリティ用途には適用されません。

最後に、ClickHouse への同期インサートに関連する従来の重複排除動作は、非同期インサート使用時にはデフォルトでは有効になりません。必要に応じて、async_insert_deduplicate の設定を参照してください。

この機能の設定に関する詳細はこちら、深掘りした解説はこちらを参照してください。

デプロイメントアーキテクチャ

OTel collector を ClickHouse と組み合わせて使用する場合、いくつかのデプロイメントアーキテクチャが利用可能です。以下では、それぞれの構成と、その構成が適用しやすいケースについて説明します。

エージェントのみ

エージェントのみのアーキテクチャでは、ユーザーは OTel collector をエージェントとしてエッジにデプロイします。これらはローカルアプリケーション(例: サイドカーコンテナとして)からトレースを受信し、サーバーおよび Kubernetes ノードからログを収集します。このモードでは、エージェントはデータを直接 ClickHouse に送信します。

Agents only

このアーキテクチャは、小規模から中規模のデプロイメントに適しています。主な利点は、追加のハードウェアを必要とせず、ClickHouse によるオブザーバビリティソリューション全体のリソースフットプリントを最小限に抑えつつ、アプリケーションとコレクターの対応関係をシンプルに保てる点です。

エージェントの数が数百を超える場合は、ゲートウェイベースのアーキテクチャへの移行を検討してください。このアーキテクチャには、スケールさせるうえで問題となるいくつかの欠点があります。

  • 接続のスケーリング - 各エージェントは ClickHouse への接続を確立します。ClickHouse は何百(場合によっては何千)もの同時 INSERT 接続を維持できますが、最終的にはこれが制約要因となり、INSERT の効率を低下させます。つまり、接続を維持するために ClickHouse 側でより多くのリソースが消費されます。ゲートウェイを使用することで接続数を最小化し、INSERT をより効率的にできます。
  • エッジでの処理 - このアーキテクチャでは、あらゆる変換処理やイベント処理をエッジ側、または ClickHouse 側で実行する必要があります。制約が大きいだけでなく、複雑な ClickHouse の materialized view が必要になったり、重要なサービスに影響が及びうるエッジ側に大きな計算処理を押し付けたりする可能性があります。エッジ側ではリソースが限られている場合もあります。
  • 小さなバッチとレイテンシ - エージェントコレクターは、それぞれがごく少量のイベントしか収集しない場合があります。通常、配信の SLA を満たすために、一定間隔でフラッシュするよう設定する必要があります。その結果、コレクターが小さなバッチを ClickHouse に送信してしまうことがあります。これは欠点ですが、非同期 INSERT を使用することで軽減可能です。詳細は Optimizing inserts を参照してください。

ゲートウェイによるスケーリング

OTel collector は、上記の制約に対処するために Gateway インスタンスとしてデプロイできます。これらはスタンドアロンのサービスを提供し、通常はデータセンターごと、あるいはリージョンごとに 1 つ配置します。これらは、単一の OTLP エンドポイントを介して、アプリケーション(またはエージェント役割を持つ他の collector)からイベントを受信します。通常、複数の Gateway インスタンスがデプロイされ、それらの間で負荷を分散するために、一般的なロードバランサーが使用されます。

ゲートウェイによるスケーリング

このアーキテクチャの目的は、計算負荷の高い処理をエージェントからオフロードし、それによってエージェントのリソース使用量を最小化することです。これらのゲートウェイは、本来であればエージェントが担う必要がある変換処理を実行できます。さらに、多数のエージェントからのイベントを集約することで、ゲートウェイは ClickHouse に対して大きなバッチを送信し、効率的な挿入を可能にします。これらの gateway collector は、エージェントの追加やイベントスループットの増加に応じて容易にスケールアウトできます。サンプルの構造化ログファイルを取り込むエージェント設定と組み合わせたゲートウェイ設定の例を以下に示します。エージェントとゲートウェイ間の通信に OTLP を使用している点に注目してください。

clickhouse-agent-config.yaml

receivers:
  filelog:
    include:
      - /opt/data/logs/access-structured.log
    start_at: beginning
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time_local
          layout: '%Y-%m-%d %H:%M:%S'
processors:
  batch:
    timeout: 5s
    send_batch_size: 1000
exporters:
  otlp:
    endpoint: localhost:4317
    tls:
      insecure: true # Set to false if you are using a secure connection
service:
  telemetry:
    metrics:
      address: 0.0.0.0:9888 # Modified as 2 collectors running on same host
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch]
      exporters: [otlp]

clickhouse-gateway-config.yaml

receivers:
  otlp:
    protocols:
    grpc:
    endpoint: 0.0.0.0:4317
processors:
  batch:
    timeout: 5s
    send_batch_size: 10000
exporters:
  clickhouse:
    endpoint: tcp://localhost:9000?dial_timeout=10s&compress=lz4
    ttl: 96h
    traces_table_name: otel_traces
    logs_table_name: otel_logs
    create_schema: true
    timeout: 10s
    database: default
    sending_queue:
      queue_size: 10000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 300s
service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [clickhouse]

これらの構成は、次のコマンドで適用できます。

./otelcol-contrib --config clickhouse-gateway-config.yaml
./otelcol-contrib --config clickhouse-agent-config.yaml

このアーキテクチャの主な欠点は、複数の collector を管理するためのコストと運用負荷が発生することです。

より大規模なゲートウェイベースのアーキテクチャの管理方法と、そこから得られる知見の例については、この ブログ記事 を参考にすることをお勧めします。

Kafka の追加

ここまでに紹介したアーキテクチャでは、メッセージキューとして Kafka を使用していないことに気づく読者もいるかもしれません。

メッセージバッファとして Kafka キューを使用することは、ログ収集アーキテクチャでよく見られる一般的な設計パターンであり、ELK スタックによって広く普及しました。これにはいくつかの利点があります。主なものは、より強力なメッセージ配信保証を提供し、バックプレッシャーへの対応を助ける点です。メッセージは収集エージェントから Kafka に送信され、ディスクに書き込まれます。理論上、クラスタ構成の Kafka インスタンスは、高スループットなメッセージバッファを提供できます。これは、メッセージをパースして処理するよりも、データをディスクに線形に書き込む方が計算オーバーヘッドが小さいためです。例えば Elastic では、トークナイズとインデクシングに大きなオーバーヘッドが発生します。エージェント側からデータを切り離して退避させることで、ソース側でのログローテーションが原因でメッセージを失うリスクも低減できます。最後に、一部のユースケースにとって魅力的になり得るメッセージのリプレイ機能やリージョン間レプリケーション機能も提供します。

しかし、ClickHouse はデータの挿入を非常に高速に処理でき、一般的なハードウェアでも毎秒数百万行を扱うことができます。ClickHouse 側からのバックプレッシャーはまれです。多くの場合、Kafka キューを活用することは、アーキテクチャの複雑さとコストの増大を意味します。ログは銀行取引やその他のミッションクリティカルなデータと同レベルの配信保証を必要としない、という前提を受け入れられるのであれば、Kafka を導入することによるこの複雑さは避けることを推奨します。

一方で、高い配信保証や(複数の宛先に対して)データをリプレイする能力が必須要件である場合には、Kafka は有用なアーキテクチャ上のコンポーネントとなり得ます。

Kafka の追加

この場合、OTel エージェントは Kafka exporter を介して Kafka にデータを送信するように設定できます。ゲートウェイインスタンスは、Kafka receiver を使用してメッセージを消費します。詳細については、Confluent と OTel のドキュメントを参照することをお勧めします。

リソース見積もり

OTel collector のリソース要件は、イベントスループット、メッセージサイズ、および実施する処理内容に依存します。OpenTelemetry プロジェクトでは、リソース要件を見積もる際に利用できるベンチマークを公開しています。

弊社の経験では、3 コアと 12GB の RAM を搭載したゲートウェイインスタンスで、毎秒約 6 万件のイベントを処理できます。これは、フィールド名の変更のみを行い、正規表現を使用しない最小限の処理パイプラインを前提としています。

ゲートウェイへのイベント送信と、イベントへのタイムスタンプ設定のみを担当するエージェントインスタンスについては、想定される 1 秒あたりのログ数に基づいてリソースを見積もることを推奨します。以下は、出発点として利用できるおおよその値です。

ログレートcollector エージェントに必要なリソース
1k/second0.2CPU, 0.2GiB
5k/second0.5 CPU, 0.5GiB
10k/second1 CPU, 1GiB