Skip to content

Prometheus 监控实战系列 08:应用白盒监控:自定义指标埋点、业务监控设计与最佳实践

约 2009 字大约 7 分钟

Prometheus 监控实战系列Prometheus

2026-03-29

在前几篇内容中,我们已经掌握了 Prometheus 的核心工作机制,以及主机、容器层面的指标采集方法。但监控的核心价值最终要落地到应用本身——通过白盒监控深入应用内部,埋点自定义指标,兼顾技术指标与业务指标,才能真正实现故障可诊断、性能可衡量、业务可感知。本文将聚焦应用白盒监控的全流程:从监控设计原则,到指标分类与埋点模式,再到 Rails 应用实战落地,结合最佳实践帮你构建完整的应用监控体系。

一、应用监控的核心原则:避开反模式,找对切入点

应用监控不是“事后补位”的附加功能,而是应用研发的核心环节。忽视监控会导致故障不可诊断、性能不可衡量、业务价值不可评估,先明确核心原则,避开常见反模式:

1.1 规避三大反模式

  • 反模式 1:监控“非核心化”——将监控/安全视为增值组件而非核心功能。 最佳实践:把监控需求纳入应用研发的规范/用户故事,覆盖每个核心组件。
  • 反模式 2:监控力度不足——“数据太少”永远比“数据太多”更危险。 最佳实践:在存储容量限制内最大化监控覆盖,优先调整数据保留时间,而非削减监控维度。
  • 反模式 3:多环境监控未分区——开发/测试/生产环境指标混叠。 最佳实践:为监控配置添加环境标签,实现指标分区隔离。

1.2 监控切入点:从“入口出口”开始

应用监控的最佳起点是程序的入口和出口,优先监控以下场景:

  • 前端交互:特定网页/API 端点的请求数、响应时间(按优先级排序监控);
  • 外部依赖:数据库、缓存、第三方服务(如支付网关)的调用次数与耗时;
  • 周期任务:Cron 作业、定时任务的调度/执行次数与耗时;
  • 核心业务:用户创建、支付交易等关键业务事件的次数与耗时。

1.3 指标分类:清晰标识来源

通过应用、方法、函数等维度为指标打标签(参考 Prometheus 标签分类最佳实践),明确指标的生成位置与业务含义,避免指标混乱。

二、应用监控的核心:指标设计(技术+业务双维度)

指标是应用监控的核心载体,我们将指标分为应用程序指标(技术维度)和业务指标(价值维度),二者互补覆盖监控需求。

2.1 应用程序指标:衡量技术性能与状态

应用程序指标聚焦“应用能不能用、用得好不好”,核心覆盖:

  • 性能维度:延迟、响应时间、吞吐量(请求数/事务数/耗时);
  • 状态维度:成功/失败次数(如登录成功/失败、接口报错/崩溃);
  • 方法论参考:USE 方法(使用率、饱和度、错误率)、RED 方法(速率、错误率、持续时间)、Google 黄金指标,可快速落地性能监控。

2.2 业务指标:衡量应用的业务价值

业务指标是应用指标的“业务化延伸”,聚焦“应用创造了多少价值”:

  • 示例 1:支付接口的“调用延迟”是应用指标,“每笔支付的交易金额”是业务指标;
  • 示例 2:API 请求数是应用指标,“新用户注册数、销售额(按地域/金额)”是业务指标;
  • 注:Prometheus 更适合即时指标采集,长期业务指标可结合事件型系统补充。

2.3 指标放置:贴近业务+封装复用

  • 放置原则:指标代码尽可能贴近被监控的操作(如支付逻辑内埋点支付指标);
  • 封装模式:避免指标配置内联散写,采用实用程序模式(Metrics 工具类),暴露统一 API 供全代码库复用。

示例(Ruby 风格):

include Metric   
def pay_user(user,amount) 
  pay(user/account,amount) 
  # 应用指标:支付次数
  Metric.increment 'payment' 
  # 业务指标:支付金额
  Metric.increment "payment-amount{amount: #{amount.to_i}}" 
  send_payment_notification(user.email)   
end   
def send_payment_notification(email) 
  send_email(payment, email) 
  # 应用指标:付款邮件发送次数
  Metric.increment 'email-payment'   
end

三、实战:Rails 应用接入 Prometheus 自定义监控

以 Rails 应用(mwp-rails)为例,完整落地“自定义指标埋点→暴露指标→Prometheus 抓取”全流程。

3.1 步骤 1:引入 Prometheus Ruby 客户端

修改 Gemfile,添加 prometheus-client 依赖:

source 'https://rubygems.org'  
ruby '2.4.2'  
gem 'rails', '5.1.5'  
gem 'prometheus-client'

执行安装:

sudo bundle install

3.2 步骤 2:封装 Metrics 工具类(实用程序模式)

lib/metrics.rb 中创建统一的指标管理模块,避免重复创建注册表/指标:

module Metrics
  def self.counter(name, docstring, base_labels = {})
    provide_metric(name) || registry.counter(name, docstring, base_labels)
  end

  def self.summary(name, docstring, base_labels = {})
    provide_metric(name) || registry.summary(name, docstring, base_labels)
  end

  def self.gauge(name, docstring, base_labels = {})
    provide_metric(name) || registry.gauge(name, docstring, base_labels)
  end

  def self.histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS)
    provide_metric(name) || registry.histogram(name, docstring, base_labels, buckets)
  end

  private
  def self.provide_metric(name)
    registry.get(name)
  end

  def self.registry
    @registry ||= ::Prometheus::Client.registry
  end
end

创建初始化文件 config/initializers/lib.rb 加载模块:

require 'metrics'

3.3 步骤 3:自定义指标埋点

示例 1:用户删除计数器(控制器层)

def destroy
  user = User.find(params[:id])
  user.destroy
  # 埋点:用户删除计数器
  Metrics.counter(:users_deleted_counter, "Deleted users counter").increment
  redirect_to users_path, :notice => "User deleted."
end

示例 2:用户创建计数器(模型层回调)

class User < ActiveRecord::Base
  enum role: [:user, :vip, :admin]
  after_initialize :set_default_role, :if => :new_record?
  after_create do
    # 埋点:用户创建计数器
    Metrics.counter(:users_created_counter, "Users created counter").increment
  end
end

扩展:带标签/指定增量的埋点

# 增量为2,添加service/app标签
Metrics.counter(:xxx_counter, "XXX counter").increment({service:'foo', app:'bar'}, 2)

3.4 步骤 4:暴露指标端点(Rack 中间件)

修改 config.ru,添加 Prometheus 中间件,自动采集 HTTP 指标并暴露 /metrics 端点:

require 'prometheus/middleware/collector'  
require 'prometheus/middleware/exporter'  
use Prometheus::Middleware::Collector  # 采集HTTP服务器指标
use Prometheus::Middleware::Exporter   # 暴露/metrics端点

访问 /metrics 可看到指标示例:

# HELP http_server_requests_total The total number of HTTP requests handled by the Rack application
http_server_requests_total{code="200",method="get",path="/"} 2.0 
# HELP http_server_request_duration_seconds The HTTP response duration of the Rack application.
http_server_request_duration_seconds_bucket{method="get",path="/",le="0.005"} 0.0
# HELP users_updated_counter Users updated counter
users_updated_counter 1.0

3.5 步骤 5:Prometheus 配置抓取

1. 基于文件的服务发现(targets/rails/*.json)

{
  "targets": ["mwp-rails1.example.com", "mwp-rails2.example.com", "mwp-rails3.example.com"]
}

2. 修改 prometheus.yml 添加作业

- job_name: rails  
  file_sd_configs:  
  - files:  
      - targets/rails/*.json  
  refresh_interval: 5m

3. 验证抓取结果

重新加载 Prometheus 后,可在 Targets 页面看到 Rails 服务器目标:

查看指标可视化效果:

四、特殊场景:外部模式(无代码控制权时的监控)

若无法修改应用代码(如老旧系统),可通过“外部模式”监控:

  1. 日志分析:统计特定日志条目数量,跟踪事件频率;
  2. 外部子系统:采集数据库事务、缓存调用、邮件发送、定时任务等事件数据;
  3. 核心思路:找到距离应用最近的可观测点,替代代码内埋点。

五、小结

本文聚焦应用白盒监控的全流程:从监控设计原则(避坑+切入点),到指标分层设计(应用+业务),再到 Rails 应用实战落地自定义埋点,同时覆盖了无代码控制场景的替代方案。核心要点:

  1. 监控是应用核心功能,需从设计阶段纳入;
  2. 指标埋点贴近业务逻辑,封装复用避免散写;
  3. 兼顾技术指标(性能/状态)与业务指标(价值);
  4. 多环境通过标签隔离,存储不足优先调整保留时间。