关于 clickstack-otel-collector
为 ClickHouse Cloud 上的 Managed ClickStack 配置 OpenTelemetry Collector,并验证遥测数据可在 ClickStack 中查看。该技能涵盖本地新建采集器或配置现有采集器两种路径,并通过 `clickhousectl` 执行云端及 SQL 操作。
主要功能
- 01部署本地 ClickStack Collector 或配置现有采集器
- 02转发日志、追踪和指标至 `otel` 数据库
- 03生成并安全保存认证凭据
- 04发送合成遥测数据并验证可见性
- 05使用 `clickhousectl` 执行云端与 SQL 操作
适用场景
- 01为 Managed ClickStack 接入新的本地采集器
- 02将网关角色的现有采集器配置为 ClickHouse exporter
- 03验证遥测数据已进入 ClickStack
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ clickhouse/ agent-skills --skill clickstack-otel-collector安装后在 Claude Code 中输入/clickstack-otel-collector确认已加载。
附带文件metadata.json
详细介绍
为 Managed ClickStack 设置 OpenTelemetry 收集器
此技能会将 OpenTelemetry 收集器接入运行于 ClickHouse Cloud 的 Managed ClickStack 服务,通过该收集器发送丰富的合成遥测数据,并确认这些数据确实能在 ClickStack 中看到。所有云端和 SQL 操作均使用 clickhousectl。
范围。 此技能支持两种路径,请在第 0 步选择:
- 在本地部署新的收集器。 有 两种方式:使用单独的
docker命令,或使用docker compose文件(推荐,命令更少,并且只需一个文件即可启动和停止)。请一开始就让用户了解这两种方式,并在第 0 步让他们选择;不要假设用户会使用普通的docker命令。无论选择哪种方式,运行的都是 ClickStack 发行版的收集器,且已预先配置为适用于 Managed ClickStack。 - 配置用户已有的收集器,方法是添加 ClickHouse exporter 配置。我们会提供可直接放入的确切配置;用户需要重新加载收集器。如果用户已在 gateway 角色中运行收集器,请使用此路径。
此处不涵盖完整的 Kubernetes 部署(Helm、将密钥存储在 K8s Secrets 中);我们生成的路径 2 配置可应用于在任何位置运行的收集器。
最终状态如下:
- 目标服务上有一个专用的
hyperdx_ingestSQL 用户,并拥有收集器所需的全部授权(首次写入时会创建otel.*架构)。 - 收集器会将日志、追踪和指标转发到服务上的
otel数据库;收集器可以是新部署的本地 ClickStack 收集器,也可以是用户已有的收集器。 - 多个服务、严重级别、Span 状态和指标类型的丰富合成遥测数据,可供 ClickStack 的 Search、Service Map 和仪表板展示实际内容。
- 确认服务处于 唤醒状态,并引导用户在 Cloud 控制台中完成 ClickStack 入门流程,以便他们确实能看到自己的数据。
密钥(OTLP 身份验证令牌和 SQL 密码)在本地生成,只写入一次权限为 0600 的 env 文件,并通过 --env-file 传递给 Docker。它们绝不会粘贴到聊天中,不会通过 docker run -e 传递,也不会在创建后回显。
请按顺序执行以下步骤。每一步都依赖上一步建立的状态。
第 0 步:选择路径
在进行任何其他操作之前,先向用户提出两个简短问题,因为答案决定后续要执行哪些步骤。
问题 1:你是否已在 gateway 角色中运行 OpenTelemetry 收集器?
- 没有,请帮我设置一个。 -> 选择 新建收集器路径。继续回答问题 2。
- 是的,我有一个。 -> 选择 现有收集器路径。跳过问题 2(不适用),并在第 6 步配置其收集器,而不是部署新的收集器。
问题 2(仅适用于新建收集器路径):使用单独的 Docker 命令运行收集器,还是使用 Docker Compose 文件?
- Docker Compose(推荐)。 命令更少,只需一个文件即可启动和停止,也最容易重新运行。最适合已安装
docker compose的情况。 - 单独的 Docker 命令。 如果未安装 Compose,或你更倾向于使用明确的命令,请选择此项。
将答案记录为 COLLECTOR_PATH(new 或 existing);如果选择新建收集器路径,还需记录 DEPLOY_MODE(compose 或 run)。请在第 6 步和第 7 步中参考这些值。
第 1 步:预先批量设置权限
编码 Agent 第一次遇到每条 shell 命令时,都会提示用户批准。为避免每隔几步就打断用户,请事先一次性询问他们是否允许以下命令前缀(在其 Agent 中选择“始终允许用于此项目/会话”选项)。这些操作不会造成破坏,也不会影响本项目或其 ClickHouse Cloud 服务以外的任何内容。
| 命令前缀 | 用途 | 何时需要 |
|---|---|---|
openssl rand … | 生成 OTLP 令牌和 SQL 密码 | 始终需要 |
clickhousectl cloud … | 身份验证、解析服务、通过 Query API 执行 SQL | 始终需要 |
jq … | 解析来自 clickhousectl 的 JSON | 始终需要 |
docker … / docker compose … | 运行/检查收集器和遥测生成器 | 新建收集器流程,以及可选的遥测检查 |
curl … | 针对 localhost:13133 进行本地健康检查(以及在缺少 clickhousectl 时安装它) | 新建收集器流程 |
请用你自己的话告诉用户:“如果你的 Agent 支持,请在它第一次询问时,为这些命令逐一选择‘始终允许’。整个过程除了收集器容器外,不会对你的计算机进行写入操作;对 ClickHouse 的写入操作仅限于创建写入用户和 otel 架构。”
如果用户选择现有收集器流程,且不想运行可选的遥测检查,则可以从列表中删除 docker 和 curl。
有两项审批属于语义审批,而非基于前缀,因此加入允许列表也无法提前通过。 请提醒用户留意以下提示,并在出现时明确批准:
- 第 3 步中安装
clickhousectl时会使用curl … | sh;无论是否设置了curl允许规则,许多 Agent 沙盒都会将其标记为“下载并运行不受信任的代码”。 - 第 5 步中的
CREATE USER/GRANT可能会被标记为“修改共享生产基础设施”,同样不受clickhousectl前缀规则的影响。
上表无法解决这两项;它们只需批准一次,且是有意执行的安全操作。
然后继续。
步骤 2:确认目标服务并创建 secrets 文件
用户的提示词中包含一个服务标识符,可以是服务 ID(UUID)或服务名称。
将该值视为 SERVICE_REF。
创建一个工作目录和一个 0600 环境变量文件,用于存放本次运行所需的所有配置和密钥。键名与采集器镜像读取的名称完全一致,因此第 6 步中会将此文件直接传递给 docker run --env-file(或由 Compose 引用)。请在严格的 umask 下写入文件,以免密钥短暂处于全局可读状态:
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"
mkdir -p "$WORKDIR" && chmod 700 "$WORKDIR"
ENV_FILE="$WORKDIR/collector.env"
# Generate secrets WITHOUT printing them; write straight into a private file.
( umask 177
{
echo "SERVICE_REF=$SERVICE_REF"
echo "OTLP_AUTH_TOKEN=$(openssl rand -hex 32)"
echo "CLICKHOUSE_USER=hyperdx_ingest"
echo "CLICKHOUSE_PASSWORD=$(openssl rand -hex 24)Aa1-"
echo "HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE=otel"
} > "$ENV_FILE"
)
chmod 600 "$ENV_FILE"
ls -l "$ENV_FILE"
有两点与这些值有关,容易出错:
- 键名必须完全一致。 采集器读取
CLICKHOUSE_USER、CLICKHOUSE_PASSWORD、CLICKHOUSE_ENDPOINT和HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE。将 SQL 密码存储在CLICKHOUSE_PASSWORD下(不要使用自定义名称);如果缺少该值,采集器会以空密码启动, 随后因code: 516, Authentication failed退出。 - 密码字符集同时受三方面限制。 ClickHouse Cloud 要求密码至少包含一个大写字母和一个特殊字符,
因此纯十六进制字符串会在
CREATE USER时失败。同时,采集器的迁移工具会将密码嵌入连接 URL, 因此@、:、/、?、#和%会导致密码损坏(表现为:启动时出现code: 516, 尽管密码“正确”)。上述方案使用随机十六进制字符串(小写字母和数字),并添加后缀Aa1-, 以满足大写字母、数字和URL 非保留特殊字符(-)的要求。OTLP 令牌没有这类规则 (它只是一个 bearer token),因此使用纯十六进制字符串即可。
环境变量文件使用不带引号的 KEY=VALUE 行:Docker 的 --env-file 不会进行 shell 解析,
因此添加的任何引号都会成为值的一部分。
对于现有采集器路径,你的采集器不会使用 OTLP_AUTH_TOKEN(接收器上的身份验证由你自行配置);
生成该令牌只是为了让同一文件在你之后切换到本地采集器时也能使用。CLICKHOUSE_* 值仍会使用:
第 6 步中,你会将它们加入采集器的 exporter 配置。
每个后续步骤都会在全新的 shell 中运行,因此 WORKDIR、ENV_FILE 和任何已导出的凭据都不会保留;
WORKDIR/ENV_FILE 也不会存储在环境变量文件中,因此无法通过加载该文件恢复它们。 开始每个后续步骤时,
请在 shell 中加入以下标准前置代码,以根据确定性默认值重新推导路径、加载已保存的凭据(第 3 步),
并加载配置:
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
如果你选择了非默认的 WORKDIR,请在每个步骤的开头显式设置它(${WORKDIR:-…} 默认值仅适用于标准位置)。
后续步骤会将这段代码称为“标准前置代码”。
请向用户确认 SERVICE_REF 是否正确。告知他们工作目录的位置,以及 collector.env(权限模式为 0600)
现在已存储 OTLP 令牌和 SQL 密码。**不要打印这两个密钥。**如果他们想查看某个值,请指引他们查看文件
(grep OTLP_AUTH_TOKEN "$ENV_FILE")。
如果用户提供了自己的令牌或密码,请将其写入文件,而不是使用生成的值,同时保持相同的 0600 安全要求,
并确保自定义密码仍符合上述字符集规则。
第 3 步:验证 clickhousectl(默认在单独的终端中)
检查 clickhousectl 是否位于 PATH 中。单独运行此检查,不要将它与安装命令串联:|| curl … | sh 这种写法会把一个无害的检查带入复合命令,而沙箱会将这类命令一概视为不受信任的代码下载并拒绝执行。
which clickhousectl
只有在没有任何输出时,才安装它(用户可能需要明确批准此操作,请参阅第 1 步):
curl -fsSL https://clickhouse.com/cli | sh
检查身份验证状态:
clickhousectl cloud auth status
此技能需要通过 API key 进行身份验证:OAuth 是只读的,无法创建用户或运行写入查询。如果 API key 行的状态不是 Active,用户必须进行身份验证。
不要让用户把 API key 和 secret 粘贴到聊天中。 粘贴到对话中的任何内容都会保留在记录中,之后必须轮换。请改为让用户在单独的终端中进行身份验证,然后告知你已完成:
我需要一个 ClickHouse Cloud Admin API key 来创建摄取用户并验证数据。 请不要在这里粘贴。请改为执行以下操作:
在 Cloud 控制台中,打开 Organization → API keys → New API key,并为其授予 Admin 角色。(Developer 级别的 key 无法配置
cloud service query使用的每服务 Query API 端点。)在单独的终端中,运行:
clickhousectl cloud auth login --api-key <key-id> --api-secret <key-secret>完成后告诉我,我会重新检查身份验证状态。
轮询,直到 API key 行显示 Active,然后通过实际的特权调用进行确认,不要只相信状态表。此处使用与引用无关的调用:SERVICE_REF 可能是名称,而 cloud service get 只接受 UUID,因此用 get 确认时,如果提供的是名称,就会因与身份验证无关的原因失败。cloud service list 不需要 ref,可以证明 API key 有效:
clickhousectl cloud auth status
clickhousectl cloud service list --json | jq -r '.[].name'
如果列表返回了你的服务,说明你已通过身份验证;继续操作。SERVICE_REF 实际的名称或 UUID 解析将在第 4 步进行。
预计需要使用环境变量凭据(这很常见,并非边缘情况)。 许多 clickhousectl 构建版本会保存凭据文件,但新启动的 shell(例如工具调用所使用的 shell)不会读取它,因此 auth status 显示 Active,紧接着的 clickhousectl 调用却会报告 No credentials found。不要把这种情况当作罕见的备用方案;请创建一个小型的可 source 凭据文件,之后在每个 shell 中加载它。这样,后续每个 shell 只需一行 .,而不用通过两条 jq 命令重新推导凭据,也能让 secret 不出现在聊天中:
# Write a private, sourceable creds file next to collector.env.
( umask 177
{ echo "export CLICKHOUSE_CLOUD_API_KEY=$(jq -r .api_key "$HOME/.clickhouse/credentials.json")"
echo "export CLICKHOUSE_CLOUD_API_SECRET=$(jq -r .api_secret "$HOME/.clickhouse/credentials.json")"
} > "$WORKDIR/creds.env"
)
chmod 600 "$WORKDIR/creds.env"
从现在起,每次打开要调用 clickhousectl 的 shell 时,都要加载这两项,因为环境变量不会跨 shell 持久保留:
. "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
加载凭据后,重新运行上面的 service list 检查;此时应该可以成功。实际调用成功之前,不要继续。(如果 clickhousectl auth status 已显示 API key … Active,并且不使用 creds.env 也能成功调用,则可以跳过此步骤;但大多数 Agent shell 都需要它。)
步骤 4:解析服务并获取 HTTPS 终结点
运行标准前置步骤(步骤 2),以便在此 shell 中加载路径、凭据和配置,然后解析服务。如果 SERVICE_REF 是 UUID,请直接使用;否则按名称查找:
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
# UUID form
clickhousectl cloud service get "$SERVICE_REF" --json > "$WORKDIR/svc.json"
# Name form (note the double quotes: service names can contain spaces or apostrophes,
# e.g. "Alex's test")
clickhousectl cloud service list --json \
| jq --arg n "$SERVICE_REF" '.[] | select(.name==$n)' > "$WORKDIR/svc.json"
提取所需的值,并将端口转换为整数。端口会序列化为浮点数(8443.0);如果终结点中出现 :8443.0,采集器的 ClickHouse 导出器将无法连接:
SERVICE_ID=$(jq -r '.id' "$WORKDIR/svc.json")
SERVICE_NAME=$(jq -r '.name' "$WORKDIR/svc.json")
STATE=$(jq -r '.state' "$WORKDIR/svc.json")
CLICKHOUSE_ENDPOINT=$(jq -r '.endpoints[] | select(.protocol=="https")
| "https://\(.host):\(.port | tonumber | floor)"' "$WORKDIR/svc.json")
# Persist the resolved values back into the env file for later steps and docker --env-file.
# Append only if the key is not already present, so a second run does not duplicate lines.
grep -q '^SERVICE_ID=' "$ENV_FILE" || echo "SERVICE_ID=$SERVICE_ID" >> "$ENV_FILE"
grep -q '^CLICKHOUSE_ENDPOINT=' "$ENV_FILE" || echo "CLICKHOUSE_ENDPOINT=$CLICKHOUSE_ENDPOINT" >> "$ENV_FILE"
printf 'service=%q state=%s endpoint=%s\n' "$SERVICE_NAME" "$STATE" "$CLICKHOUSE_ENDPOINT"
STATE 必须为 running。如果状态为 stopped 或 starting,请让用户启动服务(或等待),不要继续。ClickHouse Cloud 服务会空闲挂起,因此即使服务显示为“running”,也可能处于休眠状态;下一次查询既会检查可达性,也会唤醒服务:
clickhousectl cloud service query --id "$SERVICE_ID" --query "SELECT version()"
成功响应表示服务已唤醒,并且已配置每个服务专用的 Query API 密钥。首次调用时,clickhousectl 会打印 Provisioning Query API endpoint + key for service '<name>'...,这是预期行为。
步骤 5:创建 hyperdx_ingest SQL 用户,并授予其 otel.* 权限
此步骤在两种路径上相同:采集器(无论是新建还是现有)都以 hyperdx_ingest 身份向 ClickHouse 进行身份验证。使用组合加载命令打开 shell,以设置 $CLICKHOUSE_PASSWORD(和凭据)。
此处会出现审批提示。 以下
CREATE USER/GRANT语句是针对 Cloud 服务的 DDL,因此有些 Agent 沙箱会将其标记为“修改共享生产基础设施”,即使clickhousectl已列入允许列表。这是预期行为;这些操作的范围仅限于单个专用采集用户和otel架构,用户应在出现提示时明确批准。
绝不要将明文密码写入 SQL。请在本地对其进行哈希,并使用 sha256_hash。 有两个原因使 IDENTIFIED WITH sha256_password BY '$CLICKHOUSE_PASSWORD' 不可行:密钥会出现在进程参数列表中(可通过 ps 查看)和 shell 历史记录中;更重要的是,Query API 会在错误 JSON 中逐字回显失败的语句,因此任何错误(临时故障、字符集问题)都会导致密码泄露到 Agent 可能会显示的输出中。通过 stdin 传递也无济于事,错误回显仍会包含密码。相反,请在本地计算密码的 SHA-256 哈希值(sha256_hash 存储的内容与 sha256_password 完全相同,因此采集器仍会使用环境文件中的明文登录),并且只在语句中写入哈希值。哈希不可逆,因此即使错误被回显,也不会泄露密码:
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
# SHA-256 of the password. openssl is already a dependency; this is portable (macOS + Linux).
# Only this hash ever reaches SQL, output, or `ps`; the plaintext stays in the env file.
PW_HASH=$(printf %s "$CLICKHOUSE_PASSWORD" | openssl dgst -sha256 | awk '{print $NF}')
# Send statements ONE AT A TIME: the Query API runs over HTTP and rejects multi-statement input
# ("Multi-statements are not allowed"), so a single ; -separated batch fails.
clickhousectl cloud service query --id "$SERVICE_ID" --query \
"CREATE USER IF NOT EXISTS hyperdx_ingest IDENTIFIED WITH sha256_hash BY '$PW_HASH'"
# Re-run safe: force the password to this run's value if the user already existed.
clickhousectl cloud service query --id "$SERVICE_ID" --query \
"ALTER USER hyperdx_ingest IDENTIFIED WITH sha256_hash BY '$PW_HASH'"
授予采集器创建和写入 otel.* 架构所需的最低权限。在当前镜像中,架构迁移及其版本表也位于 otel 中,因此 otel.* 就足够了(此语句不包含机密信息):
clickhousectl cloud service query --id "$SERVICE_ID" --query \
"GRANT SELECT, INSERT, CREATE DATABASE, CREATE TABLE, CREATE VIEW ON otel.* TO hyperdx_ingest"
较旧的镜像版本: 某些较早的采集器版本会针对
default数据库中的版本表运行 goose 迁移,因此在授予default.*权限之前,启动会因ACCESS_DENIED而陷入循环。如果你在采集器日志(步骤 6)中看到引用default的ACCESS_DENIED,请添加以下权限并重启容器:clickhousectl cloud service query --id "$SERVICE_ID" --query \ "GRANT SELECT, INSERT, CREATE TABLE ON default.* TO hyperdx_ingest"
验证:
clickhousectl cloud service query --id "$SERVICE_ID" --query "SHOW GRANTS FOR hyperdx_ingest"
你应看到 GRANT SELECT, INSERT, CREATE DATABASE, CREATE TABLE, CREATE VIEW ON otel.* TO hyperdx_ingest。
步骤 6:设置采集器
按照与步骤 0 中所选路径和模式相符的小节操作。三种方式最终都会得到相同结果:采集器接收 OTLP,并将数据写入服务上的 otel 数据库。本步骤中的所有代码块都假定你已先运行标准前置步骤(步骤 2),因此 $WORKDIR、$ENV_FILE、$SERVICE_ID 和密钥均已在 shell 中设置。
确保 Docker 正在运行(仅适用于新建采集器路径):
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
docker info > /dev/null
Step 6a:使用 Docker Compose 创建新采集器(DEPLOY_MODE=compose)
在工作目录中编写一个 Compose 文件。它会读取同一个 collector.env 文件中的机密信息,
发布 OTLP 和健康检查端口,并固定一个命名网络,以便 Step 7 中的遥测生成器可以通过容器名称访问采集器:
cat > "$WORKDIR/docker-compose.yaml" <<'EOF'
name: clickstack
services:
otel-collector:
image: clickhouse/clickstack-otel-collector:latest
container_name: clickstack-otel-collector
env_file: ./collector.env
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "13133:13133" # health
restart: unless-stopped
networks: [clickstack-net]
networks:
clickstack-net:
name: clickstack-net
EOF
# Compose refuses to adopt a clickstack-net it did not create (a leftover from the docker run
# path, a prior failed Compose run, or a DEPLOY_MODE switch), failing with "network clickstack-net
# was found but has incorrect label". If an orphan exists with no containers attached, remove it so
# Compose can recreate it with its own labels.
if docker network inspect clickstack-net >/dev/null 2>&1 \
&& [ -z "$(docker network inspect clickstack-net -f '{{range .Containers}}{{.Name}} {{end}}')" ]; then
docker network rm clickstack-net
fi
( cd "$WORKDIR" && docker compose up -d )
Compose 会为你创建 clickstack-net 网络(上面的保护逻辑会先清理上次运行遗留的孤立网络)。跳到 Step 6d 确认健康状态。
Step 6b:使用单独的 Docker 命令创建新采集器(DEPLOY_MODE=run)
创建一个用户自定义网络,以便 Step 7 中的遥测生成器可以通过容器名称访问采集器:
docker network create clickstack-net 2>/dev/null || true
启动采集器,通过 --env-file 传入所有机密信息(绝不要使用 -e,否则机密信息会出现在命令行、Shell 历史记录和 ps 中)。先运行 docker rm -f,可确保此步骤能够安全地重复执行:
docker rm -f clickstack-otel-collector 2>/dev/null || true
docker run -d \
--name clickstack-otel-collector \
--network clickstack-net \
--env-file "$ENV_FILE" \
-p 4317:4317 \
-p 4318:4318 \
-p 13133:13133 \
clickhouse/clickstack-otel-collector:latest
镜像会从环境变量文件中读取 OTLP_AUTH_TOKEN、CLICKHOUSE_ENDPOINT、CLICKHOUSE_USER、CLICKHOUSE_PASSWORD 和 HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE。它会在 OTLP 接收器上启用 Bearer 令牌身份验证,并使用空方案,因此调用方应将原始令牌作为 authorization 标头发送(不带 Bearer 前缀)。继续执行 Step 6d。
Step 6c:配置现有采集器(COLLECTOR_PATH=existing)
将 ClickHouse 导出器添加到现有采集器配置中。下面的配置与 ClickStack 发行版的行为一致,包括 Session Replay(rrweb)路由路径,并将数据写入 ClickStack 界面所需的 otel 数据库。
请使用环境变量(${env:…})引用端点和密码,不要将其硬编码到配置文件中。 contrib 采集器会在加载时展开 ${env:VAR},因此将明文密码保留在配置文件之外既更安全,也符合此技能的其他部分。启动采集器时,确保环境变量可用;最简单的方式是使用本地采集器相同的 --env-file:
# When running the contrib collector in Docker, pass collector.env so ${env:CLICKHOUSE_*} resolve:
# docker run -d --env-file "$ENV_FILE" -p 4317:4317 -p 4318:4318 \
# -v "$WORKDIR/your-config.yaml:/etc/otelcol-contrib/config.yaml:ro" \
# otel/opentelemetry-collector-contrib:latest
# For a non-Docker collector, export CLICKHOUSE_ENDPOINT and CLICKHOUSE_PASSWORD into its
# environment (e.g. an EnvironmentFile= in the systemd unit) before it starts.
将以下内容添加到采集器配置中,然后重新加载配置:
receivers:
otlp/hyperdx:
protocols:
grpc:
include_metadata: true
endpoint: "0.0.0.0:4317"
http:
cors:
allowed_origins: ["*"]
allowed_headers: ["*"]
include_metadata: true
endpoint: "0.0.0.0:4318"
processors:
batch:
memory_limiter:
limit_mib: 1500
spike_limit_mib: 512
check_interval: 5s
connectors:
routing/logs:
default_pipelines: [logs/out-default]
error_mode: ignore
table:
- context: log
statement: route() where IsMatch(attributes["rr-web.event"], ".*")
pipelines: [logs/out-rrweb]
exporters:
clickhouse:
database: otel
endpoint: ${env:CLICKHOUSE_ENDPOINT}
username: hyperdx_ingest
password: ${env:CLICKHOUSE_PASSWORD}
ttl: 720h
timeout: 5s
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
clickhouse/rrweb:
database: otel
endpoint: ${env:CLICKHOUSE_ENDPOINT}
username: hyperdx_ingest
password: ${env:CLICKHOUSE_PASSWORD}
ttl: 720h
logs_table_name: hyperdx_sessions
timeout: 5s
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
service:
pipelines:
traces:
receivers: [otlp/hyperdx]
processors: [memory_limiter, batch]
exporters: [clickhouse]
metrics:
receivers: [otlp/hyperdx]
processors: [memory_limiter, batch]
exporters: [clickhouse]
logs/in:
receivers: [otlp/hyperdx]
exporters: [routing/logs]
logs/out-default:
receivers: [routing/logs]
processors: [memory_limiter, batch]
exporters: [clickhouse]
logs/out-rrweb:
receivers: [routing/logs]
processors: [memory_limiter, batch]
exporters: [clickhouse/rrweb]
此路径的注意事项:
- 如果使用自己的发行版,请确保其中包含 ClickHouse 导出器。上游的 contrib 镜像已包含该导出器。
- OTLP 接收器上的身份验证沿用你现有的设置。除非你将 Step 2 生成的
OTLP_AUTH_TOKEN接入自己的身份验证配置(例如bearertokenauth),否则这里不会使用它。 - 重新加载后,跳过下面的健康检查(该检查仅适用于本地容器),直接前往 Step 7 发送验证数据突发(将生成器指向你自己的采集器 OTLP 端点)。
步骤 6d:确认本地采集器运行正常(新采集器路径)
docker ps --filter name=clickstack-otel-collector --format '{{.Status}}'
curl -fsS http://localhost:13133/ && echo
docker logs --tail 40 clickstack-otel-collector 2>&1 | tail -40
正常启动时,种子迁移会运行至完成([seed] OK ... 行最终显示
goose: up to current file version: N),随后显示 Everything is ready. Begin running and processing data.(或类似信息),docker ps 报告 Up ... (healthy),且健康检查返回
HTTP 200。较旧服务器版本出现类似 ClickHouse 25.12 < 26.2, falling back to compatibility logs and traces schemas 的种子行是预期情况,不会造成问题,无需因此暂停。如果容器退出,原因几乎总在种子步骤中:
code: 516, Authentication failed: password is incorrect-> 环境文件中的CLICKHOUSE_PASSWORD为空或错误。最常见的问题是密码使用了其他键名(它必须是CLICKHOUSE_PASSWORD),或密码中包含@ : / ? # %,导致迁移工具的连接 URL 出错。- 在 “server hello” 处出现
[HTTP 403]/data size should be 0 < <huge number>-> 根本原因相同:通过 HTTPS 端点使用了空密码或错误密码。 - TLS / 拨号错误 ->
CLICKHOUSE_ENDPOINT格式错误(必须为https://<host>:8443,端口后不能带.0)。 ACCESS_DENIED,涉及default-> 仅出现在较旧的镜像构建中;应用步骤 5 说明中的default.*授权并重启。
步骤 7:发送丰富的合成遥测数据并验证摄取情况
使用 OpenTelemetry Collector Contrib 生成器 telemetrygen 的 Docker 镜像,无需在主机上安装任何内容。不要只发送一次平铺的突发数据,而应跨多个服务、严重性、Span 状态和指标类型发送遥测数据,这样 ClickStack 的 Search、Service Map 和仪表板才能获得真实、多样的数据,而不是单一且均匀的数据流。
加载环境文件以便使用令牌,然后引用 $OTLP_AUTH_TOKEN。下面的 tg 辅助函数会将生成器的所有输出重定向到日志文件,只打印退出代码,因为 telemetrygen 会将完整配置(包括 authorization 标头(即你的 OTLP 令牌))输出到 stdout。切勿在聊天中显示这段原始输出。telemetrygen 的标头语法要求值是带引号的字符串:key="value"。
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
TG_IMAGE=ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
NET=clickstack-net
ENDPOINT=clickstack-otel-collector:4317
TG_LOG="$WORKDIR/telemetrygen.log"; : > "$TG_LOG"
tg() {
# usage: tg <logs|traces|metrics> [extra telemetrygen flags...]
# Output (which contains the token in the echoed config) goes to $TG_LOG, never the terminal.
local signal="$1"; shift
docker run --rm --network "$NET" "$TG_IMAGE" "$signal" \
--otlp-endpoint "$ENDPOINT" \
--otlp-insecure \
--otlp-header "authorization=\"$OTLP_AUTH_TOKEN\"" \
--rate 10 --duration 15s "$@" >>"$TG_LOG" 2>&1
echo "$signal exit=$?"
}
**现有采集器路径:**设置
NET和ENDPOINT,以连接到你的采集器。如果它运行在此主机上,请使用--network host方式访问,或将ENDPOINT指向它发布的地址,并将authorization标头(或其他身份验证信息)设为接收器所要求的值。其余步骤完全相同。
应根据退出代码和行数判断是否成功,切勿查看生成器日志。原因有二。第一,日志中包含你的 OTLP 令牌(见上文),因此不要打印它。第二,日志很杂乱,而且每次运行在 --duration 到期后都会以 rpc error: code = Canceled desc = grpc: the client connection is closing 结束,这是预期的关闭行为,并非失败。成功时,tg 辅助函数会打印 <signal> exit=0。如果必须检查故障,请用 grep 搜索日志中的真实信号,但不要输出日志内容,例如 grep -c Unauthenticated "$TG_LOG"(计数非零且退出代码非零,表示 authorization 标头不匹配)。请通过下面验证查询中的行数确认整体是否成功。
对属性值加引号,确保内部双引号能保留并传递到 shell。telemetrygen 要求每个属性都采用 key="value" 格式(包含字面双引号);如果使用不带引号的 key=value,则会报错 value should be a string wrapped in double quotes。如果写成 --otlp-attributes deployment.environment="production",bash 会去掉引号,容器收到的就是
deployment.environment=production,从而硬性失败。请用单引号包住整个参数,使内部双引号能够传递到容器,和 tg 辅助函数处理身份验证标头的方式完全相同。
跨两个服务发送日志,使用不同的严重性和正文,其中包括一条错误日志:
tg logs --service checkout --severity-text Info --severity-number 9 \
--body "checkout completed" \
--otlp-attributes 'deployment.environment="production"' \
--telemetry-attributes 'http.method="POST"'
tg logs --service payment --severity-text Error --severity-number 17 \
--body "payment gateway timeout" \
--otlp-attributes 'deployment.environment="production"' \
--telemetry-attributes 'http.status_code="500"'
包含子 Span 的跟踪数据、一个健康服务和一个报错服务(Service Map 和错误视图的数据由此生成):
tg traces --service checkout --child-spans 4 --span-duration 120ms --status-code Ok \
--otlp-attributes 'deployment.environment="production"' \
--telemetry-attributes 'http.route="/cart"'
tg traces --service payment --child-spans 3 --span-duration 400ms --status-code Error \
--otlp-attributes 'deployment.environment="production"' \
--telemetry-attributes 'http.route="/charge"'
涵盖三种常见类型的指标,让仪表板中包含仪表、计数器和分布:
tg metrics --service checkout --metric-type Sum
tg metrics --service checkout --metric-type Gauge
tg metrics --service payment --metric-type Histogram
(--metric-type 接受 Gauge、Sum、Histogram 或 ExponentialHistogram。添加 --otlp-http
和 --otlp-endpoint clickstack-otel-collector:4318,即可测试 HTTP 路径,而不是 gRPC。)
等待约 15 秒,让收集器刷新其批次,然后确认表已创建:
clickhousectl cloud service query --id "$SERVICE_ID" --query \
"SELECT name FROM system.tables WHERE database='otel' ORDER BY name"
接着确认数据行已写入。按 parts.rows 计数;这种方式不依赖信号类型,且无需将每种信号的列名写死:
clickhousectl cloud service query --id "$SERVICE_ID" --query \
"SELECT table, sum(rows) AS rows
FROM system.parts
WHERE database='otel' AND active
AND table IN ('otel_logs','otel_traces',
'otel_metrics_sum','otel_metrics_gauge',
'otel_metrics_histogram','otel_metrics_exponential_histogram',
'otel_metrics_summary')
GROUP BY table ORDER BY table"
你应该能在 otel_logs、otel_traces、otel_metrics_sum、
otel_metrics_gauge 和 otel_metrics_histogram 中看到非零的 rows。如果有信号缺失:
- 查看收集器日志(
docker logs --tail 50 clickstack-otel-collector),查找导出错误。 - 确认
authorization标头与$OTLP_AUTH_TOKEN匹配:grep -c Unauthenticated "$TG_LOG"(非零计数表示不匹配,完整消息为code = Unauthenticated desc = provided authorization does not match expected scheme or token)。请使用 grep,不要打印 日志,因为其中包含令牌。 - 再次确认
CLICKHOUSE_ENDPOINT使用https://协议和:8443端口。 - 某些指标类型刷新较慢。在判定失败前,等待 30 秒后重新计数。
请勿继续,直到每种预期信号都有非零行数。
步骤 8:确认服务已唤醒,然后在 ClickStack 中完成引导
ClickHouse 中有数据行,并不代表用户已在 ClickStack 中看到遥测数据。ClickStack UI 需要通过一次性引导步骤自动检测数据源;如果 ClickHouse 服务在此期间因空闲而暂停,该步骤就会失败。
首先,确认服务已唤醒。 请勿跳过此步骤;这是引导界面中没有显示数据源的最常见原因。运行一个实际查询,并确认其成功:
clickhousectl cloud service query --id "$SERVICE_ID" --query "SELECT 1"
如果返回 1,则服务已唤醒;请立即继续下面的控制台步骤,让服务保持活跃。如果返回错误或超时,则表示服务处于休眠状态,此调用正在唤醒它:等待几秒后重新运行,直到返回 1。只有成功后才能继续。
然后,明确引导用户完成引导流程。 不要只说“完成了”;请逐步说明每次点击,因为只有完成此流程后才会显示数据源:
- 前往 ClickHouse Cloud 控制台,并打开目标服务。
- 在左侧菜单中选择 ClickStack。
- 点击进入入门指南,并按照引导流程操作。
- 忽略任何要求设置或配置收集器/开始摄取数据的提示。 你已在上述步骤中完成这些操作。直接跳过这些页面(点击“下一步”),前往数据源检测。无需重新运行控制台中的收集器设置,这只会造成困惑。
- 数据源会自动检测:系统会自动发现
otel数据库中的日志、跟踪数据和指标,你的数据也会显示在搜索和仪表板视图中。
直接链接为 https://console.clickhouse.cloud/services/<SERVICE_ID>/clickstack(替换
$SERVICE_ID)。
如果数据源检测没有显示任何内容,几乎可以肯定是服务在发送数据后、执行控制台步骤前因空闲而暂停了。为用户重新运行上面的 SELECT 1 唤醒查询,然后让他们重新执行检测,而不是让他们自行排查不明确的故障。
步骤 9:总结并交接(不回显机密)
按大致如下的格式打印摘要。请注意,令牌是仅供引用,不会打印,SQL 密码完全不会显示,并且采集器会一直运行,直到用户将其停止。根据用户选择的部署模式调整“如何停止”这一行。
✅ ClickStack is set up and ingesting telemetry for service <SERVICE_NAME> (<SERVICE_ID>).
Complete onboarding in the console (Step 8) to auto-detect the sources and see your data.
Collector
▸ New local collector via <Docker Compose | docker run> (or: configured your existing collector)
▸ Send OTLP gRPC to: localhost:4317
▸ Send OTLP HTTP to: localhost:4318
▸ Health check: http://localhost:13133/ (local collector only)
▸ Required header: authorization: <OTLP token>
(retrieve with: grep OTLP_AUTH_TOKEN <WORKDIR>/collector.env)
ClickHouse target
▸ Endpoint: <CLICKHOUSE_ENDPOINT>
▸ SQL user: hyperdx_ingest (password in <WORKDIR>/collector.env, mode 0600)
▸ Database: otel
Finish in the ClickHouse Cloud console:
▸ Open the service, select ClickStack in the left menu, then Getting Started,
and complete onboarding to auto-detect sources.
▸ https://console.clickhouse.cloud/services/<SERVICE_ID>/clickstack
然后用你自己的话告诉用户:
- 所有机密都保存在
<WORKDIR>/collector.env(模式0600)中。没有任何敏感信息被粘贴到此对话中,也没有通过docker run命令行传递。 - 采集器会一直运行,直到用户将其停止。使用 Compose 时,运行
cd <WORKDIR> && docker compose down可停止它,运行docker compose up -d可重新启动它。使用单独的 Docker 容器时,运行docker stop clickstack-otel-collector和docker start clickstack-otel-collector。 - 此主机上的任何应用、SDK 或 Agent 现在都可以使用环境文件中的
authorization标头,将 OTLP 发送到localhost:4317(gRPC)或localhost:4318(HTTP)。 - ClickHouse Cloud 服务会在空闲时自动暂停。如果 ClickStack 后续显示没有近期数据,服务可能只是处于休眠状态;发送新的遥测数据或运行任何查询都能唤醒它。
清理(仅在用户明确要求时)
# Docker Compose deployment:
( cd "$WORKDIR" && docker compose down )
# Individual Docker deployment:
docker rm -f clickstack-otel-collector
docker network rm clickstack-net 2>/dev/null || true
# Either deployment, remove the ingest user:
clickhousectl cloud service query --id "$SERVICE_ID" --query "DROP USER IF EXISTS hyperdx_ingest"
# Optionally remove the local files once they are no longer needed:
# rm -f "$WORKDIR/collector.env" "$WORKDIR/svc.json" "$WORKDIR/docker-compose.yaml"
不要删除 otel 数据库:其中包含用户可能希望保留的遥测数据。