跳到主要内容

OpenTelemetry

OpenTelemetry(简称 OTel)是一个中立厂商的开源可观测性框架,用于监测、生成、收集和导出日志、链路追踪和指标等可观测性数据。OpenTelemetry 定义了一套可观测性标准和协议,被可观测性社区和厂商广泛采纳,逐渐成为可观测性领域的事实标准。

OpenTelemetry 提供框架和可观测性数据采集 SDK,使应用程序和系统可以在不同编程语言、基础设施和运行时环境中完成监测。Doris 可以作为 OpenTelemetry 的存储后端,提供高性能、低成本、统一的可观测性数据存储和分析能力。整体架构如下:

Doris Opentelemetry Integration

适用场景与接入流程

你可以根据数据类型选择对应的接入方式:

用户场景推荐配置参考章节
采集 Doris FE 等普通 TEXT 日志,并处理 Java stacktrace 等多行日志使用 filelog receiver、multilineregex_parser,将多行日志合并并解析后写入 Doris采集 Doris FE TEXT 日志
采集每行一个 JSON 对象的结构化日志使用 filelog receiver 和 json_parser,将 JSON 行日志解析后写入 Doris采集 GitHub Events JSON 日志
采集应用 Trace 数据使用 otlp receiver 接收 OpenTelemetry Java Agent 上报的数据,再通过 Doris Exporter 写入 Doris采集应用 Trace 数据
配置 Doris 写入目标、自动建表、分区保留和 Stream Load 参数在 Doris Exporter 中配置 endpointdatabasetable.*create_schemaheaders 等参数配置 Doris Exporter

使用 OpenTelemetry Collector Doris Exporter 接入 Doris 的基本流程如下:

  1. 下载并解压 OpenTelemetry Collector Contrib。
  2. 配置 Doris Exporter,包括 Doris FE 地址、账号、目标库表和 Stream Load 参数。
  3. 根据数据类型配置 receiver、processor 和 pipeline。
  4. 启动 Collector,将日志、Trace 或 Metrics 数据写入 Doris。
  5. 通过 Stream Load 响应日志和写入速度日志观察导入结果。

安装 OpenTelemetry Collector Contrib

OpenTelemetry 官方 Release 页面 下载 OpenTelemetry Collector Contrib 安装包。Contrib 版本包含 Doris Exporter,例如:

wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.132.2/otelcol-contrib_0.132.2_linux_amd64.tar.gz

下载后解压安装包,即可得到 otelcol-contrib 可执行文件。

配置 Doris Exporter

OpenTelemetry Collector Doris Exporter 通过 Doris Stream Load HTTP 接口写入数据。核心配置项如下:

配置项默认值说明
endpointDoris FE HTTP 地址,格式是 host:port,例如 127.0.0.1:8030
mysql_endpointDoris FE MySQL 地址,格式是 host:port,例如 127.0.0.1:9030
usernameDoris 用户名。该用户需要具有对应库表的写入权限。
passwordDoris 用户的密码。
database要写入的 Doris 库名。
table.logsotel_logslogs 数据写入的 Doris 表名。
table.tracesotel_tracestraces 数据写入的 Doris 表名。
table.metricsotel_metricsmetrics 数据写入的 Doris 表名。
create_schematrue是否自动创建 Doris 库表。
history_days0自动创建的 Doris 表的历史数据保留天数。0 表示永久保留。
create_history_days0自动创建的 Doris 表的初始分区天数。0 表示不创建分区。
label_prefixopen_telemetryDoris Stream Load Label 前缀。最终生成的 Label 格式为 {label_prefix}_{db}_{table}_{yyyymmdd_hhmmss}_{uuid}
headersDoris Stream Load 的 headers 参数,语法格式为 YAML map。
log_progress_interval10在日志中输出写入速度的时间间隔,单位为秒。设置为 0 可以关闭该日志。

更多配置请参考 OpenTelemetry Collector Contrib Doris Exporter 文档

采集 Doris FE TEXT 日志

该场景以 Doris FE 日志为例,展示如何采集 TEXT 日志并写入 Doris。

步骤 1:准备日志文件

Doris FE 日志文件通常位于 Doris 安装目录下的 fe/log/fe.log。FE 日志是典型的 Java 程序日志,包含时间戳、日志级别、线程名、代码位置、日志内容等字段。日志中既有普通日志,也有带 stacktrace 的异常日志。由于 stacktrace 跨多行,采集时需要将主日志和对应的 stacktrace 合并为一条日志。

2024-07-08 21:18:01,432 INFO (Statistics Job Appender|61) [StatisticsJobAppender.runAfterCatalogReady():70] Stats table not available, skip
2024-07-08 21:18:53,710 WARN (STATS_FETCH-0|208) [StmtExecutor.executeInternalQuery():3332] Failed to run internal SQL: OriginStatement{originStmt='SELECT * FROM __internal_schema.column_statistics WHERE part_id is NULL ORDER BY update_time DESC LIMIT 500000', idx=0}
org.apache.doris.common.UserException: errCode = 2, detailMessage = tablet 10031 has no queryable replicas. err: replica 10032's backend 10008 does not exist or not alive
at org.apache.doris.planner.OlapScanNode.addScanRangeLocations(OlapScanNode.java:931) ~[doris-fe.jar:1.2-SNAPSHOT]
at org.apache.doris.planner.OlapScanNode.computeTabletInfo(OlapScanNode.java:1197) ~[doris-fe.jar:1.2-SNAPSHOT]

步骤 2:编写 OpenTelemetry 配置

日志采集配置文件 opentelemetry_java_log.yml 主要包含三部分:

配置部分作用
receivers读取原始数据。
processors对数据进行转换和批处理。
exporters将数据输出到 Doris。
# 1. receivers 负责读取原始数据。
# filelog 是本地 receiver,可以读取本地文件系统中的日志文件。
# multiline 会把非时间戳开头的行拼接到上一行后面,用于合并 stacktrace 和主日志。
receivers:
filelog:
include:
- /path/to/fe.log
start_at: beginning
multiline:
line_start_pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}' # 匹配时间戳作为新日志开始
operators:
- type: regex_parser
regex: '^(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) (?P<severity>INFO|WARN|ERROR) (?P<message>.*)'
timestamp:
parse_from: attributes.time
layout: '%Y-%m-%d %H:%M:%S,%f'
severity:
parse_from: attributes.severity
trace: TRACE
debug: DEBUG
info: INFO
warn: WARN
error: ERROR
fatal: FATAL

# 2. processors 负责做数据转换。
# batch processor 会将数据攒成批次后再发送。
processors:
batch:
send_batch_size: 100000 # 每个批次的数据条数,建议 batch 的数据量在 100M-1G 之间
timeout: 10s

# 3. exporters 负责将数据输出。
# doris exporter 使用 Stream Load HTTP 接口写入 Doris。
# 默认 Stream Load 数据格式为 JSON,Stream Load 会解析 JSON 字段并写入 Doris 表中的对应字段。
exporters:
doris:
endpoint: http://localhost:8030 # FE HTTP 地址
mysql_endpoint: localhost:9030 # FE MySQL 地址
database: doris_db_name
username: doris_username
password: doris_password
table:
logs: otel_logs
create_schema: true # 是否自动创建 schema,如果设置为 false,则需要手动建表
history_days: 10
create_history_days: 10
timezone: Asia/Shanghai
timeout: 60s # HTTP Stream Load 客户端超时时间
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"

service:
pipelines:
logs:
receivers: [filelog]
processors: [batch]
exporters: [doris]

步骤 3:运行 OpenTelemetry Collector

./otelcol-contrib --config config/opentelemetry_java_log.yml

步骤 4:查看写入结果

log_responsetrue 时,日志会输出每次 Stream Load 的请求参数和响应结果:

2025-08-18T00:33:22.543+0800    info    dorisexporter@v0.132.0/exporter_logs.go:181    log response:
{
"TxnId": 52,
"Label": "open_telemetry_otel_otel_logs_20250818003321_498bb8ec-040c-4982-9eb4-452b15129782",
"Comment": "",
"TwoPhaseCommit": "false",
"Status": "Success",
"Message": "OK",
"NumberTotalRows": 50355,
"NumberLoadedRows": 50355,
"NumberFilteredRows": 0,
"NumberUnselectedRows": 0,
"LoadBytes": 31130235,
"LoadTimeMs": 680,
"BeginTxnTimeMs": 0,
"StreamLoadPutTimeMs": 3,
"ReadDataTimeMs": 106,
"WriteDataTimeMs": 653,
"ReceiveDataTimeMs": 11,
"CommitAndPublishTimeMs": 23
}

默认每隔 10 秒会输出写入速度信息,包括自启动以来的数据量(MB 和 ROWS)、总速度(MB/s 和 R/s)以及最近 10 秒速度:

2025-08-18T00:05:00.017+0800    info    dorisexporter@v0.132.0/progress_reporter.go:63    [LOG] total 11 MB 18978 ROWS, total speed 0 MB/s 632 R/s, last 10 seconds speed 1 MB/s 1897 R/s

采集 GitHub Events JSON 日志

该场景以 GitHub Events Archive 数据为例,展示如何采集 JSON 日志并写入 Doris。

步骤 1:准备 JSON 数据

GitHub Events Archive 是 GitHub 用户操作事件的归档数据,格式是 JSON,可以从 https://www.gharchive.org/ 下载。以下示例下载 2024 年 1 月 1 日 15 点的数据:

wget https://data.gharchive.org/2024-01-01-15.json.gz

下面是一条数据样例。实际数据是一行一个 JSON 对象,这里为了便于阅读进行了格式化。

{
"id": "37066529221",
"type": "PushEvent",
"actor": {
"id": 46139131,
"login": "Bard89",
"display_login": "Bard89",
"gravatar_id": "",
"url": "https://api.github.com/users/Bard89",
"avatar_url": "https://avatars.githubusercontent.com/u/46139131?"
},
"repo": {
"id": 780125623,
"name": "Bard89/talk-to-me",
"url": "https://api.github.com/repos/Bard89/talk-to-me"
},
"payload": {
"repository_id": 780125623,
"push_id": 17799451992,
"size": 1,
"distinct_size": 1,
"ref": "refs/heads/add_mvcs",
"head": "f03baa2de66f88f5f1754ce3fa30972667f87e81",
"before": "85e6544ede4ae3f132fe2f5f1ce0ce35a3169d21"
},
"public": true,
"created_at": "2024-04-01T23:00:00Z"
}

步骤 2:编写 OpenTelemetry 配置

与 TEXT 日志采集不同,JSON 日志采集在 filelog receiver 中使用 json_parserjson_parser 会将每一行文本当作 JSON 解析,解析后的字段用于后续处理。

receivers:
filelog:
include:
- /path/to/2024-01-01-15.json
start_at: beginning
operators:
- type: json_parser
timestamp:
parse_from: attributes.created_at
layout: '%Y-%m-%dT%H:%M:%SZ'

processors:
batch:
send_batch_size: 100000 # 每个批次的数据条数,建议 batch 的数据量在 100M-1G 之间
timeout: 10s

exporters:
doris:
endpoint: http://localhost:8030 # FE HTTP 地址
mysql_endpoint: localhost:9030 # FE MySQL 地址
database: doris_db_name
username: doris_username
password: doris_password
table:
logs: otel_logs
create_schema: true # 是否自动创建 schema,如果设置为 false,则需要手动建表
history_days: 10
create_history_days: 10
timezone: Asia/Shanghai
timeout: 60s # HTTP Stream Load 客户端超时时间
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"

service:
pipelines:
logs:
receivers: [filelog]
processors: [batch]
exporters: [doris]

步骤 3:运行 OpenTelemetry Collector

./otelcol-contrib --config config/opentelemetry_json_log.yml

采集应用 Trace 数据

该场景展示如何通过 OTLP 协议接收应用侧上报的 Trace 数据,并将 Trace 写入 Doris。

步骤 1:编写 OpenTelemetry 配置

创建 otel_trace.yaml 配置文件:

receivers:
otlp: # OTLP 协议,接收 OpenTelemetry Java Agent 发送的数据
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318

processors:
batch:
send_batch_size: 100000 # 每个批次的数据条数,建议 batch 的数据量在 100M-1G 之间
timeout: 10s

exporters:
doris:
endpoint: http://localhost:8030 # FE HTTP 地址
database: doris_db_name
username: doris_username
password: doris_password
table:
traces: doris_table_name
create_schema: true # 是否自动创建 schema,如果设置为 false,则需要手动建表
mysql_endpoint: localhost:9030 # FE MySQL 地址
history_days: 10
create_history_days: 10
timezone: Asia/Shanghai
timeout: 60s # HTTP Stream Load 客户端超时时间
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"

service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [doris]

步骤 2:运行 OpenTelemetry Collector

./otelcol-contrib --config otel_trace.yaml

步骤 3:应用侧接入 OpenTelemetry SDK

以下示例使用 Spring Boot 示例应用接入 OpenTelemetry Java SDK。示例应用来自官方 demo,对路径 / 返回简单的 Hello World! 字符串。

下载 OpenTelemetry Java Agent。使用 Java Agent 的优势是不需要修改现有应用代码。其他语言和接入方式请参考 OpenTelemetry 官网的 Language APIs & SDKsZero-code Instrumentation

启动应用之前,添加以下环境变量:

export JAVA_TOOL_OPTIONS="${JAVA_TOOL_OPTIONS} -javaagent:/your/path/to/opentelemetry-javaagent.jar" # OpenTelemetry Java Agent 的路径
export OTEL_JAVAAGENT_LOGGING="none" # 禁用 OTel log,防止干扰服务本身的日志
export OTEL_SERVICE_NAME="myproject"
export OTEL_TRACES_EXPORTER="otlp" # 使用 OTLP 协议发送 Trace 数据
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" # OpenTelemetry Collector 的地址

java -jar myproject-0.0.1-SNAPSHOT.jar