clickstack-otel-collector

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Set up an OpenTelemetry collector for Managed ClickStack

为托管ClickStack服务配置OpenTelemetry收集器

This skill wires an OpenTelemetry collector into a Managed ClickStack service running on ClickHouse Cloud, sends rich synthetic telemetry through it, and confirms the data is actually visible in ClickStack. It uses
clickhousectl
for all cloud and SQL operations.
Scope. This skill supports two paths, chosen in Step 0:
  1. Deploy a new collector locally. You can do this two ways: individual
    docker
    commands, or a
    docker compose
    file
    (recommended, fewer commands and one file to start/stop). Make the user aware of both up front and let them pick in Step 0; do not assume plain
    docker
    . Either way runs the ClickStack distribution of the collector, preconfigured for Managed ClickStack.
  2. Configure your own existing collector by adding the ClickHouse exporter configuration. We give you the exact config to drop in; you reload your collector. Use this if you already run a collector in a gateway role.
A full Kubernetes deployment (Helm, secrets in K8s Secrets) is out of scope here; the config we generate in path 2 can be applied to a collector running anywhere.
The end state is:
  • A dedicated
    hyperdx_ingest
    SQL user on the target service, with exactly the grants the collector needs (it creates the
    otel.*
    schema on first write).
  • A collector forwarding logs, traces, and metrics into the
    otel
    database on the service, either the new local ClickStack collector or your existing one.
  • Rich synthetic telemetry across several services, severities, span statuses, and metric types, so ClickStack's Search, Service Map, and dashboards have something real to show.
  • The service confirmed awake, and the user walked through the ClickStack onboarding in the Cloud console so they can actually see their data.
Secrets (the OTLP auth token and the SQL password) are generated locally, written once to a
0600
env file, and passed to Docker via
--env-file
. They are never pasted into the chat, never passed with
docker run -e
, and never echoed back after creation.
Follow these steps in order. Each step depends on state established by the previous one.

本技能将OpenTelemetry收集器接入ClickHouse Cloud上运行的托管ClickStack服务,通过收集器发送丰富的合成遥测数据,并确认数据已成功显示在ClickStack中。所有云操作和SQL操作均通过
clickhousectl
完成。
适用范围:本技能支持两种部署路径,需在步骤0中选择:
  1. 部署新的本地收集器:提供两种方式——单独的
    docker
    命令,或
    docker compose
    文件(推荐,命令更少,仅需一个文件即可启停)。需提前告知用户两种方式并让其在步骤0中选择,不要默认使用纯
    docker
    命令。无论哪种方式,均运行ClickStack分发版的收集器,已预先配置为适配托管ClickStack服务。
  2. 配置现有收集器:通过添加ClickHouse导出器配置来完成。我们会提供可直接复用的配置代码,您只需重新加载收集器即可。此路径适用于已在网关角色下运行收集器的场景。
Kubernetes完整部署(Helm、存储在K8s Secrets中的密钥)不在本技能的覆盖范围内;路径2中生成的配置可应用于任何环境下运行的收集器。
最终实现效果:
  • 目标服务上创建专用的
    hyperdx_ingest
    SQL用户,仅拥有收集器所需的权限(首次写入时会自动创建
    otel.*
    模式)。
  • 收集器将日志、链路追踪和指标转发至服务的
    otel
    数据库,可为新部署的本地ClickStack收集器或您的现有收集器。
  • 生成跨多个服务、不同严重级别、链路状态和指标类型的丰富合成遥测数据,使ClickStack的搜索功能、服务地图和仪表盘拥有真实的数据展示内容。
  • 确认服务处于活跃状态,并引导用户完成ClickHouse Cloud控制台中的ClickStack入门流程,确保用户能够实际查看数据。
密钥(OTLP认证令牌和SQL密码)在本地生成,仅写入一次到权限为
0600
的环境文件中,并通过
--env-file
传递给Docker。密钥不会粘贴到对话中,不会通过
docker run -e
传递,也不会在创建后回显。
请按顺序执行以下步骤,每一步都依赖于上一步建立的状态。

Step 0: Choose your path

步骤0:选择部署路径

Ask the user two short questions before doing anything else, because they determine which later steps run.
Question 1: Do you already have an OpenTelemetry collector running in a gateway role?
  • No, set one up for me. -> the new-collector path. Continue to Question 2.
  • Yes, I have one. -> the existing-collector path. Skip Question 2 (it does not apply), and in Step 6 you will configure their collector rather than deploy a new one.
Question 2 (new-collector path only): Run the collector with individual Docker commands, or a Docker Compose file?
  • Docker Compose (recommended). Fewer commands, one file to start and stop, easiest to re-run. Best if
    docker compose
    is available.
  • Individual Docker commands. Use if Compose is not installed or you prefer explicit commands.
Record the answers as
COLLECTOR_PATH
(
new
or
existing
) and, for the new path,
DEPLOY_MODE
(
compose
or
run
). Refer back to them in Step 6 and Step 7.

在执行任何操作前,先向用户提出两个简短问题,答案将决定后续执行的步骤。
问题1:您是否已在网关角色下运行了OpenTelemetry收集器?
  • 否,帮我部署一个。 → 进入新收集器路径,继续回答问题2。
  • 是,我已有收集器。 → 进入现有收集器路径,跳过问题2(不适用),在步骤6中配置现有收集器而非部署新收集器。
问题2(仅新收集器路径适用):使用单独的Docker命令还是Docker Compose文件运行收集器?
  • Docker Compose(推荐):命令更少,仅需一个文件即可启停,便于重新运行。适用于已安装
    docker compose
    的环境。
  • 单独的Docker命令:适用于未安装Compose或偏好显式命令的场景。
将答案记录为
COLLECTOR_PATH
new
existing
),对于新收集器路径,还需记录
DEPLOY_MODE
compose
run
)。后续步骤6和步骤7会参考这些值。

Step 1: Batch the permissions up front

步骤1:提前批量申请权限

Coding agents prompt for approval the first time they see each shell command. To avoid interrupting the user every few steps, ask them once, up front, to allowlist the command prefixes below (the "always allow for this project / session" option in their agent). There are no destructive operations and nothing targets anything outside this project or their ClickHouse Cloud service.
Command prefixUsed forNeeded when
openssl rand …
generate the OTLP token and SQL passwordalways
clickhousectl cloud …
auth, resolve the service, run SQL via the Query APIalways
jq …
parse JSON from
clickhousectl
always
docker …
/
docker compose …
run/inspect the collector and the telemetry generatornew-collector path, and the optional telemetry check
curl …
local health check against
localhost:13133
(and installing
clickhousectl
if missing)
new-collector path
Tell the user, in your own words: "If your agent supports it, choose 'always allow' for each of these the first time it asks. The whole run is read-only against your machine except for the collector container, and write operations against ClickHouse are limited to creating the ingest user and the
otel
schema."
If the user is on the existing-collector path and does not want to run the optional telemetry check, you can drop
docker
and
curl
from the list.
Two approvals are semantic, not prefix-based, so allowlisting won't pre-clear them. Warn the user to expect these and approve them explicitly when they appear:
  • The
    clickhousectl
    install in Step 3 uses
    curl … | sh
    , which many agent sandboxes flag as "downloading and running untrusted code" regardless of any
    curl
    allowlist rule.
  • The
    CREATE USER
    /
    GRANT
    in Step 5 may be flagged as "modifying shared production infrastructure," again independent of the
    clickhousectl
    prefix rule.
Neither is solved by the table above; they are one-time, intentional, and safe to approve.
Then continue.

代码代理在首次执行每个shell命令时会提示用户批准。为避免在每一步都打断用户,需提前一次性请求用户将以下命令前缀加入白名单(代理中的“针对本项目/会话始终允许”选项)。所有操作均无破坏性,且不会针对本项目或ClickHouse Cloud服务以外的资源执行。
命令前缀用途适用场景
openssl rand …
生成OTLP令牌和SQL密码所有场景
clickhousectl cloud …
认证、解析服务、通过Query API执行SQL所有场景
jq …
解析
clickhousectl
返回的JSON数据
所有场景
docker …
/
docker compose …
运行/检查收集器和遥测数据生成器新收集器路径,以及可选的遥测数据检查步骤
curl …
localhost:13133
执行本地健康检查(若缺少
clickhousectl
则用于安装)
新收集器路径
用您自己的语言告知用户:“如果您的代理支持该功能,首次提示时请为每个命令前缀选择‘始终允许’。除收集器容器外,整个流程对您的机器仅执行只读操作;针对ClickHouse的写入操作仅限于创建采集用户和
otel
模式。”
若用户选择现有收集器路径且不想执行可选的遥测数据检查步骤,可从列表中移除
docker
curl
有两个操作需语义批准,而非基于前缀,因此白名单无法预先通过。需提醒用户注意这两个操作,并在出现时明确批准:
  • 步骤3中安装
    clickhousectl
    使用
    curl … | sh
    ,许多代理沙箱会将其标记为“下载并运行不受信任的代码”,无论是否添加了
    curl
    白名单规则。
  • 步骤5中的
    CREATE USER
    /
    GRANT
    操作可能被标记为“修改共享生产基础设施”,同样不受
    clickhousectl
    前缀规则的影响。
这两个操作均无法通过上述表格解决,它们是一次性的、有意设计的安全操作,用户可放心批准。
之后继续执行后续步骤。

Step 2: Confirm the target service and lay down the secrets file

步骤2:确认目标服务并创建密钥文件

The user's prompt contains a service identifier, either a service ID (UUID) or a service name. Treat that value as
SERVICE_REF
.
Create a working directory and a
0600
env file
that will hold all configuration and secrets for this run. The key names match exactly what the collector image reads, so this same file is passed straight to
docker run --env-file
(or referenced by Compose) in Step 6. Write it under a tight
umask
so the secret is never briefly world-readable:
bash
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"
mkdir -p "$WORKDIR" && chmod 700 "$WORKDIR"
ENV_FILE="$WORKDIR/collector.env"
用户的提示中包含服务标识符,可为服务ID(UUID)或服务名称。将该值视为
SERVICE_REF
创建工作目录和一个权限为**
0600
的环境文件**,用于存储本次运行的所有配置和密钥。密钥名称与收集器镜像读取的名称完全一致,因此该文件可直接在步骤6中通过
docker run --env-file
传递(或被Compose引用)。通过严格的
umask
设置写入文件,确保密钥不会短暂地被全局可读:
bash
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"

Two things about these values matter and are easy to get wrong:

- **Key names are exact.** The collector reads `CLICKHOUSE_USER`, `CLICKHOUSE_PASSWORD`,
  `CLICKHOUSE_ENDPOINT`, and `HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE`. Store the SQL password
  under `CLICKHOUSE_PASSWORD` (not a custom name); if it is missing, the collector starts with an
  **empty** password and dies with `code: 516, Authentication failed`.
- **The password charset is constrained from three directions at once.** ClickHouse Cloud rejects
  passwords without at least one uppercase character and one special character, so a plain hex
  string fails at `CREATE USER`. At the same time, the collector's migration tool embeds the
  password in a connection URL, so `@`, `:`, `/`, `?`, `#`, and `%` corrupt it (symptom:
  `code: 516` at startup even though the password is "correct"). The recipe above is random hex
  (lowercase + digits) plus the suffix `Aa1-`, which adds the required uppercase, a digit, and a
  **URL-unreserved** special character (`-`). The OTLP token has no such rules (it is just a
  bearer token), so plain hex is fine for it.

The env file uses **bare `KEY=VALUE` lines with no quotes**: Docker's `--env-file` does not do
shell parsing, so any quotes you add become part of the value.

On the **existing-collector path** the `OTLP_AUTH_TOKEN` is not used by your collector (auth on
your receiver is your own setup); it is generated only so the same file works if you later switch
to the local collector. The `CLICKHOUSE_*` values are still used: they go into the exporter
config you add to your collector in Step 6.

**Every later step runs in a fresh shell, so `WORKDIR`, `ENV_FILE`, and any exported credentials do
not persist, and `WORKDIR`/`ENV_FILE` are not stored inside the env file, so sourcing it can't
recover them.** Begin each subsequent step's shell with this **standard preamble**, which
re-derives the paths from the deterministic default, loads the saved credentials (Step 3), and
loads the config:

```bash
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
If you chose a non-default
WORKDIR
, set it explicitly at the top of every step (the
${WORKDIR:-…}
default only covers the standard location). Later steps refer to this as "the standard preamble".
Confirm with the user that
SERVICE_REF
is correct. Tell them the working directory and that
collector.env
(mode
0600
) now holds the OTLP token and the SQL password. Do not print either secret. If they want to see a value, point them at the file (
grep OTLP_AUTH_TOKEN "$ENV_FILE"
).
If the user supplied their own token or password, write those into the file instead of the generated ones, but keep the same
0600
discipline and make sure any custom password still meets the charset rules above.

( 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,因此`@`、`:`、`/`、`?`、`#`和`%`会破坏URL(症状:即使密码“正确”,启动时仍会出现`code: 516`错误)。上述生成规则使用随机十六进制(小写+数字)加上后缀`Aa1-`,添加了所需的大写字母、数字和**URL安全**的特殊字符(`-`)。OTLP令牌无此类规则(仅作为Bearer令牌),因此纯十六进制即可。

环境文件使用**无引号的`KEY=VALUE`格式**:Docker的`--env-file`不执行shell解析,因此添加的任何引号都会成为值的一部分。

在**现有收集器路径**中,`OTLP_AUTH_TOKEN`不会被您的收集器使用(接收器的认证由您自行配置);生成该值仅为了让同一文件在您后续切换到本地收集器时仍能使用。`CLICKHOUSE_*`值仍会被使用:它们将被添加到步骤6中您收集器的导出器配置中。

**后续每个步骤都在新的shell中运行,因此`WORKDIR`、`ENV_FILE`和任何导出的凭证不会持久化,且`WORKDIR`/`ENV_FILE`不会存储在环境文件中,因此无法通过source命令恢复**。每个后续步骤的shell都需以以下**标准前置代码**开头,从确定性默认值重新推导路径,加载保存的凭证(步骤3)和配置:

```bash
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
权限,并确保自定义密码仍符合上述字符集规则。

Step 3: Authenticate
clickhousectl
(separate terminal by default)

步骤3:认证
clickhousectl
(默认使用独立终端)

Check
clickhousectl
is on
PATH
. Run this presence check on its own, not chained to the installer: the
|| curl … | sh
form drags a harmless check into a compound command that sandboxes deny wholesale as an untrusted-code download.
bash
which clickhousectl
Only if that prints nothing, install it (the user may need to approve this explicitly, see Step 1):
bash
curl -fsSL https://clickhouse.com/cli | sh
Check authentication:
bash
clickhousectl cloud auth status
This skill needs API key authentication: OAuth is read-only and cannot create users or run write queries. If the
API key
row is not
Active
, the user must authenticate.
Do not ask the user to paste their API key and secret into the chat. Anything pasted into the conversation lives in the transcript and has to be rotated afterward. Instead, ask them to authenticate in a separate terminal, then tell you when they are done:
I need a ClickHouse Cloud Admin API key to create the ingest user and verify the data. Please don't paste it here. Instead:
  1. In the Cloud console, open Organization → API keys → New API key, and give it the Admin role. (Developer-scoped keys can't provision the per-service Query API endpoint that
    cloud service query
    uses.)
  2. In a separate terminal, run:
    bash
    clickhousectl cloud auth login --api-key <key-id> --api-secret <key-secret>
  3. Tell me when that's done and I'll re-check the auth status.
Poll until the API key row reports
Active
, then confirm with a real privileged call rather than trusting the status table alone. Use a ref-agnostic call here:
SERVICE_REF
may be a name, and
cloud service get
only accepts a UUID, so confirming with
get
would fail on a name for reasons unrelated to auth.
cloud service list
needs no ref and proves the API key works:
bash
clickhousectl cloud auth status
clickhousectl cloud service list --json | jq -r '.[].name'
If the list returns your services, you are authenticated; continue. The actual name-or-UUID resolution of
SERVICE_REF
happens in Step 4.
Expect to need the env-var credentials (common, not an edge case). Many
clickhousectl
builds save the credentials file but a freshly spawned shell (such as the one your tool calls run in) doesn't read it, so
auth status
shows
Active
yet the very next
clickhousectl
call reports
No credentials found
. Rather than treat this as a rare fallback, write a small sourceable creds file once, then load it in every later shell. This keeps each subsequent shell to a single
.
line instead of two
jq
re-derivations, and keeps the secret out of the chat:
bash
undefined
检查
clickhousectl
是否在
PATH
中。单独运行此存在性检查不要与安装命令链式执行:
|| curl … | sh
形式会将无害的检查拖入复合命令,沙箱会将其整体拒绝为不受信任的代码下载。
bash
which clickhousectl
仅当命令无输出时,才进行安装(用户可能需要明确批准此操作,见步骤1):
bash
curl -fsSL https://clickhouse.com/cli | sh
检查认证状态:
bash
clickhousectl cloud auth status
本技能需要API密钥认证:OAuth为只读权限,无法创建用户或执行写入查询。若
API key
行未显示
Active
,用户必须进行认证。
不要要求用户将API密钥和密钥粘贴到对话中。粘贴到对话中的任何内容都会保留在记录中,后续必须轮换。相反,要求用户在独立终端中进行认证,完成后告知您:
我需要ClickHouse Cloud的Admin API密钥来创建采集用户并验证数据。 请不要在此处粘贴密钥。请按以下步骤操作:
  1. Cloud控制台中,打开Organization → API keys → New API key,并为其分配Admin角色。(Developer范围的密钥无法提供
    cloud service query
    使用的每个服务的Query API端点。)
  2. 独立终端中运行:
    bash
    clickhousectl cloud auth login --api-key <key-id> --api-secret <key-secret>
  3. 完成后告知我,我将重新检查认证状态。
轮询直到API密钥行显示
Active
,然后通过实际的特权调用确认,而非仅信任状态表。此处使用与引用无关的调用:
SERVICE_REF
可能是名称,而
cloud service get
仅接受UUID,因此使用
get
确认会因名称问题失败,与认证无关。
cloud service list
无需引用,可证明API密钥有效:
bash
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
重新推导,且可避免密钥出现在对话中:
bash
undefined

Write a private, sourceable creds file next to collector.env.

在collector.env旁边写入私有、可source的凭证文件。

( 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"

**From now on, open every shell that calls `clickhousectl` with both loads**, because env vars do
not persist across shells:

```bash
. "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
Re-run the
service list
check above with the creds loaded; it should now succeed. Do not continue until a real call works. (If
clickhousectl auth status
already shows
API key … Active
and calls succeed without
creds.env
, you can skip this; but most agent shells need it.)

( 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之间持久化:

```bash
. "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
加载凭证后重新运行上述
service list
检查;应成功执行。在实际调用成功前不要继续。(若
clickhousectl auth status
已显示
API key … Active
且调用无需
creds.env
即可成功,可跳过此步骤;但大多数代理shell需要此步骤。)

Step 4: Resolve the service and capture the HTTPS endpoint

步骤4:解析服务并捕获HTTPS端点

Run the standard preamble (Step 2) so the paths, credentials, and config are all loaded in this shell, then resolve the service. If
SERVICE_REF
is a UUID, use it directly; otherwise look it up by name:
bash
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
bash
undefined
运行标准前置代码(步骤2),使路径、凭证和配置均加载到当前shell中,然后解析服务。若
SERVICE_REF
是UUID,直接使用;否则按名称查找:
bash
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
bash
undefined

UUID form

UUID格式

clickhousectl cloud service get "$SERVICE_REF" --json > "$WORKDIR/svc.json"
clickhousectl cloud service get "$SERVICE_REF" --json > "$WORKDIR/svc.json"

Name form (note the double quotes: service names can contain spaces or apostrophes,

名称格式(注意双引号:服务名称可能包含空格或撇号,例如"Alex's test")

e.g. "Alex's test")

clickhousectl cloud service list --json
| jq --arg n "$SERVICE_REF" '.[] | select(.name==$n)' > "$WORKDIR/svc.json"

Extract the values you need, coercing the port to an integer. The port serializes as a float
(`8443.0`); if `:8443.0` leaks into the endpoint the collector's ClickHouse exporter cannot dial
it:

```bash
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")
clickhousectl cloud service list --json
| jq --arg n "$SERVICE_REF" '.[] | select(.name==$n)' > "$WORKDIR/svc.json"

提取所需的值,将端口转换为整数。端口会序列化为浮点数(`8443.0`);若`:8443.0`泄漏到端点中,收集器的ClickHouse导出器将无法连接:

```bash
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.

将解析后的值持久化回环境文件,供后续步骤和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` must be `running`. If it is `stopped` or `starting`, ask the user to start the service (or
wait), and do not proceed. ClickHouse Cloud services **idle-suspend**, so even a "running" service
can be asleep; the next query both checks reachability and wakes it:

```bash
clickhousectl cloud service query --id "$SERVICE_ID" --query "SELECT version()"
A successful response confirms the service is awake and that the per-service Query API key is provisioned. On the first call
clickhousectl
prints
Provisioning Query API endpoint + key for service '<name>'...
, which is expected.

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”状态的服务也可能处于休眠状态;下一个查询将同时检查可达性并唤醒服务:

```bash
clickhousectl cloud service query --id "$SERVICE_ID" --query "SELECT version()"
成功响应确认服务已唤醒,且每个服务的Query API密钥已配置。首次调用时
clickhousectl
会打印
Provisioning Query API endpoint + key for service '<name>'...
,这是预期行为。

Step 5: Create the
hyperdx_ingest
SQL user and grant it
otel.*

步骤5:创建
hyperdx_ingest
SQL用户并授予
otel.*
权限

This step is the same on both paths: the collector (new or existing) authenticates to ClickHouse as
hyperdx_ingest
. Open the shell with the combined load so
$CLICKHOUSE_PASSWORD
(and credentials) are set.
Expect an approval prompt here. The
CREATE USER
/
GRANT
statements below are DDL against a Cloud service, so some agent sandboxes flag them as "modifying shared production infrastructure" even when
clickhousectl
is allowlisted. This is expected; the operations are scoped to a single dedicated ingest user and the
otel
schema, and the user should approve them explicitly when prompted.
Never put the plaintext password in the SQL. Hash it locally and use
sha256_hash
.
Two problems rule out
IDENTIFIED WITH sha256_password BY '$CLICKHOUSE_PASSWORD'
: the secret would land in the process arg list (visible in
ps
) and shell history, and, critically, the Query API echoes the failing statement verbatim in its error JSON, so any error (a transient failure, a charset slip) leaks the password into output an agent may surface. Passing it over stdin does not help, the error echo still contains it. Instead compute the SHA-256 hash of the password locally (
sha256_hash
stores exactly what
sha256_password
would, so the collector still logs in with the plaintext from the env file) and put only the hash in the statement. A hash is non-reversible, so even an echoed error cannot leak the password:
bash
WORKDIR="${WORKDIR:-$HOME/clickstack-otel-collector}"; ENV_FILE="$WORKDIR/collector.env"
[ -f "$WORKDIR/creds.env" ] && . "$WORKDIR/creds.env"; set -a; . "$ENV_FILE"; set +a
此步骤对两种路径均相同:收集器(新收集器或现有收集器)以
hyperdx_ingest
身份认证到ClickHouse。打开shell并同时加载凭证,确保
$CLICKHOUSE_PASSWORD
(和其他凭证)已设置。
预期会出现批准提示:以下
CREATE USER
/
GRANT
语句是针对Cloud服务的DDL操作,因此即使
clickhousectl
已加入白名单,某些代理沙箱仍会将其标记为“修改共享生产基础设施”。这是预期行为;操作仅针对单个专用采集用户和
otel
模式,用户在提示时应明确批准。
切勿在SQL中使用明文密码。在本地哈希密码并使用
sha256_hash
。有两个问题排除了使用
IDENTIFIED WITH sha256_password BY '$CLICKHOUSE_PASSWORD'
的可能:密钥会出现在进程参数列表中(可通过
ps
查看)和shell历史记录中,更关键的是,Query API会在错误JSON中逐字回显失败的语句,因此任何错误(临时故障、字符集错误)都会将密码泄漏到代理可能显示的输出中。通过stdin传递也无济于事,错误回显仍会包含密码。相反,在本地计算密码的SHA-256哈希(
sha256_hash
存储的内容与
sha256_password
完全相同,因此收集器仍可使用环境文件中的明文登录),并仅将哈希值放入语句中。哈希值不可逆转,因此即使错误回显也不会泄漏密码:
bash
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).

密码的SHA-256哈希值。openssl已是依赖项;此命令可跨平台(macOS + Linux)运行。

Only this hash ever reaches SQL, output, or
ps
; the plaintext stays in the env file.

只有哈希值会进入SQL、输出或
ps
;明文密码始终保存在环境文件中。

PW_HASH=$(printf %s "$CLICKHOUSE_PASSWORD" | openssl dgst -sha256 | awk '{print $NF}')
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

逐个发送语句:Query API通过HTTP运行,拒绝多语句输入("Multi-statements are not allowed"),因此单个分号分隔的批处理会失败。

("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'"
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'"

Grant the least privilege the collector needs to create and write the `otel.*` schema. On the
current image the schema migrations and their version table also live in `otel`, so `otel.*` is
sufficient (this statement carries no secret):

```bash
clickhousectl cloud service query --id "$SERVICE_ID" --query \
  "GRANT SELECT, INSERT, CREATE DATABASE, CREATE TABLE, CREATE VIEW ON otel.* TO hyperdx_ingest"
Older image builds: some earlier collector versions ran their goose migrations against a version table in the
default
database, so startup looped on
ACCESS_DENIED
until
default.*
was also granted. If you see
ACCESS_DENIED
referencing
default
in the collector logs (Step 6), add this and restart the container:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query \
  "GRANT SELECT, INSERT, CREATE TABLE ON default.* TO hyperdx_ingest"
Verify:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query "SHOW GRANTS FOR hyperdx_ingest"
You should see
GRANT SELECT, INSERT, CREATE DATABASE, CREATE TABLE, CREATE VIEW ON otel.* TO hyperdx_ingest
.

clickhousectl cloud service query --id "$SERVICE_ID" --query
"ALTER USER hyperdx_ingest IDENTIFIED WITH sha256_hash BY '$PW_HASH'"

授予收集器创建和写入`otel.*`模式所需的最小权限。在当前镜像中,模式迁移及其版本表也位于`otel`中,因此`otel.*`权限已足够(此语句不包含密钥):

```bash
clickhousectl cloud service query --id "$SERVICE_ID" --query \
  "GRANT SELECT, INSERT, CREATE DATABASE, CREATE TABLE, CREATE VIEW ON otel.* TO hyperdx_ingest"
旧版镜像构建:某些早期收集器版本会在
default
数据库中的版本表上运行goose迁移,因此启动时会因
ACCESS_DENIED
错误循环,直到授予
default.*
权限。若在收集器日志(步骤6)中看到引用
default
ACCESS_DENIED
错误,添加以下权限并重启容器:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query \
  "GRANT SELECT, INSERT, CREATE TABLE ON default.* TO hyperdx_ingest"
验证权限:
bash
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

Step 6: Set up the collector

步骤6:配置收集器

Follow the sub-section that matches the path and mode you chose in Step 0. All three converge on the same end state: a collector accepting OTLP and writing into the
otel
database on the service. Every code block in this step assumes you have run the standard preamble (Step 2) first, so
$WORKDIR
,
$ENV_FILE
,
$SERVICE_ID
, and the secrets are set in the shell.
Make sure Docker is running (new-collector path only):
bash
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
按照步骤0中选择的路径和模式执行相应的子步骤。所有三种方式最终都会实现相同的状态:收集器接收OTLP数据并写入服务的
otel
数据库。此步骤中的所有代码块均假设您已先运行标准前置代码(步骤2),因此
$WORKDIR
$ENV_FILE
$SERVICE_ID
和密钥已在shell中设置。
确保Docker正在运行(仅新收集器路径适用):
bash
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: New collector with Docker Compose (
DEPLOY_MODE=compose
)

步骤6a:使用Docker Compose部署新收集器(
DEPLOY_MODE=compose

Write a Compose file in the working directory. It reads the same
collector.env
for secrets, publishes the OTLP and health ports, and pins a named network so the telemetry generator in Step 7 can reach the collector by container name:
bash
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文件。文件读取相同的
collector.env
获取密钥,发布OTLP和健康检查端口,并固定命名网络,以便步骤7中的遥测数据生成器可通过容器名称访问收集器:
bash
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

Compose不会采用非自身创建的clickstack-net(例如来自docker run路径、之前失败的Compose运行或DEPLOY_MODE切换的遗留网络),会失败并提示"network clickstack-net was found but has incorrect label"。若存在无容器连接的孤立网络,需将其删除,以便Compose使用自己的标签重新创建。

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 creates the `clickstack-net` network for you (the guard above clears an orphaned one from a
prior run first). Skip to **Step 6d** to confirm health.
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`网络(上述防护代码会先清除之前运行遗留的孤立网络)。跳至**步骤6d**确认健康状态。

Step 6b: New collector with individual Docker commands (
DEPLOY_MODE=run
)

步骤6b:使用单独的Docker命令部署新收集器(
DEPLOY_MODE=run

Create a user-defined network so the telemetry generator in Step 7 can reach the collector by container name:
bash
docker network create clickstack-net 2>/dev/null || true
Start the collector, passing all secrets via
--env-file
(never
-e
, which would put the secret on the command line, in shell history, and in
ps
). The
docker rm -f
first makes the step safe to re-run:
bash
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
The image reads
OTLP_AUTH_TOKEN
,
CLICKHOUSE_ENDPOINT
,
CLICKHOUSE_USER
,
CLICKHOUSE_PASSWORD
, and
HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE
from the env file. It enables bearer-token auth on the OTLP receiver with an empty scheme, so callers send the raw token as the
authorization
header (no
Bearer 
prefix). Continue to Step 6d.
创建用户定义的网络,以便步骤7中的遥测数据生成器可通过容器名称访问收集器:
bash
docker network create clickstack-net 2>/dev/null || true
启动收集器,通过
--env-file
传递所有密钥
(切勿使用
-e
,否则密钥会出现在命令行、shell历史记录和
ps
中)。先执行
docker rm -f
确保步骤可安全重新运行:
bash
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 
前缀)。继续执行步骤6d

Step 6c: Configure your existing collector (
COLLECTOR_PATH=existing
)

步骤6c:配置现有收集器(
COLLECTOR_PATH=existing

Add the ClickHouse exporter to your existing collector configuration. The config below matches the behavior of the ClickStack distribution, including the Session Replay (
rrweb
) routing path, and writes into the
otel
database the ClickStack UI expects.
Reference the endpoint and password as environment variables (
${env:…}
), do not hardcode them into the config file.
The contrib collector expands
${env:VAR}
at load time, so keeping the plaintext password out of the config file is both safer and consistent with the rest of this skill. Start your collector with the env vars available, the simplest way is the same
--env-file
the local collector uses:
bash
undefined
将ClickHouse导出器添加到现有收集器的配置中。以下配置与ClickStack分发版的行为一致,包括会话重放(
rrweb
)路由路径,并写入ClickStack UI期望的
otel
数据库。
将端点和密码引用为环境变量(
${env:…}
),不要硬编码到配置文件中
。contrib收集器会在加载时展开
${env:VAR}
,因此将明文密码保留在配置文件外既更安全,也与本技能的其余部分保持一致。启动收集器时需确保环境变量可用,最简单的方式是使用本地收集器使用的相同
--env-file
bash
undefined

When running the contrib collector in Docker, pass collector.env so ${env:CLICKHOUSE_*} resolve:

在Docker中运行contrib收集器时,传递collector.env以便${env:CLICKHOUSE_*}解析:

docker run -d --env-file "$ENV_FILE" -p 4317:4317 -p 4318:4318 \

docker run -d --env-file "$ENV_FILE" -p 4317:4317 -p 4318:4318 \

-v "$WORKDIR/your-config.yaml:/etc/otelcol-contrib/config.yaml:ro" \

-v "$WORKDIR/your-config.yaml:/etc/otelcol-contrib/config.yaml:ro" \

otel/opentelemetry-collector-contrib:latest

otel/opentelemetry-collector-contrib:latest

For a non-Docker collector, export CLICKHOUSE_ENDPOINT and CLICKHOUSE_PASSWORD into its

对于非Docker收集器,在启动前将CLICKHOUSE_ENDPOINT和CLICKHOUSE_PASSWORD导出到其环境中(例如systemd单元中的EnvironmentFile=)。

environment (e.g. an EnvironmentFile= in the systemd unit) before it starts.


Add this to your collector config and reload it:

```yaml
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]
Notes for this path:
  • If you use your own distribution, ensure it includes the ClickHouse exporter. The upstream contrib image already does.
  • Authentication on the OTLP receivers is your existing setup. The
    OTLP_AUTH_TOKEN
    generated in Step 2 is not used here unless you wire it into your own auth (for example
    bearertokenauth
    ).
  • After reloading, skip the health check below (that is specific to the local container) and go straight to Step 7 to send a verification burst (point the generator at your own collector's OTLP endpoint).

将以下内容添加到收集器配置中并重新加载:

```yaml
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接收器的认证由您的现有配置决定。步骤2中生成的
    OTLP_AUTH_TOKEN
    仅在您将其接入自己的认证(例如
    bearertokenauth
    )时才会使用。
  • 重新加载后,跳过以下健康检查(仅适用于本地容器),直接进入步骤7发送验证数据(将生成器指向您自己收集器的OTLP端点)。

Step 6d: Confirm the local collector is healthy (new-collector path)

步骤6d:确认本地收集器健康(仅新收集器路径适用)

bash
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
A healthy start shows the seed migrations running to completion (
[seed] OK ...
lines ending in
goose: up to current file version: N
), then
Everything is ready. Begin running and processing data.
(or equivalent),
docker ps
reporting
Up ... (healthy)
, and the health check returning HTTP 200. A seed line like
ClickHouse 25.12 < 26.2, falling back to compatibility logs and traces schemas
on an older server version is expected and harmless, not an error; do not pause on it. If instead the container exits, the cause is almost always in the seed step:
  • code: 516, Authentication failed: password is incorrect
    ->
    CLICKHOUSE_PASSWORD
    is empty or wrong in the env file. The most common slip is storing the password under a different key name (it must be
    CLICKHOUSE_PASSWORD
    ), or using a password containing
    @ : / ? # %
    , which corrupts the migration tool's connection URL.
  • [HTTP 403]
    /
    data size should be 0 < <huge number>
    at "server hello" -> same root cause: an empty/wrong password against the HTTPS endpoint.
  • TLS / dial errors ->
    CLICKHOUSE_ENDPOINT
    is malformed (it must be
    https://<host>:8443
    , with no
    .0
    on the port).
  • ACCESS_DENIED
    referencing
    default
    -> only on older image builds; apply the
    default.*
    grant from the Step 5 note and restart.

bash
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。
  • [HTTP 403]
    /
    data size should be 0 < <huge number>
    在“server hello”时出现 → 根本原因相同:HTTPS端点使用的密码为空或错误。
  • TLS / 连接错误 →
    CLICKHOUSE_ENDPOINT
    格式错误(必须为
    https://<host>:8443
    ,端口后不能有
    .0
    )。
  • ACCESS_DENIED
    引用
    default
    → 仅旧版镜像构建会出现;应用步骤5备注中的
    default.*
    权限并重启容器。

Step 7: Send rich synthetic telemetry and verify ingestion

步骤7:发送丰富的合成遥测数据并验证采集

Use
telemetrygen
(the OpenTelemetry Collector Contrib generator) from its Docker image, so nothing is installed on the host. Instead of one flat burst, send telemetry across several services, severities, span statuses, and metric types, so ClickStack's Search, Service Map, and dashboards have realistic, varied data rather than a single uniform stream.
Load the env file so the token is available, then reference
$OTLP_AUTH_TOKEN
. The
tg
helper below redirects all generator output to a log file and prints only an exit code, because
telemetrygen
echoes its full config, including the
authorization
header (your OTLP token)
, to stdout. Never surface that raw output in the chat.
telemetrygen
's header syntax requires the value to be a quoted string:
key="value"
.
bash
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=$?"
}
Existing-collector path: set
NET
and
ENDPOINT
to reach your collector instead. If it runs on this host, use
--network host
style access or point
ENDPOINT
at its published address, and set the
authorization
header (or other auth) to whatever your receiver expects. Everything below is otherwise identical.
Judge success by exit code and row counts, never by the generator's logs. Two reasons. First, the log contains your OTLP token (see above), so do not print it. Second, it is noisy and every run ends with
rpc error: code = Canceled desc = grpc: the client connection is closing
once
--duration
elapses, which is expected shutdown, not a failure. The
tg
helper already prints
<signal> exit=0
on success. If you must inspect a failure, grep the log for the real signal without dumping it, for example
grep -c Unauthenticated "$TG_LOG"
(a non-zero count plus a non-zero exit means the
authorization
header did not match). Confirm overall success with the row counts in the verification queries below.
Quote attribute values so the inner double quotes survive the shell.
telemetrygen
requires each attribute as
key="value"
(with literal double quotes), and rejects a bare
key=value
with
value should be a string wrapped in double quotes
. If you write
--otlp-attributes deployment.environment="production"
, bash strips the quotes and the container receives
deployment.environment=production
, which hard-fails. Wrap the whole argument in single quotes so the inner double quotes reach the container, exactly as the
tg
helper already does for the auth header.
Logs across two services with different severities and bodies, including an error line:
bash
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"'
Traces with child spans, a healthy service and an erroring one (this is what populates the Service Map and the error views):
bash
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"'
Metrics across the three common types, so dashboards have gauges, counters, and a distribution:
bash
tg metrics --service checkout --metric-type Sum
tg metrics --service checkout --metric-type Gauge
tg metrics --service payment  --metric-type Histogram
(
--metric-type
accepts
Gauge
,
Sum
,
Histogram
, or
ExponentialHistogram
. Add
--otlp-http
with
--otlp-endpoint clickstack-otel-collector:4318
to exercise the HTTP path instead of gRPC.)
Wait ~15 seconds for the collector to flush its batch, then confirm the tables exist:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query \
  "SELECT name FROM system.tables WHERE database='otel' ORDER BY name"
Then confirm rows are landing. Count by
parts.rows
, which is signal-agnostic and avoids hard-coding per-signal column names:
bash
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"
You should see non-zero
rows
for
otel_logs
,
otel_traces
,
otel_metrics_sum
,
otel_metrics_gauge
, and
otel_metrics_histogram
. If a signal is missing:
  1. Tail the collector logs (
    docker logs --tail 50 clickstack-otel-collector
    ) for export errors.
  2. Confirm the
    authorization
    header matches
    $OTLP_AUTH_TOKEN
    :
    grep -c Unauthenticated "$TG_LOG"
    (a non-zero count means a mismatch, the full message is
    code = Unauthenticated desc = provided authorization does not match expected scheme or token
    ). Grep rather than print the log, since it contains the token.
  3. Re-check
    CLICKHOUSE_ENDPOINT
    has the
    https://
    scheme and
    :8443
    port.
  4. Some metric kinds flush slowly. Re-run the count after another 30 seconds before declaring failure.
Do not proceed until every expected signal has non-zero rows.

使用
telemetrygen
(OpenTelemetry Collector Contrib生成器)的Docker镜像,无需在主机上安装任何内容。不要发送单一的扁平数据,而是发送跨多个服务严重级别链路状态指标类型的遥测数据,使ClickStack的搜索功能、服务地图和仪表盘拥有真实多样的数据,而非单一统一的数据流。
加载环境文件以获取令牌,然后引用
$OTLP_AUTH_TOKEN
。以下
tg
助手会将所有生成器输出重定向到日志文件,仅打印退出代码,因为
telemetrygen
会回显其完整配置,**包括
authorization
头(您的OTLP令牌)**到标准输出。切勿在对话中显示原始输出。
telemetrygen
的头语法要求值为带引号的字符串:
key="value"
bash
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() {
  # 使用方法:tg <logs|traces|metrics> [额外的telemetrygen参数...]
  # 输出(包含回显配置中的令牌)会写入$TG_LOG,不会显示在终端。
  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令牌(如上所述),因此不要打印;其次,日志内容繁杂,每次运行结束时都会出现
rpc error: code = Canceled desc = grpc: the client connection is closing
,这是
--duration
结束后的预期关闭,并非故障
tg
助手会在成功时打印
<signal> exit=0
。若必须检查故障,可在日志中搜索真实信号而非完整打印,例如
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
助手对认证头的处理一样。
发送跨两个服务、不同严重级别和内容的日志,包括一条错误日志:
bash
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"'
发送包含子链路、健康服务和错误服务的链路追踪数据(这会填充服务地图和错误视图):
bash
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"'
发送三种常见类型的指标,使仪表盘拥有仪表图、计数器和分布数据:
bash
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秒让收集器刷新批处理,然后确认表已存在:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query \
  "SELECT name FROM system.tables WHERE database='otel' ORDER BY name"
然后确认数据已写入。通过
parts.rows
计数,该方式与信号类型无关,无需硬编码每个信号的列名:
bash
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
值非零。若某个信号缺失:
  1. 查看收集器日志尾部(
    docker logs --tail 50 clickstack-otel-collector
    )寻找导出错误。
  2. 确认
    authorization
    头与
    $OTLP_AUTH_TOKEN
    匹配:
    grep -c Unauthenticated "$TG_LOG"
    (非零计数加非零退出码表示不匹配,完整消息为
    code = Unauthenticated desc = provided authorization does not match expected scheme or token
    )。仅搜索日志而非打印,因为日志包含令牌。
  3. 重新检查
    CLICKHOUSE_ENDPOINT
    是否包含
    https://
    协议和
    :8443
    端口。
  4. 某些指标类型刷新较慢。在判定失败前,等待30秒后重新运行计数。
在所有预期信号的行数均非零前不要继续。

Step 8: Confirm the service is awake, then complete onboarding in ClickStack

步骤8:确认服务活跃,完成ClickStack入门流程

Rows in ClickHouse are not the same as the user seeing telemetry in ClickStack. The ClickStack UI requires a one-time onboarding step that auto-detects the data sources, and that step fails if the ClickHouse service has idle-suspended in the meantime.
First, confirm the service is awake. Do not skip this; it is the most common reason onboarding shows no sources. Run a real query and require it to succeed:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query "SELECT 1"
If this returns
1
, the service is awake; continue immediately to the console steps below while it stays warm. If it errors or times out, the service was asleep and this call is waking it: wait a few seconds and re-run until it returns
1
. Only proceed once it succeeds.
Then walk the user through onboarding explicitly. Do not just say "done"; spell out each click, because the sources only appear after this flow is completed:
  1. Go to the ClickHouse Cloud console and open the target service.
  2. In the left-hand menu, select ClickStack.
  3. Click through to Getting Started and follow the onboarding flow.
  4. Ignore any prompt that asks you to set up or configure a collector / start ingestion. You have already done that in the steps above. Skip straight past those screens (click through / "Next") to source detection. Re-running the console's collector setup is unnecessary and only causes confusion.
  5. The data sources are auto-detected: logs, traces, and metrics for the
    otel
    database are picked up automatically, and your data appears in the Search and dashboard views.
The direct link is
https://console.clickhouse.cloud/services/<SERVICE_ID>/clickstack
(substitute
$SERVICE_ID
).
If source detection shows nothing, the service almost certainly idle-suspended between the data send and the console step. Re-run the
SELECT 1
wake query above for the user, then have them re-run the detection, rather than leaving them to debug an opaque failure.

ClickHouse中的数据不等于用户在ClickStack中看到遥测数据。ClickStack UI需要一次性入门步骤来自动检测数据源,若ClickHouse服务在此期间空闲暂停,该步骤会失败。
首先,确认服务活跃。不要跳过此步骤;这是入门流程未显示数据源的最常见原因。运行真实查询并确保成功:
bash
clickhousectl cloud service query --id "$SERVICE_ID" --query "SELECT 1"
若返回
1
,则服务活跃;请立即继续以下控制台步骤,保持服务处于活跃状态。若出现错误或超时,说明服务处于休眠状态,此调用正在唤醒服务:等待几秒后重新运行,直到返回
1
。仅在成功后继续。
然后明确引导用户完成入门流程。不要只说“完成”;需详细说明每一步,因为只有完成此流程后数据源才会显示:
  1. 前往ClickHouse Cloud控制台并打开目标服务。
  2. 左侧菜单中选择ClickStack
  3. 进入Getting Started并跟随入门流程操作。
  4. 忽略任何要求您设置或配置收集器/开始采集的提示。您已在上述步骤中完成了这些操作。直接跳过这些屏幕(点击“Next”)进入数据源检测。重新运行控制台的收集器设置毫无必要,只会造成混淆。
  5. 数据源会自动检测
    otel
    数据库的日志、链路追踪和指标会被自动识别,您的数据会显示在搜索和仪表盘视图中。
直接链接为
https://console.clickhouse.cloud/services/<SERVICE_ID>/clickstack
(替换
$SERVICE_ID
)。
若数据源检测未显示任何内容,几乎可以肯定是在发送数据和控制台步骤之间服务空闲暂停了。为用户重新运行
SELECT 1
唤醒查询,然后让他们重新运行检测,而非让他们调试模糊的故障。

Step 9: Summarize and hand off (without echoing secrets)

步骤9:总结并交接(不回显密钥)

Print a summary in roughly this format. Note the token is referenced, not printed, the SQL password is not shown at all, and the collector keeps running until the user stops it. Adjust the "how to stop" line to the deploy mode they chose.
✅ 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
Then tell the user, in your own words, that:
  1. All secrets live in
    <WORKDIR>/collector.env
    (mode
    0600
    ). Nothing sensitive was pasted into this chat or passed on a
    docker run
    command line.
  2. The collector keeps running until they stop it. For Compose:
    cd <WORKDIR> && docker compose down
    stops it,
    docker compose up -d
    brings it back. For individual Docker:
    docker stop clickstack-otel-collector
    and
    docker start clickstack-otel-collector
    .
  3. Any application, SDK, or agent on this host can now send OTLP to
    localhost:4317
    (gRPC) or
    localhost:4318
    (HTTP) with the
    authorization
    header from the env file.
  4. The ClickHouse Cloud service idle-suspends. If ClickStack later shows no recent data, the service may simply be asleep; sending new telemetry or running any query wakes it.

打印大致如下格式的总结。注意令牌仅被引用,不打印,SQL密码完全不显示,收集器会持续运行直到用户停止。根据用户选择的部署模式调整“如何停止”的内容。
✅ 已为服务<SERVICE_NAME>(<SERVICE_ID>)完成ClickStack设置并开始采集遥测数据。
   完成控制台中的入门流程(步骤8)以自动检测数据源并查看您的数据。

收集器信息
  ▸ 通过<Docker Compose | docker run>部署的新本地收集器 (或:已配置您的现有收集器)
  ▸ OTLP gRPC发送地址:localhost:4317
  ▸ OTLP HTTP发送地址:localhost:4318
  ▸ 健康检查地址:      http://localhost:13133/   (仅本地收集器)
  ▸ 必填请求头:       authorization: <OTLP令牌>
       (获取方式:  grep OTLP_AUTH_TOKEN <WORKDIR>/collector.env)

ClickHouse目标信息
  ▸ 端点:<CLICKHOUSE_ENDPOINT>
  ▸ SQL用户:hyperdx_ingest   (密码存储在<WORKDIR>/collector.env,权限0600)
  ▸ 数据库:otel

在ClickHouse Cloud控制台完成后续操作:
  ▸ 打开服务,在左侧菜单中选择ClickStack,然后进入Getting Started,
    完成入门流程以自动检测数据源。
  ▸ https://console.clickhouse.cloud/services/<SERVICE_ID>/clickstack
然后用您自己的语言告知用户:
  1. 所有密钥存储在
    <WORKDIR>/collector.env
    中(权限0600)。任何敏感内容均未粘贴到此对话中,也未在
    docker run
    命令行中传递。
  2. 收集器会持续运行直到用户停止。对于Compose部署:
    cd <WORKDIR> && docker compose down
    停止服务,
    docker compose up -d
    重新启动。对于单独的Docker部署:
    docker stop clickstack-otel-collector
    停止,
    docker start clickstack-otel-collector
    启动。
  3. 本机上的任何应用、SDK或代理现在均可将OTLP数据发送到
    localhost:4317
    (gRPC)或
    localhost:4318
    (HTTP),并附带环境文件中的
    authorization
    头。
  4. ClickHouse Cloud服务会空闲暂停。若ClickStack后续未显示最新数据,可能是服务处于休眠状态;发送新的遥测数据或运行任何查询即可唤醒服务。

Cleanup (only if the user explicitly asks)

清理(仅当用户明确要求时执行)

bash
undefined
bash
undefined

Docker Compose deployment:

Docker Compose部署:

( cd "$WORKDIR" && docker compose down )
( cd "$WORKDIR" && docker compose down )

Individual Docker deployment:

单独的Docker部署:

docker rm -f clickstack-otel-collector docker network rm clickstack-net 2>/dev/null || true
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"
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"

rm -f "$WORKDIR/collector.env" "$WORKDIR/svc.json" "$WORKDIR/docker-compose.yaml"


Do **not** drop the `otel` database: it contains telemetry the user may want to retain.

请勿删除`otel`数据库:它包含用户可能需要保留的遥测数据。