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

トレース保存と分析

この記事では、Apache DorisでのTraceデータの保存と分析方法について説明し、テーブル作成、収集、クエリの全体パスをカバーします。

  • 総合的なオブザーバビリティソリューションについては、概要を参照してください。
  • リソース推定、クラスタデプロイメント、チューニングについては、Logを参照してください。

クイックナビゲーション

完全なオンボーディングフローは3つのステップで構成されており、順序に従って完了できます:

ステップ内容目的
1. テーブルの作成DorisでTrace保存テーブルを作成Traceの書き込みとクエリパターンに対してパフォーマンスを最適化
2. 収集OpenTelemetryを通じてTraceデータをDorisに書き込みアプリケーションからCollectorを経由してDorisへのパイプラインを接続
3. クエリGrafanaでTraceデータを視覚的に分析検索、レイテンシ分布の表示、トレース詳細の検査

1. テーブルの作成

Traceデータは書き込みとクエリパターンに明確な特性を持ちます。テーブル作成時の的確な設定により、より良いパフォーマンスを得られます。

1.1 主要設定項目

以下の表は、テーブル作成における主要な設定の観点と推奨手法をまとめています:

設定の観点推奨手法説明
パーティショニング時刻フィールドでのRANGEパーティション、動的パーティショニングを有効にして日次パーティションを自動管理パーティションを自動でローテーションし、ホット/コールド分離と期限切れクリーンアップを容易にする
ソートキーservice_nameDATETIME型の時刻フィールドをキーとして使用特定のサービスに対する時間範囲でのクエリを数倍高速化
バケット数クラスタ内の全ディスク数のおよそ3倍並列性と小さなファイルの制御のバランスを取る
バケット戦略書き込み時に単一タブレットインポートと合わせてRANDOMを使用書き込みバッチングを改善
コンパクションtime_seriesコンパクションポリシーを使用書き込み増幅を削減、高スループットTrace書き込み下でのリソース最適化に重要
半構造化フィールドspan_attributesresource_attributesにVARIANT型を使用JSONを自動的にサブカラムに分割して保存、圧縮とサブカラムフィルタ・分析パフォーマンスを向上
インデックスよくクエリされるフィールドに転置インデックスを作成等価フィルタと範囲クエリを高速化
全文検索parserパラメータでトークナイザを指定(通常unicodeで十分)、必要に応じてsupport_phraseを有効化support_phraseはフレーズクエリを可能にする;不要な場合はオフにしてストレージ容量を削減
レプリカクラウドディスクは1レプリカ可能;物理ディスクは最低2レプリカを使用信頼性とコストのバランスを取る
ホット/コールド分離log_s3オブジェクトストレージとlog_policy_3dayポリシーを設定3日以上古いデータを自動的にS3に移動し、ホットストレージコストを削減

1.2 テーブル作成SQLの例

以下の例は、リソース、ストレージポリシー、テーブルの完全な作成プロセスをカバーしています:

CREATE DATABASE log_db;
USE log_db;

-- Not required in the storage-compute decoupled mode
CREATE RESOURCE "log_s3"
PROPERTIES
(
"type" = "s3",
"s3.endpoint" = "your_endpoint_url",
"s3.region" = "your_region",
"s3.bucket" = "your_bucket",
"s3.root.path" = "your_path",
"s3.access_key" = "your_ak",
"s3.secret_key" = "your_sk"
);

-- Not required in the storage-compute decoupled mode
CREATE STORAGE POLICY log_policy_3day
PROPERTIES(
"storage_resource" = "log_s3",
"cooldown_ttl" = "259200"
);

CREATE TABLE trace_table
(
service_name VARCHAR(200),
timestamp DATETIME(6),
service_instance_id VARCHAR(200),
trace_id VARCHAR(200),
span_id STRING,
trace_state STRING,
parent_span_id STRING,
span_name STRING,
span_kind STRING,
end_time DATETIME(6),
duration BIGINT,
span_attributes VARIANT,
events ARRAY<STRUCT<timestamp:DATETIME(6), name:STRING, attributes:MAP<STRING, STRING>>>,
links ARRAY<STRUCT<trace_id:STRING, span_id:STRING, trace_state:STRING, attributes:MAP<STRING, STRING>>>,
status_message STRING,
status_code STRING,
resource_attributes VARIANT,
scope_name STRING,
scope_version STRING,
INDEX idx_timestamp(timestamp) USING INVERTED,
INDEX idx_service_instance_id(service_instance_id) USING INVERTED,
INDEX idx_trace_id(trace_id) USING INVERTED,
INDEX idx_span_id(span_id) USING INVERTED,
INDEX idx_trace_state(trace_state) USING INVERTED,
INDEX idx_parent_span_id(parent_span_id) USING INVERTED,
INDEX idx_span_name(span_name) USING INVERTED,
INDEX idx_span_kind(span_kind) USING INVERTED,
INDEX idx_end_time(end_time) USING INVERTED,
INDEX idx_duration(duration) USING INVERTED,
INDEX idx_span_attributes(span_attributes) USING INVERTED,
INDEX idx_status_message(status_message) USING INVERTED,
INDEX idx_status_code(status_code) USING INVERTED,
INDEX idx_resource_attributes(resource_attributes) USING INVERTED,
INDEX idx_scope_name(scope_name) USING INVERTED,
INDEX idx_scope_version(scope_version) USING INVERTED
)
ENGINE = OLAP
DUPLICATE KEY(service_name, timestamp)
PARTITION BY RANGE(timestamp) ()
DISTRIBUTED BY RANDOM BUCKETS 250
PROPERTIES (
"compression" = "zstd",
"compaction_policy" = "time_series",
"inverted_index_storage_format" = "V2",
"dynamic_partition.enable" = "true",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-30",
"dynamic_partition.end" = "1",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "250",
"dynamic_partition.replication_num" = "2", -- Not required in storage-compute decoupled mode
"replication_num" = "2", -- Not required in storage-compute decoupled mode
"storage_policy" = "log_policy_3day" -- Not required in storage-compute decoupled mode
);

2. Trace収集

DorisはOpenTelemetryなどのTrace収集システムと統合するオープンで汎用的なStream HTTP APIを提供しています。

2.1 全体的なパイプライン

アプリケーション → OpenTelemetry SDK/Agent → OpenTelemetry Collector (Doris Exporterを使用) → Dorisテーブル。

2.2 OpenTelemetry統合手順

Step 1: アプリケーション側でのOpenTelemetry SDKの統合

この例では、OpenTelemetry Java SDKと統合された公式のSpring Boot demoを使用し、パス / に対してシンプルな Hello World! 文字列を返します。

OpenTelemetry Java Agentをダウンロードします。Java Agentを使用する利点は、既存のアプリケーションに変更を加える必要がないことです。

他の言語や統合方法については、以下を参照してください:

Step 2: OpenTelemetry Collectorのデプロイと設定

OpenTelemetry Collectorをダウンロードして展開します。

名前が otelcol-contrib で始まるリリースパッケージをダウンロードしてください。これにはDoris ExporterコンポーネントがContribに含まれており、TraceデータをDorisにインポートできます。

以下のように otel_demo.yaml 設定ファイルを作成します。より多くの設定オプションについては、Doris Exporter documentationを参照してください:

receivers:
otlp: # otlp protocol, receives data sent by the OpenTelemetry Java Agent
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318

processors:
batch:
send_batch_size: 100000 # Number of records per batch; recommended batch size is between 100M and 1G
timeout: 10s

exporters:
doris:
endpoint: http://localhost:8030 # FE HTTP address
database: doris_db_name
username: doris_username
password: doris_password
table:
traces: doris_table_name
create_schema: true # Whether to automatically create the schema; when set to false, you need to create the table manually
mysql_endpoint: localhost:9030 # FE MySQL address
history_days: 10
create_history_days: 10
timezone: Asia/Shanghai
timeout: 60s # http stream load client timeout
log_response: true
sending_queue:
enabled: true
num_consumers: 20
queue_size: 1000
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
headers:
load_to_single_tablet: "true"

ステップ3: OpenTelemetry Collectorを実行する

./otelcol-contrib --config otel_demo.yaml

Step 4: Spring Bootサンプルアプリケーションの開始

アプリケーションを開始する前に、いくつかの環境変数を設定するだけで済みます。コードの変更は必要ありません:

export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS} -javaagent:/your/path/to/opentelemetry-javaagent.jar" # Path to the OpenTelemetry Java Agent
export OTEL_JAVAAGENT_LOGGING="none" # Disable otel logging to avoid interfering with the service's own logs
export OTEL_SERVICE_NAME="myproject"
export OTEL_TRACES_EXPORTER="otlp" # Use the otlp protocol to send trace data
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" # Address of the OpenTelemetry Collector

java -jar myproject-0.0.1-SNAPSHOT.jar

ステップ5: サンプルアプリケーションへのアクセスとトレースデータの生成

curl localhost:8080を実行してhelloサービス呼び出しをトリガーします。OpenTelemetry Java Agentが自動的にトレースデータを生成し、OpenTelemetry Collectorに送信します。その後、CollectorはDoris Exporterの設定を通じてトレースデータをDorisテーブルに書き込みます(デフォルトのテーブル名はotel.otel_tracesです)。

3. トレースクエリ

トレースクエリは通常、Grafanaなどのビジュアルインターフェースを通じて実行されます。一般的なシナリオには以下が含まれます:

  • 時間範囲とサービス名でフィルタリングしてトレースの概要を表示します。これには、レイテンシ分布チャートと最新のトレースが含まれます。

    Trace list

  • リンクをクリックしてトレースの詳細を表示します。

    Trace query