Superlog 自托管安装、资源占用与限制
了解 Superlog 自托管实际安装的组件:Postgres、ClickHouse、OpenTelemetry Collector 和 4 个 Node 服务,以及无 release tags、需自行固定提交和 VPS 资源占用等限制。
自行托管 Superlog 实际会安装什么
要自行托管 Superlog,您需要克隆代码仓库,使用 Docker Compose 启动 Postgres、ClickHouse 和 OpenTelemetry collector,执行一次数据库迁移,然后从源代码启动 4 个 Node 服务。您的应用会将 OTLP(OpenTelemetry 协议)跟踪、日志和指标发送到接收端口。Superlog 会为这些数据生成指纹,将重复出现的数据归并为一个事件,并由代理生成第一轮排查结果。安装需要一个下午。开始前,最值得了解的是它的资源占用和实际限制。
Superlog 采用 Apache 2.0 许可证,代码位于 github.com/superloglabs/superlog。截至 2026 年 8 月,该项目约有 1.2k 个 stars,在 main 上大约有 460 次提交,并且完全没有 release tags。最后这一点会影响安装方式:git checkout v1.0.0 中没有可供检出的内容,因此您需要自行固定一个提交,或者直接运行克隆当天早上 main 中恰好存在的版本。
Superlog 能回答哪些问题,而 Uptime Kuma 和 Langfuse 不能
从外部看,自托管监控工具似乎可以互相替代。但事实并非如此。选错工具,只会占用服务器资源,却得不到任何收益。
- Uptime Kuma 从外部探测您的端点,只回答一个问题:服务是否正常。
- Zabbix 在 Ubuntu 24.04 上监控主机和服务,根据您设置的阈值检查 CPU、内存、磁盘和服务状态。
- Langfuse 跟踪 LLM 调用,记录每次调用的提示词、模型、token 数量、延迟和成本。
- Superlog 使用普通服务已经产生的遥测数据,将重复故障转换为事件。
Superlog 负责回答另一个问题:哪里发生了故障,具体坏了什么,以及原因是什么。它不处理 LLM 调用,也不会从外部探测您的服务。它接收普通应用代码发送的 OTLP,并在故障分诊环节部署代理。这个环节本来就是值班人员通常执行的第一轮检查。
对于 VPS 预算而言,真正重要的区别在于存储。Uptime Kuma 只存储几千条检查结果,因此在 1 GB RAM 的服务器上也能正常运行。Superlog 使用列式存储,因为遥测数据写入一次后,还需要按时间范围查询数百万行数据。这正是 ClickHouse 的用途,而不是 Postgres 的用途。Postgres 仍然位于整个技术栈中,用于存储少量关系数据:项目、用户、事件和摄取密钥。
docker compose up -d 实际启动了什么?
3 个容器,其中没有 Superlog。原本以为一条命令就能完成安装的用户,通常会对此感到意外。
postgres:16,发布到主机的 5434 端口clickhouse/clickhouse-server:26.1,HTTP 使用 8123 端口,原生协议使用 9000 端口otel/opentelemetry-collector-contrib:0.150.1,gRPC 使用 4317 端口,基于 HTTP 的 OTLP 使用 4318 端口
Superlog 应用在主机上从源代码运行,由 pnpm dev 启动。截至 2026 年 8 月,代码仓库中没有用于生产环境的 compose 文件。因此,要长期运行这些应用,您需要围绕每个应用的 start 脚本自行编写 systemd unit,或者使用代码树中随附的各应用 Dockerfile。
请记住 span 经过的路径,因为下面的每个故障,都是其中一个跳转环节中断造成的。您的应用将 OTLP 发送到 Superlog 接收代理。代理使用您的 ingest key 验证请求,为请求写入项目 ID,然后将其转发给 collector。collector 删除客户端尝试设置的任何 superlog.* 属性,从代理提供的请求头中添加 superlog.project_id,然后批量写入 ClickHouse。Web 应用和 API 从 ClickHouse 读取遥测数据,再从 Postgres 读取其他所有数据。
删除这些属性是真正的多租户控制措施,而不是装饰性配置。如果没有这一步,任何持有有效 ingest key 的人都可以自行设置 superlog.project_id,并将数据写入其他项目。
VPS 需要多大规格?
对于低数据摄入量的单节点安装,建议按 4 vCPU、8 GB RAM 和 40 GB SSD 规划。这只是规划下限,不是测量结果,因此应将其作为起始规格,并根据您自己的流量进行验证。
内存主要分配给四个部分。ClickHouse 面向拥有充足 RAM 的机器设计,其默认配置也以此为前提。这里的 Postgres 16 占用较少,因为它存储的是元数据,而不是遥测数据。Collector 的占用也较少。四个 Node 进程则不同:一个 Vite 开发服务器和三个 tsx watch 进程各自都可能占用数百 MB,因此在 2 GB 的服务器上运行 pnpm dev 会非常困难。
磁盘是更容易被忽视的问题。在尚未摄入任何 span 之前,pnpm install 就会在这个 monorepo 中拉取 AWS SDK、ClickHouse 客户端、OpenTelemetry SDK 和 React 工具链。之后 ClickHouse 还会随流量增长。请同时测量这两项:
df -h /
free -m
docker stats --no-stream
docker compose exec clickhouse clickhouse-client --database superlog --query "SELECT table, formatReadableSize(sum(bytes_on_disk)) AS size FROM system.parts WHERE active AND database = 'superlog' GROUP BY table ORDER BY sum(bytes_on_disk) DESC"在低流量下,少量服务每分钟发送几百个 span,服务器负载较低,ClickHouse 大部分时间处于空闲状态。真正造成压力的是突发流量:一次有问题的部署可能会在一分钟内产生数千条相同错误。指纹聚合会将这些错误合并为读者看到的一个事件,但 ClickHouse 仍会在底层写入每一行数据。
保留期限由您设置。Collector 的 ClickHouse exporter 会创建这些表:otel_traces、otel_logs,以及每种指标类型对应的一张表。只有当 infra/collector/config.yaml 中的配置设置了 TTL 时,它才会应用数据保留期限。数据不会自动过期,因此如果不提前规划,繁忙运行一个月就可能耗尽磁盘空间。
从固定提交安装
git clone https://github.com/superloglabs/superlog.git
cd superlog
git tag -l
git log -1 --format='%H %cs %s'截至 August 2026,git tag -l 不输出任何内容才是预期结果。选择已测试的提交,并固定使用该提交:
git checkout 0d3a6c8bb63eda3493e6ba0003e7c2a70750bc1e接下来安装工具链:
node -v
corepack enable
corepack prepare pnpm@9.12.0 --activate
pnpm -vpackage.json 将 engines.node 声明为 >=20.0.0,并将 packageManager 声明为 pnpm@9.12.0。在较旧的 Node 上运行安装时,pnpm 会停止并显示 ERR_PNPM_UNSUPPORTED_ENGINE,其中会指出所需版本。Ubuntu 24.04 软件包归档中的 nodejs 版本低于 20,因此请从 NodeSource 或 nvm 安装 Node 20 或更高版本。仓库中包含 .nvmrc,因此如果已安装 nvm,nvm use 会选择指定的版本。
pnpm install
docker compose up -d
docker compose ps请等待健康检查完成,不要因为 up -d 显示就认为服务已就绪。Postgres 和 ClickHouse 都在 compose 文件中声明了健康检查:
curl -sS http://127.0.0.1:8123/ping
pg_isready -h 127.0.0.1 -p 5434 -U postgresClickHouse 响应 Ok.,而 pg_isready 响应 accepting connections。在 8123 端口上收到连接拒绝,表示容器仍在启动,或已经退出。docker compose logs clickhouse 可显示具体情况;如果内核因内存不足终止容器,docker inspect $(docker compose ps -q clickhouse) | grep -i oomkilled 会报告 true。这说明服务器配置过小,而不是配置文件有问题。
然后执行迁移并启动应用:
pnpm --filter @superlog/db db:migrate
pnpm dev注意端口是 5434,而不是 5432。compose 文件将 Postgres 发布到 5434,以避免与主机上已经安装的 Postgres 冲突;应用的 .env.example 文件也使用相同设置,并包含 DATABASE_URL=postgres://postgres:postgres@localhost:5434/superlog。如果在已经运行 Postgres 的服务器上将迁移指向 5432,可能会收到连接拒绝;更严重时,迁移可能会应用到错误的数据库。
pnpm dev 会启动仓库 Procfile 中列出的 4 个进程:api、web、worker 和 proxy。每个进程都会将输出同时写入 tmp/logs/,因此应在 tail -f tmp/logs/proxy.log 中监控 ingest。README 将 Web 应用配置在 http://localhost:5173,API 配置在 http://localhost:4100,OTLP 接收端配置在 http://localhost:4101。
在将任何客户端指向这些端口之前,先确认实际监听端口:
ss -lntp | grep -E '4100|4101|5173'
curl -sS http://127.0.0.1:4101/health这一点之后很重要。代理从 PORT 环境变量读取自身端口;如果 PORT 未设置,则回退到 4000。开发环境堆栈会自动设置该变量。自行编写的 systemd 单元不会设置它。因此,如果 exporter 指向 4101,而代理监听 4000,连接会被拒绝,且不会提供其他线索。
发送一条追踪,生成一个错误,查看一个事件
在 Web 应用中创建项目,并复制其摄取密钥。摄取端会使用该密钥验证每个请求,因此未携带密钥发送的遥测数据永远不会到达 ClickHouse。
将任意 OpenTelemetry SDK 指向摄取端,并使用标准环境变量:
export OTEL_SERVICE_NAME=checkout-api
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4101
export OTEL_EXPORTER_OTLP_HEADERS='x-api-key=YOUR_INGEST_KEY'摄取端从 x-api-key 标头读取密钥。如果导出器更容易通过其他方式配置,也可以使用 authorization: bearer YOUR_INGEST_KEY。它提供 3 个标准 OTLP 路径:/v1/traces、/v1/logs 和 /v1/metrics,以及 /health。
有一个容易踩坑的地方需要说明。OTEL_EXPORTER_OTLP_ENDPOINT 是基础 URL,SDK 会将信号路径追加到该 URL。信号专用变量(例如 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)会按原样使用,不会追加路径。将信号专用变量设置为 http://127.0.0.1:4101 后,每次导出都会向 / 发送请求。该地址不是有效路由,因此不会有任何数据到达;SDK 会记录导出失败,但应用看起来仍然正常。
对于 Node 服务,无代码路径就足以验证整个管道:
npm install @opentelemetry/api @opentelemetry/auto-instrumentations-node
node --require @opentelemetry/auto-instrumentations-node/register server.js现在故意制造一个故障。任何会抛出错误的路由都可以:
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/boom按顺序检查各个环节。第一个出现断点的地方就是失败环节:
tail -n 50 tmp/logs/proxy.log
docker compose exec clickhouse clickhouse-client --database superlog --query 'SELECT count() FROM otel_traces'如果 otel_traces 中的计数持续增加,但 Web 应用中没有数据,说明项目不匹配。请检查摄取密钥所属的项目。如果计数没有变化,但代理日志中有活动,问题可能出在收集器或写入 ClickHouse 的环节,请查看 docker compose logs collector。如果代理日志完全没有活动,说明导出器没有到达摄取端:可能是端口错误、路径错误,或密钥被拒绝。
在 Web 应用中,这些重复失败会合并为一个事件,而不是每个请求对应一行。Superlog 会为传入信号生成指纹,并将匹配的信号分组。这样,收件箱中显示的是一个事件,而不是 4,000 个相同错误。随后,代理会在该分组上记录调查结果。
调查步骤会调用模型,因此工作进程必须配置模型提供商。请从你固定版本的提交中、每个应用目录内的 .env.example 文件读取这些变量名,不要参考外部文章,因为这些变量会随 main 变化。GitHub 和 Sentry 集成也一样;它们各自的配置文档位于 docs/github-app-setup.md 和 docs/sentry-app-setup.md,Webhook 负载则记录在 docs/webhooks.md。
保持接收端私有,并让 agent 只读
Docker 默认会将容器端口发布到 0.0.0.0。这些已发布端口会绕过 ufw,因为 Docker 会将自己的规则写入 DOCKER-USER 链,而该链会在 ufw 处理数据包之前进行匹配。在具有公网 IP 的 VPS 上,compose 文件的默认配置会将 ClickHouse HTTP 发布到 8123,并将 Postgres 发布到 5434,因此互联网可以直接访问它们。该文件中的凭据是开发环境默认值:ClickHouse 用户为 default,密码为空;Postgres 则将 postgres 同时作为用户名和密码。
将它们绑定到 loopback。compose 文件中的每个已发布端口都通过环境变量设置主机端口,因此只需在仓库根目录创建一个 .env:
POSTGRES_HOST_PORT=127.0.0.1:5434
CLICKHOUSE_HTTP_HOST_PORT=127.0.0.1:8123
CLICKHOUSE_TCP_HOST_PORT=127.0.0.1:9000
COLLECTOR_GRPC_HOST_PORT=127.0.0.1:4317
COLLECTOR_HTTP_HOST_PORT=127.0.0.1:4318在信任结果之前先进行验证,然后重新创建容器:
docker compose config
docker compose up -d
ss -lntp | grep -E '5434|8123|9000|4317|4318'docker compose config 会输出解析后的文件内容,因此你可以直接查看 127.0.0.1:5434:5432,而不是凭猜测判断。此时 ss 应显示 127.0.0.1:5434,且不应出现 0.0.0.0:5434。不要尝试通过 compose override 文件重新声明 ports 来修复此问题,因为 Compose 会合并多个文件中的端口列表,而不是替换它们。这样最终会同时保留两个绑定,公网绑定仍然处于开放状态。
接收端也需要同样谨慎处理。你的 ingest key 会通过请求头传输,因此前面必须使用 TLS(传输层安全协议):在代理前使用 nginx 或 Caddy 终止 TLS,或者将 ingest 保持在私有网络或 WireGuard 隧道内。运行在 5173 上的 Web 应用是 Vite 开发服务器,根本不应暴露到互联网。
接下来是 agent 本身。Superlog 的定位是让 agent 调查问题并提出修复方案,重点在“提出”。在你观察它处理几起真实事件之前,应让它对生产环境保持只读。为 GitHub App 授予只读权限范围,并允许它创建 pull request,由你负责审核。能够读取遥测数据并生成补丁的 agent 很有用。能够重启服务的 agent 则具有完全不同级别的风险。是否授予这种权限,应由你明确决定,而不是沿用默认配置。成本也需要同样重视,因为每次调查都会调用模型:在将 agent 指向嘈杂的生产系统之前,先为 VPS 上的 agent 支出设定预算,并保留agent 实际执行操作的记录,这样出现意外的 pull request 时,背后会有可供审计的记录。
你会遇到的故障,以及用于描述这些故障的字符串
ERR_PNPM_UNSUPPORTED_ENGINE期间出现pnpm install,表示 Node 版本低于 20。node -v可在一行中确认这一点。- 迁移期间出现
ECONNREFUSED 127.0.0.1:5434,表示 compose stack 未启动,或DATABASE_URL指向了错误的端口。 - ClickHouse 反复重启通常是内存问题。先查看
docker compose logs clickhouse,然后检查容器的OOMKilled是否为true。 - 如果 exporter 报告成功,但 Web 应用仍为空,通常表示数据直接发送到了 4318 端口上的 collector,绕过了 proxy 执行的项目标记。
- 生产环境安装中,如果连接 4101 端口被拒绝,表示 proxy 回退到了
PORT=4000。在 unit file 中显式设置PORT。 docker compose ps显示0.0.0.0:8123,表示 loopback 绑定未生效。运行docker compose config,然后查看解析后的端口。
Flawless、HyperProbe,以及 Superlog 所处的位置
这一类别还比较新,各工具对代理允许操作的范围存在明显差异。Flawless 是一款面向 Kubernetes 的开源 AI SRE(站点可靠性工程)工具。它从现有的 Prometheus、Loki 和 Grafana 技术栈读取数据,而不是接管整条数据管道。HyperProbe 则相反:截至 2026 年 8 月,它是一款闭源托管产品。它会在运行中的进程内放置只读探针,以捕获变量状态,并通过 MCP(模型上下文协议)将这些状态提供给助手。
Superlog 介于两者之间。它端到端接管整条数据管道,从 OTLP 接收一直到 ClickHouse 存储,并将代理放在分类排查步骤,而不是修复步骤。这种设计正是自托管 Superlog 属于基础设施决策的原因,而不是部署一个可以完全不管的容器。运行 Superlog 后,您实际上运行的是列式存储系统,需要像管理其他自有数据库一样维护它。
FAQ
自托管 Superlog 需要多少 RAM?
对于低摄取量的单节点,建议准备 8 GB RAM、4 vCPU 和 40 GB 磁盘空间。该技术栈包含 Postgres、ClickHouse、一个 OpenTelemetry collector 和 4 个 Node 进程,而 ClickHouse 还需要预留足够的资源。1 GB 或 2 GB 的 VPS 不够用:仅 pnpm install 就很占资源,负载升高时 ClickHouse 会被内核的 out-of-memory killer 终止。请使用 docker stats --no-stream 和 free -m 测量您自己的资源使用情况,不要盲目相信任何已发布的数据,包括本文中的数据。
应将 OTLP exporter 指向哪个端口?
指向 Superlog intake proxy,也就是 README 中配置为 http://localhost:4101 的组件。它提供 /v1/traces、/v1/logs 和 /v1/metrics,并使用从 x-api-key header 或 authorization: bearer header 获取的项目 ingest key 进行身份验证。4318 端口是底层的 OpenTelemetry collector 端口。直接向该端口导出会绕过 proxy,而 proxy 负责将项目 id 写入数据。PORT 未设置时,proxy 会回退到 4000 端口。因此,请运行 ss -lntp,确认它实际绑定的端口后,再判断是否为 4101。
Superlog 能替代 Uptime Kuma 或 Zabbix 吗?
不能。Uptime Kuma 用于确认从网络外部访问某个端点时是否能得到响应,Zabbix 则根据您设置的阈值监控主机和服务指标。Superlog 接收应用生成的 traces、logs 和 metrics,并将重复发生的故障归并为 incidents。请同时保留外部 uptime probe,因为运行在其他位置的 probe 仍能报告承载遥测流水线的服务器是否发生故障。
Superlog agent 能更改我的生产系统吗?
只有在您授予相应权限时才能更改。它的输出是调查结果和建议的变更,由人工审核。开始时请让 GitHub App 仅使用 read 权限范围,并将 worker 持有的凭据限制为读取权限。请将生产环境的 write 权限作为单独的决策谨慎处理,因为能够重启服务的 agent,其风险和责任远高于只读取遥测数据并生成补丁供审核的 agent。
应固定某个 commit,还是跟踪 main?
固定某个 commit。截至 2026 年 8 月,该仓库没有 release tags,因此 main 是唯一可用的移动目标,而且每周会产生多个 commit。记录经过测试的 SHA,部署该版本,并在升级前阅读 diff。git log --oneline <old-sha>..main 是审核依据;每个应用的 .env.example 文件则是在任何版本更新后查找新增必需变量的首要位置。