1. 项目概述:从“可观测性”的痛点说起
如果你在运维一个稍微有点规模的线上服务,或者正在开发一个微服务架构的应用,那么下面这个场景你一定不陌生:凌晨三点,监控告警响了,CPU使用率飙升。你打开监控面板,看到某个节点的CPU曲线确实冲到了90%,但问题是,哪个服务、哪个接口、哪段代码导致的?你只能凭经验去猜,是数据库查询慢了,还是某个外部API调用超时了?接着,你需要在日志系统里大海捞针,在链路追踪工具里翻找可疑的调用链,在指标系统里核对各种关联数据。几个工具来回切换,信息支离破碎,定位问题的黄金时间就在这种“拼图游戏”中白白流逝了。
这就是传统监控体系下“可观测性”的典型困境:指标(Metrics)、日志(Logs)、追踪(Traces)三大支柱数据相互割裂。我们缺的不是工具,而是一个能将这三者有机融合、提供统一分析视角的平台。这也是为什么当我第一次接触到SigNoz这个开源项目时,会感到眼前一亮。SigNoz 将自己定位为Datadog、New Relic 的开源替代方案,其核心目标就是构建一个统一的可观测性平台,让你在一个界面里,就能完成从宏观指标异常下钻到具体错误日志和慢追踪的全链路分析。
简单来说,SigNoz 是一个集成了指标监控、分布式链路追踪、日志聚合与分析的全栈可观测性解决方案。它采用OpenTelemetry作为数据采集和标准化的基石,后端使用ClickHouse作为高性能的时序数据存储,前端则提供了一个功能丰富、类似 Grafana 但更专注于可观测性场景的查询与分析界面。对于中小团队、创业公司或者任何希望以可控成本(甚至是零成本)获得强大可观测性能力的开发者而言,SigNoz 提供了一个极具吸引力的选择。
2. 核心架构与设计哲学拆解
要理解 SigNoz 为什么能成为 Datadog 的有力挑战者,我们必须深入其架构设计。它的设计哲学非常清晰:拥抱标准、专注性能、一体化体验。
2.1 基石:OpenTelemetry 的全面拥抱
这是 SigNoz 最明智也最具前瞻性的选择。OpenTelemetry(简称 OTel)是由 CNCF 孵化的项目,旨在为可观测性数据(指标、日志、追踪)提供一套统一的标准 API、SDK 和采集器。在过去,你要接入 Jaeger(追踪)、Prometheus(指标)、Fluentd(日志),可能需要三套不同的客户端库和代理,配置复杂,数据格式也不互通。
SigNoz 从设计之初就将 OTel 作为一等公民。这意味着:
- 采集无痛:你的应用只需要集成 OTel SDK,通过配置,就可以将追踪、指标、日志(通过 OTel Logs Bridge)统一发送到 SigNoz。这大大降低了接入成本和技术栈复杂度。
- 数据关联:OTel 规范定义了贯穿整个请求链路的
trace_id和span_id。当 SigNoz 后端收到这些数据时,它能天然地将同一个请求的追踪 spans、该请求过程中产生的日志、以及由此聚合出的服务指标(如请求延迟、错误率)关联在一起。这是实现“一键下钻”能力的根本。 - 未来兼容:随着 OTel 标准的不断成熟和普及,任何遵循该标准的应用或中间件,都能轻松地将数据接入 SigNoz,保证了平台的长期生命力和扩展性。
注意:虽然 SigNoz 强烈推荐使用 OTel,但它并非强制。其采集器(OpenTelemetry Collector)也支持接收 Jaeger、Zipkin 等格式的追踪数据,以及 Prometheus 格式的指标。不过,要获得最佳的一体化体验,OTel 是最推荐的路径。
2.2 引擎:ClickHouse 作为存储核心
可观测性数据是典型的时间序列数据,且数据量巨大(尤其是追踪和日志),查询模式复杂(既有实时聚合,也有历史下钻)。SigNoz 没有选择 Elasticsearch(传统日志方案)或 Prometheus + Thanos(传统指标方案),而是选择了ClickHouse作为统一的存储后端。
这个选择背后有深刻的考量:
- 极高的压缩比:ClickHouse 的列式存储和高效的压缩算法,能将对存储空间要求极高的追踪和日志数据压缩 10 倍甚至更多。这直接降低了硬件成本和长期存储的可行性。
- 恐怖的查询性能:对于可观测性场景中常见的聚合查询(如“过去5分钟,服务A的错误率”、“按接口分组统计P99延迟”),ClickHouse 的向量化执行引擎和预聚合能力(通过物化视图)能提供亚秒级的响应速度。这对于交互式排查问题至关重要。
- SQL 的强大与灵活:ClickHouse 支持标准的 SQL 方言。这意味着 SigNoz 的前端查询能力非常强大,用户可以通过相对熟悉的 SQL 语法进行灵活的数据探索和自定义查询,降低了学习成本,也提高了平台的灵活性。
当然,这个选择也有代价。ClickHouse 的写入吞吐虽然很高,但对高频、小批量的实时写入不如 Elasticsearch 优化得那么极致。SigNoz 通过使用 Kafka(或 Redpanda)作为缓冲队列来解耦数据接收和写入,完美解决了这个问题。数据先进入队列,再由 SigNoz 的流水线服务消费并批量写入 ClickHouse,既保证了可靠性,又发挥了 ClickHouse 的批量写入优势。
2.3 界面:一体化的前端设计
SigNoz 的前端不是 Grafana 的简单套壳。它是为可观测性量身定做的。其界面逻辑紧密围绕Metrics、Traces、Logs 的关联分析来设计。
- 服务仪表盘(Service Dashboard):这是你的首页。直观地展示所有服务的关键黄金指标:请求速率(RPS)、错误率、平均响应时间(Avg Duration)和P99/P95延迟。点击任何一个服务,即可进入该服务的专属视图。
- 追踪(Traces)浏览器:这里你可以查看所有的分布式追踪。强大的过滤功能让你可以按服务、操作、状态码、持续时间甚至自定义标签来筛选。最关键的是,当你点击一个缓慢或错误的追踪(Span)时,右侧会直接关联展示该 Span 时间段内,在相同服务/实例上产生的所有日志。无需跳转,上下文一目了然。
- 日志(Logs)管理:虽然 SigNoz 的日志功能相对 Traces 和 Metrics 晚一些,但发展迅速。支持基于
trace_id的日志查询是核心亮点。你可以在日志面板直接输入trace_id=xxxx,找到该次请求的全部日志。反之,在查看日志时,如果该日志包含trace_id,也可以一键跳转到对应的完整追踪链路。 - 指标(Metrics)查询器:提供类似 PromQL 的查询界面,但底层查询会转换为对 ClickHouse 的 SQL 查询。你可以在这里定义自定义的监控图表和告警规则。
这种设计将“可观测性”从一个概念,落地为一种流畅的操作体验。你不再是在三个独立的工具间传递trace_id,而是在一个平台内完成自然的上下文切换。
3. 从零开始部署与核心配置实战
理论说得再多,不如亲手部署一遍。SigNoz 提供了极其友好的入门方式,特别是对于本地开发和测试。
3.1 快速本地部署:Docker Compose 方案
对于大多数想尝鲜和评估的个人开发者或小团队,Docker Compose 是最快的方式。SigNoz 官方维护了一个功能完整的docker-compose.yaml文件。
# 1. 克隆仓库(选择稳定版本,如 v0.28.0) git clone -b v0.28.0 https://github.com/SigNoz/signoz.git cd signoz/deploy/docker/clickhouse-setup # 2. 启动所有服务 docker-compose -f docker-compose.yaml up -d这个命令会启动一整套服务,包括:
otel-collector: OpenTelemetry 收集器,接收应用数据。clickhouse: 存储所有可观测性数据。query-service: 后端查询服务,处理前端请求。frontend: SigNoz 的 Web 界面。alertmanager和alerts-service: 告警相关服务。redis: 缓存。
启动完成后,访问http://localhost:3301就能看到 SigNoz 的登录界面。首次使用,你需要用默认邮箱admin@signoz.io和密码admin注册一个管理员账户。
实操心得:在本地运行,尤其是 Mac 或 Windows 上,可能会因为 Docker 资源限制导致 ClickHouse 启动缓慢或失败。如果前端一直无法连接,可以查看
clickhouse容器的日志:docker logs signoz-clickhouse -f,确保它已完全启动并监听端口。建议为 Docker Desktop 分配至少 4GB 内存。
3.2 生产环境部署考量
Docker Compose 适合单机测试,但对于生产环境,你需要考虑高可用、可扩展性和数据持久化。官方推荐使用Kubernetes Helm Chart进行部署。
# 添加 SigNoz Helm 仓库 helm repo add signoz https://charts.signoz.io helm repo update # 安装 SigNoz helm install my-signoz signoz/signoz -n platform --create-namespace生产部署的关键配置点:
- 存储:必须为 ClickHouse 配置持久化存储卷(PersistentVolume),否则数据在 Pod 重启后会丢失。在 Helm values 中配置
clickhouse.persistence.enabled=true并指定 storageClass。 - 资源限制:根据数据量预估,为
clickhouse、query-service等核心组件设置合理的resources.requests/limits。ClickHouse 是内存和CPU消耗大户。 - 高可用:对于核心服务如
otel-collector、query-service,可以通过设置replicaCount: 2来实现简单的多副本。更复杂的高可用需要规划 ClickHouse 集群(分片与复制),目前 SigNoz 的 Helm Chart 对 ClickHouse 集群的支持还在完善中,大型部署可能需要自行维护 ClickHouse 集群。 - 数据保留策略:可观测性数据量增长很快。需要在 SigNoz 前端界面(Settings -> General -> Retention Period)或直接配置 ClickHouse 的 TTL(Time To Live)来设置不同数据的保留时间。例如,追踪数据保留7天,指标聚合数据保留30天。
3.3 应用接入:以 Go 和 Python 应用为例
部署好平台,下一步就是让应用数据“流”进来。我们以最典型的 Go 和 Python 微服务为例。
Go 应用接入:
package main import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.17.0" ) func initTracer() func() { // 1. 创建 OTLP gRPC 导出器,指向 SigNoz 的 Collector exporter, err := otlptracegrpc.New(context.Background(), otlptracegrpc.WithEndpoint("localhost:4317"), // SigNoz Collector 默认端口 otlptracegrpc.WithInsecure(), // 生产环境应使用 TLS ) if err != nil { log.Fatal(err) } // 2. 创建资源标识,描述你的服务 res, _ := resource.Merge( resource.Default(), resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceName("your-go-service"), semconv.ServiceVersion("1.0.0"), attribute.String("environment", "demo"), ), ) // 3. 创建 Tracer Provider tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), sdktrace.WithResource(res), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) // 返回一个关闭函数,用于程序退出时刷新数据 return func() { if err := tp.Shutdown(context.Background()); err != nil { log.Printf("Error shutting down tracer provider: %v", err) } } } func main() { shutdown := initTracer() defer shutdown() // 你的业务代码... tr := otel.Tracer("example-tracer") ctx, span := tr.Start(context.Background(), "my-operation") defer span.End() // ... 执行操作 }Python (Django/Flask) 应用接入:
对于 Python,通常使用自动插桩(Auto-instrumentation)来最小化代码侵入。
# 1. 安装必要的包 pip install opentelemetry-distro opentelemetry-exporter-otlp pip install opentelemetry-instrumentation-flask opentelemetry-instrumentation-requests # 2. 通过环境变量配置并自动运行你的应用 export OTEL_SERVICE_NAME="your-python-service" export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" # HTTP 协议,对应 4318 端口。gRPC 用 4317。 export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" # 使用 opentelemetry-bootstrap 自动安装所有检测库 opentelemetry-bootstrap -a install # 3. 用 opentelemetry-instrument 包装命令启动你的应用 opentelemetry-instrument --traces_exporter otlp --metrics_exporter otlp \ python your_app.py接入后,访问你的应用接口,然后去 SigNoz 的Traces页面,应该就能看到相关的追踪数据了。指标数据(如 HTTP 请求数、延迟)也会被自动捕获。
4. 核心功能场景化深度使用指南
平台搭好了,数据也进来了,接下来就是如何用它真正提升效率。我们通过几个典型场景来拆解。
4.1 场景一:快速定位接口性能瓶颈
假设监控告警显示user-service的 P99 延迟从 200ms 飙升到了 2s。
- 第一步:服务概览。打开 SigNoz,首页的 Service Dashboard 就能看到
user-service的延迟曲线异常。点击user-service进入服务详情页。 - 第二步:下钻到慢追踪。在服务详情页,找到“Traces”标签页。使用过滤器:
Service = user-service并且Duration > 1s(你可以设置一个阈值)。列表会列出所有慢请求的追踪。 - 第三步:分析追踪火焰图。点击一个慢追踪,右侧会展开火焰图(Flamegraph)和甘特图(Gantt Chart)。火焰图能直观地告诉你时间花在了哪里。你可能会发现,大部分时间消耗在一个名为
GET /api/internal/profile的数据库查询或外部调用上。 - 第四步:关联日志。在火焰图上点击那个耗时的 Span,右侧的“Logs”标签页会自动加载在该 Span 执行期间、同一服务实例上产生的所有日志。你可能会看到类似“SQL query slow: SELECT * FROM users WHERE ...”、“Redis connection timeout”这样的错误或警告日志。至此,你从宏观指标异常,到具体的慢接口,再到可能的原因(慢SQL、网络超时),全部在一个界面内完成,耗时可能不到一分钟。
4.2 场景二:排查偶发性错误
用户报告偶尔会收到 500 错误,但并非每次重现。
- 错误率监控:在
user-service的详情页,关注“错误率”图表。确认错误是否在特定时间段频发。 - 过滤错误追踪:在 Traces 页面,过滤
Status Code = 2(OTel 中 2 代表 Error)。查看这些错误追踪的共性。 - 对比分析:SigNoz 提供了一个强大的功能——“对比模式”。你可以选择一个成功的追踪和一个失败的追踪进行对比。系统会高亮显示两者在调用链路上的差异,比如失败的追踪在某个下游服务调用时缺失了一个 Span,或者返回了不同的状态码,这能快速指引你找到错误分叉点。
- 检查异常日志:同样,点击错误 Span 查看关联日志。结合日志中的错误堆栈信息,基本就能定位到出错的代码行或依赖服务。
4.3 场景三:基于业务指标的告警
除了系统指标,我们更关心业务指标。例如,我们希望当“下单失败率”超过 5% 时告警。
- 发送自定义指标:在你的下单服务中,使用 OTel SDK 发送自定义指标。
meter := otel.Meter("order-service") failureCounter, _ := meter.Int64Counter("order.failure.count") // 在下单失败时 failureCounter.Add(ctx, 1, attribute.String("payment_gateway", "stripe")) - 在 SigNoz 中定义告警:
- 进入
Alerts页面,创建新的告警规则。 - 数据源选择
clickhouse。 - 查询语句使用 SigNoz 扩展的 SQL 语法。例如,计算过去5分钟的失败率:
SELECT (sum(`order.failure.count`) / sum(`order.total.count`)) * 100 as failure_rate FROM signoz_metrics.distributed_samples WHERE timestamp >= now() - 300 AND metric_name IN ('order.failure.count', 'order.total.count') GROUP BY metric_name - 设置阈值条件
failure_rate > 5,并配置告警渠道(如 Slack, Webhook)。
- 进入
4.4 场景四:日志的集中管理与追踪关联
对于已经使用传统日志代理(如 Filebeat/Fluentd)的应用,也可以将日志接入 SigNoz。
- 配置日志转发:在你的 Fluentd 配置中,将日志输出到 SigNoz 的 OTLP 接收端。
<match your.log.tag> @type otlp endpoint "http://your-signoz-collector:4318" service_name "your-service" # 关键:从日志中解析或注入 trace_id 和 span_id <headers> trace_id ${record.dig("trace_id")} span_id ${record.dig("span_id")} </headers> </match> - 在 SigNoz 中查询:之后,你就可以在 SigNoz 的 Logs 页面,通过服务名、日志级别、关键字进行搜索。更重要的是,如果日志里带有
trace_id,你可以直接点击它跳转到完整的请求追踪,实现上下文的无缝切换。
5. 性能调优、问题排查与运维心得
运行一段时间后,你可能会遇到一些性能和运维上的挑战。这里分享一些实战经验。
5.1 性能与资源优化
- ClickHouse 写入优化:SigNoz 的流水线服务(
pipeline)负责将队列中的数据写入 ClickHouse。如果数据量很大,可以调整其批处理参数(如flush_interval,flush_size)来平衡延迟和吞吐。监控 ClickHouse 的system.metrics表,关注InsertedRows和InsertedBytes速率是否正常。 - 查询加速:对于频繁查询的聚合指标(如服务每分钟错误率),可以在 ClickHouse 中创建**物化视图(Materialized View)**进行预聚合。SigNoz 的部分核心指标已经内置了物化视图。对于自定义的关键业务指标,考虑依样画葫芦,能极大提升仪表盘加载速度。
- 存储成本控制:这是重中之重。务必设置数据保留策略。SigNoz 前端可以设置全局保留时间。对于更精细的控制,你需要直接操作 ClickHouse,为不同的表设置 TTL。例如,原始追踪数据 (
signoz_traces.distributed_traces) 保留7天,但可以创建一个物化视图将每天的慢追踪(duration > 10s)聚合到另一张表保留30天。-- 示例:为 traces 表设置 7 天 TTL ALTER TABLE signoz_traces.distributed_traces ON CLUSTER cluster MODIFY TTL timestamp + INTERVAL 7 DAY;
5.2 常见问题排查速查表
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 前端无法访问 (localhost:3301) | 服务未完全启动,端口冲突 | 1.docker-compose ps检查所有服务状态。2. docker logs signoz-frontend查看前端日志。3. 检查本地 3301 端口是否被占用。 |
| 应用发送数据后,SigNoz 无显示 | OTel Collector 配置错误,网络不通,数据格式不对 | 1. 检查应用配置的 OTLP 端点 (localhost:4317) 是否正确。2. docker logs signoz-otel-collector查看 Collector 是否收到数据及有无错误。3. 用 curl或grpcurl测试 Collector 端口是否可达。4. 检查应用 SDK 版本与 Collector 是否兼容。 |
| 查询速度非常慢 | ClickHouse 内存不足,查询过于复杂,缺少索引 | 1. 检查 ClickHouse 容器/节点的内存使用率 (docker stats或top)。2. 在 SigNoz 前端打开浏览器开发者工具,查看哪个 API 请求慢。 3. 登录 ClickHouse,使用 EXPLAIN分析慢查询语句。 |
| 磁盘空间增长过快 | 数据保留策略未设置,日志级别过低产生过多数据 | 1. 检查 SigNoz 设置中的 Retention Period。 2. 检查应用日志级别是否为 DEBUG,适当调整为 INFO 或 WARN。 3. 计算每日数据摄入量,规划合理的保留周期。 |
| 告警不触发或重复触发 | 告警规则条件设置错误,评估间隔不合理 | 1. 仔细检查告警规则中的查询语句,在Metrics查询器先手动执行验证结果。2. 调整告警规则的“评估间隔”(Evaluation Interval),避免过于频繁。 3. 配置告警的“冷却时间”(Cool Down Period)防止抖动。 |
5.3 生产环境运维建议
- 监控 SigNoz 自身:用 SigNoz 监控 SigNoz 自身。为
signoz命名空间下的服务(collector, query-service, clickhouse)配置基础资源告警(CPU、内存、磁盘)。这是确保可观测性平台自身高可用的前提。 - 备份与恢复:定期备份 ClickHouse 的数据。ClickHouse 提供了
clickhouse-backup等工具。制定灾难恢复预案,知道如何从备份中恢复数据。 - 版本升级:关注 SigNoz 的 Release Notes。升级前,务必在测试环境验证。特别是大版本升级,可能涉及数据表结构变更,需要按照官方指南进行数据迁移。
- 安全加固:生产环境务必启用 TLS 加密 OTLP 数据传输。修改默认的管理员密码。通过网络策略限制对 SigNoz 管理端口(3301)和 Collector 端口(4317, 4318)的访问。考虑集成 OAuth/SSO 进行用户认证。
SigNoz 作为一个快速发展的开源项目,其社区非常活跃。遇到问题时,除了查阅官方文档,其 GitHub Issues 和 Slack 频道是寻求帮助的好地方。从我个人的使用体验来看,它已经能够覆盖中小型企业 80% 以上的可观测性需求。它的优势在于“开箱即用”的一体化体验和基于开放标准的设计,避免了供应商锁定。当然,与成熟的商业方案相比,它在极端规模下的性能调优、企业级功能(如精细的权限控制、审计日志)方面还有成长空间,但这正是开源项目的魅力所在——你可以参与其中,与社区一起将它塑造成你需要的模样。对于任何正在被多套监控工具折磨,或者预算有限但渴望拥有强大可观测性能力的团队,SigNoz 绝对值得你投入时间深入评估和尝试。