3. 监控系统选型:Prometheus + Grafana方案、ELK日志监控方案、自定义埋点方案、选型对比与决策

监控系统选型,说白了就是给特征平台装一套「体检设备」。你想想看,一个每天处理几亿特征数据的平台,要是出了问题你都不知道,那跟开盲盒有什么区别?

我个人习惯把监控方案分成三大流派:指标监控、日志监控和自定义埋点。每个流派都有自己的看家本领,也有各自的短板。今天我们就来掰扯清楚,到底该怎么选。

3.1 Prometheus + Grafana:指标监控的扛把子

这套组合在云原生圈子里有多火,不用我多说。Prometheus 负责采集和存储时序数据,Grafana 负责可视化展示。我最早接触 Prometheus 是在 2018 年,当时还在做微服务改造,一用就回不去了。

核心架构

特征服务 → Prometheus Client (暴露 /metrics 端点)
                ↓
         Prometheus Server (拉取 + 存储)
                ↓
         Grafana (查询 + 告警 + 仪表盘)

Prometheus 采用的是 Pull 模型,也就是服务端主动去拉取目标的数据。这一点跟传统的 Push 模型(比如 Zabbix)很不一样。Pull 模型的好处是:你不需要在每个服务里配上报地址,只要统一在 Prometheus 配置文件里声明目标就行。

特征平台关键指标示例

  • feature_ingestion_latency_seconds —— 特征写入延迟
  • feature_retrieval_total —— 特征查询总量(带 status 标签)
  • feature_storage_usage_bytes —— 存储使用量
  • feature_sla_violation_total —— SLA 违约次数

Grafana 这边,我建议你提前把仪表盘模板化。我在项目中遇到过一个问题:每次新接入一个特征源,就要手动拖一遍面板,太累了。后来我们统一用 Grafana Provisioning 的方式,把仪表盘定义成 JSON 文件,放到 Git 里管理。新服务上线,自动生成对应的监控面板。

小技巧:Prometheus 的告警规则建议用 for 字段做「持续时间」判断。比如特征延迟超过 5 秒持续 1 分钟才告警,避免因为瞬时抖动而收到一堆垃圾告警。

3.2 ELK日志监控方案:日志里的金矿

ELK(Elasticsearch + Logstash + Kibana)是日志监控的经典组合。很多人觉得日志就是用来排错的,其实不然。日志里藏着大量有价值的信息——用户行为、异常堆栈、性能瓶颈,全都有。

ELK 在特征平台中的典型用法

特征服务 → Filebeat (采集日志) → Logstash (解析/过滤) → Elasticsearch (存储/索引) → Kibana (搜索/可视化)

我记得有一次线上特征数据出现异常,Prometheus 指标显示一切正常,但业务方反馈特征值不对。最后查了半天,是某个特征计算逻辑里有个边界条件没处理好。要不是 ELK 里保留了完整的请求日志,这个问题根本定位不了。

ELK 的优势在于全量数据留存和灵活搜索。Prometheus 只能存聚合后的指标,但 ELK 可以存每一条原始日志。这对于事后审计和根因分析来说,价值巨大。

注意:ELK 的存储成本很高。特征平台每天产生的日志量可能达到 TB 级别。我建议做分层存储:热数据保留 7 天,温数据保留 30 天,冷数据归档到对象存储。别一股脑全塞进 Elasticsearch,否则账单会让你怀疑人生。

日志结构化是关键

很多团队用 ELK 效果不好,是因为日志格式太随意。我建议统一使用 JSON 格式输出日志,并且定义好字段规范:

{
  "timestamp": "2024-01-15T10:30:00.123Z",
  "level": "ERROR",
  "service": "feature-ingestion",
  "feature_name": "user_click_rate_v2",
  "latency_ms": 5230,
  "error_code": "TIMEOUT",
  "trace_id": "abc123def456",
  "message": "特征计算超时,已触发降级"
}

这样 Logstash 解析起来效率高,Kibana 里做聚合分析也方便。你想想看,如果日志是纯文本的,想统计某个特征的平均延迟,得写多复杂的正则?

3.3 自定义埋点方案:灵活但代价高

有些场景,Prometheus 和 ELK 都搞不定。比如:

  • 你想统计某个特征在特定业务场景下的调用链路耗时
  • 你想记录用户在一次请求中,特征命中缓存的次数
  • 你想追踪特征数据从产生到消费的端到端延迟

这时候就需要自定义埋点了。说白了,就是在代码里主动打点,把数据上报到专门的存储系统。

常见的自定义埋点实现方式

// 伪代码示例:特征命中率埋点
public class FeatureHitCounter {
    private final Counter hitCounter = Metrics.counter("feature_cache_hit");
    private final Counter missCounter = Metrics.counter("feature_cache_miss");

    public FeatureValue getFeature(String name) {
        FeatureValue value = cache.get(name);
        if (value != null) {
            hitCounter.inc();
        } else {
            missCounter.inc();
            value = computeFeature(name);
            cache.put(name, value);
        }
        return value;
    }
}

自定义埋点的好处是精准,你想埋什么就埋什么。但代价也很明显:

  • 侵入性强:需要修改业务代码
  • 维护成本高:埋点多了,代码里到处都是打点逻辑
  • 存储压力大:自定义指标往往维度很多,容易导致基数爆炸

我的建议:自定义埋点只用于「Prometheus 和 ELK 覆盖不到」的核心场景。比如特征端到端延迟、缓存命中率、降级触发次数。其他常规指标,能用 Prometheus 解决的,就别自己造轮子。

3.4 选型对比与决策

好了,三种方案都介绍完了。到底怎么选?我画了一张对比图,帮你理清思路。

特征平台监控方案选型决策树 监控需求分析 需要实时指标? 需要全量日志? 需要自定义维度? Prometheus + Grafana ELK 日志方案 自定义埋点 选型建议 1. 优先使用 Prometheus + Grafana 覆盖 80% 的监控需求 2. ELK 作为补充,用于日志分析和根因定位 3. 自定义埋点只用于 Prometheus 和 ELK 覆盖不到的核心场景 4. 三种方案可以共存,但要有明确的职责边界 5. 避免重复造轮子:能用现成方案解决的,不要自己写

下面这张表,是我在实际项目中总结的选型对比,你可以直接拿来参考:

对比维度 Prometheus + Grafana ELK 日志方案 自定义埋点
数据形态 时序指标(聚合后) 原始日志(全量) 自定义指标/事件
存储成本 低(聚合存储) 高(全量存储) 中(取决于维度)
查询延迟 毫秒级 秒级 取决于后端
告警能力 强(内置 Alertmanager) 中(需额外配置) 需自建
代码侵入 低(SDK 接入) 低(日志框架) 高(业务代码)
适用场景 性能监控、SLA 告警 故障排查、审计 业务指标、链路追踪

我的最终建议:

  • 中小规模团队(特征量 < 1000):Prometheus + Grafana 就够了,日志用 ELK 做辅助
  • 大规模团队(特征量 > 10000):三种方案都要上,但要有清晰的职责划分。我曾经见过一个团队,三种方案各搞各的,最后告警重复、数据对不上,反而增加了运维负担
  • 关键原则:能用 Prometheus 解决的,不要用 ELK;能用 ELK 解决的,不要自定义埋点。每多一种方案,就多一份维护成本

嗯,监控系统选型这块,说到底没有银弹。关键是要想清楚:你真正需要监控的是什么?是性能、是可用性、还是业务正确性?想清楚了,选型自然就清晰了。