ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Prometheus自定义指标监控实战:从数据模型到业务可观测性

Prometheus自定义指标监控实战:从数据模型到业务可观测性 1. 项目概述从通用监控到精准洞察在运维和开发领域监控是系统的“眼睛”。我们熟知的Prometheus以其强大的时序数据模型和灵活的查询语言PromQL早已成为云原生时代监控的事实标准。它自带了一套丰富的系统指标比如CPU、内存、磁盘、网络开箱即用。但真实的生产环境远比这复杂你的业务订单处理速度是否在下降缓存命中率是否异常一个核心的微服务接口的99分位响应时间是多少这些直接反映业务健康度和用户体验的指标恰恰是Prometheus默认不提供的。这就是“自定义指标监控”要解决的核心问题——将监控的触角从基础设施层延伸到应用层和业务层实现真正意义上的可观测性。简单来说这个项目就是教你如何打破Prometheus的“默认监控边界”让任何你认为重要的数据——无论是应用内部的一个计数器还是一个复杂的业务逻辑计算结果——都能变成一条时序曲线纳入统一的监控告警体系。这不仅仅是技术实现更是一种监控思维的转变从“监控服务器是否活着”到“监控业务是否健康”。无论你是运维工程师、SRE还是后端开发者掌握这套方法都能让你对你负责的系统有更深刻、更主动的掌控力。2. 自定义指标的核心原理与数据模型拆解要玩转自定义指标首先得吃透Prometheus的数据模型这是所有操作的基石。Prometheus存储的是时序数据每一条数据都由一个指标名称Metric Name和一组标签Label唯一标识伴随着一个时间戳和一个浮点数值。2.1 指标类型不仅仅是数字Prometheus定义了四种核心的指标类型理解它们的适用场景是关键Counter计数器这是一个只增不减的累加器。典型应用场景是请求总数、错误总数、完成任务数量。你永远不应该在程序中去减少一个Counter的值。它的价值在于计算速率比如通过PromQL的rate(http_requests_total[5m])来计算每秒的请求量QPS。Gauge仪表盘这是一个可以任意上下波动的数值。它反映的是当前瞬间的状态。比如当前CPU使用率、内存占用大小、活跃连接数、队列长度。你可以对它进行增、减、设置操作。Histogram直方图这是一个用于统计和分析数据分布情况的强大工具特别是对请求延迟或响应大小的测量。它并不是存储一个值而是自动创建多个时序_bucket桶记录落在特定值区间的观测值数量用于计算分位数如P99。_sum所有观测值的总和。_count观测事件的总数。 例如一个名为http_request_duration_seconds的Histogram可以让你轻松查询“过去5分钟内95%的请求延迟低于多少秒”。Summary摘要与Histogram功能类似也用于计算分位数。但关键区别在于Summary的分位数计算是在客户端即你的应用程序完成的然后直接将计算结果如quantile0.95推送给Prometheus。而Histogram的分位数是在服务端Prometheus通过PromQL动态计算的。Summary适用于不需要全局聚合跨不同标签维度的分位数场景且对客户端性能有一定消耗Histogram更灵活资源消耗在服务端是目前更主流的推荐方式。注意选择Histogram还是Summary常常让人困惑。一个简单的经验法则是如果你需要跨不同维度如按服务、按接口聚合计算分位数例如查看整个集群所有服务的P99延迟或者你不确定分位数的具体值希望后期灵活查询那么用Histogram。如果你非常明确只需要几个固定的分位数如0.5 0.9 0.99并且不需要跨标签聚合且可以接受客户端计算开销可以用Summary。2.2 标签的力量维度化数据标签是Prometheus的灵魂。一个没有标签的指标价值有限。例如http_requests_total这个指标如果加上methodPOSTendpoint/api/v1/orderstatus_code200这几个标签它的价值就发生了质变。你可以轻松分析不同接口的请求量http_requests_total{endpoint/api/v1/order}POST和GET方法的错误率对比rate(http_requests_total{status_code!200}[5m])特定端点的成功率设计标签时要遵循“高基数禁忌”。避免使用可能产生大量唯一值组合的标签例如用户ID、会话ID、完整的请求参数等。这会导致Prometheus产生海量的时序数据严重消耗存储和内存。标签应该用于描述有界的、可枚举的维度如环境prod/staging、数据中心、服务名、接口路径、HTTP方法、状态码等。3. 客户端库集成与指标暴露实战理解了理论接下来就是动手。Prometheus提供了多种语言的客户端库如Go、Java、Python、Ruby等它们负责帮你创建和管理指标并以Prometheus能够抓取的文本格式暴露出来。3.1 以Go语言为例的完整集成步骤这里以最流行的Go语言为例展示从零开始集成Prometheus客户端库并暴露自定义指标的完整流程。第一步引入客户端库go get github.com/prometheus/client_golang第二步在应用中定义和注册指标通常我们会在一个独立的包如metrics/metrics.go中集中管理所有指标。package metrics import ( github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/promauto ) // 定义命名空间和子系统避免指标名冲突 const ( namespace myapp subsystem order_service ) var ( // 1. 定义一个Counter用于统计订单创建总数 OrdersCreatedTotal promauto.NewCounterVec( prometheus.CounterOpts{ Namespace: namespace, Subsystem: subsystem, Name: orders_created_total, Help: The total number of created orders., }, []string{payment_method, status}, // 标签支付方式、订单状态 ) // 2. 定义一个Gauge用于监控当前处理中的订单数 OrdersInProcess promauto.NewGauge( prometheus.GaugeOpts{ Namespace: namespace, Subsystem: subsystem, Name: orders_in_process, Help: The current number of orders being processed., }, ) // 3. 定义一个Histogram用于统计订单处理耗时秒 OrderProcessingDurationSeconds promauto.NewHistogramVec( prometheus.HistogramOpts{ Namespace: namespace, Subsystem: subsystem, Name: order_processing_duration_seconds, Help: Histogram of order processing duration in seconds., Buckets: prometheus.DefBuckets, // 使用默认桶也可自定义如 []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} }, []string{order_type}, // 标签订单类型如normal, flash_sale ) ) // Init函数可用于执行一些初始设置非必须 func Init() { // 例如可以在这里注册自定义的Collector }第三步在业务代码中操作指标在你的订单服务逻辑中你需要对定义的指标进行增减和记录。package service import ( context time your_project/metrics ) func CreateOrder(ctx context.Context, req *OrderRequest) (*OrderResponse, error) { // 开始计时 startTime : time.Now() // 在处理前增加“进行中”订单数 metrics.OrdersInProcess.Inc() // 确保在函数退出时减少“进行中”订单数 defer metrics.OrdersInProcess.Dec() var err error var orderStatus string // ... 这里是复杂的业务逻辑比如库存检查、支付调用等 ... if err ! nil { orderStatus failed } else { orderStatus success } // 无论成功失败订单创建尝试次数1并打上支付方式和状态的标签 metrics.OrdersCreatedTotal.WithLabelValues(req.PaymentMethod, orderStatus).Inc() // 记录处理耗时打上订单类型标签 duration : time.Since(startTime).Seconds() metrics.OrderProcessingDurationSeconds.WithLabelValues(req.OrderType).Observe(duration) // ... 返回结果 ... }第四步暴露指标端点主函数中需要启动一个独立的HTTP服务来暴露指标。通常使用/metrics路径。package main import ( net/http github.com/prometheus/client_golang/prometheus/promhttp your_project/metrics ) func main() { // 初始化指标如果有需要 metrics.Init() // 注册Prometheus的默认指标如Go运行时指标、进程指标 // 这行代码会暴露很多有用的系统级指标强烈建议开启 http.Handle(/metrics, promhttp.Handler()) // 启动你的业务HTTP服务 http.HandleFunc(/api/create_order, orderHandler) // ... 其他路由 ... // 通常指标暴露端口如9091与业务端口如8080分开 // 这里为了简单放在同一个端口的不同路径下 http.ListenAndServe(:8080, nil) }现在你的应用在http://your-app:8080/metrics端点就会输出Prometheus格式的指标数据了。访问它你会看到类似如下的文本# HELP myapp_order_service_orders_created_total The total number of created orders. # TYPE myapp_order_service_orders_created_total counter myapp_order_service_orders_created_total{payment_methodalipay,statussuccess} 42 myapp_order_service_orders_created_total{payment_methodwechat,statusfailed} 3 # HELP myapp_order_service_orders_in_process The current number of orders being processed. # TYPE myapp_order_service_orders_in_process gauge myapp_order_service_orders_in_process 7 # HELP myapp_order_service_order_processing_duration_seconds Histogram of order processing duration in seconds. # TYPE myapp_order_service_order_processing_duration_seconds histogram myapp_order_service_order_processing_duration_seconds_bucket{order_typenormal,le0.005} 0 myapp_order_service_order_processing_duration_seconds_bucket{order_typenormal,le0.01} 2 ... myapp_order_service_order_processing_duration_seconds_sum{order_typenormal} 15.6 myapp_order_service_order_processing_duration_seconds_count{order_typenormal} 453.2 其他语言与框架的集成要点Java (Spring Boot)使用micrometer库。它是监控门面可以对接Prometheus、Atlas、Datadog等多种监控系统。在Spring Boot中只需添加micrometer-registry-prometheus依赖并在配置文件中启用相关端点management.endpoints.web.exposure.includeprometheus,health,info它就会自动收集大量应用指标如JVM、HTTP请求并暴露在/actuator/prometheus。Python使用prometheus_client库。其使用模式与Go类似你需要手动创建和更新指标并启动一个HTTP服务来暴露它们。Node.js使用prom-client库。这是Node.js生态最常用的Prometheus客户端。实操心得对于微服务架构我强烈建议在每个服务启动时通过环境变量或配置中心注入一个全局的、唯一的标签比如service_name、instance_id可用主机名端口、environmentprod/staging/dev。这可以在Prometheus服务端通过relabel_configs配置确保从所有服务抓取到的指标都自动带上这些标识在做全局视图和聚合时无比方便。例如在Go中你可以用promauto.NewCounterVec创建指标时在ConstLabels中设置但更灵活的方式是在Prometheus的抓取配置中统一添加。4. Prometheus服务端抓取配置详解你的应用暴露了指标现在需要让Prometheus Server来定期抓取Scrape这些数据。这是通过修改Prometheus的配置文件prometheus.yml中的scrape_configs部分实现的。4.1 静态配置与动态服务发现静态配置最简单的方式直接写明目标地址。适用于服务数量固定、IP变化不频繁的环境。scrape_configs: - job_name: order-service # 覆盖全局的抓取间隔 scrape_interval: 15s static_configs: - targets: [order-svc-1:8080, order-svc-2:8080] labels: environment: production service: order这里Prometheus会每15秒去抓取order-svc-1:8080/metrics和order-svc-2:8080/metrics并且自动为这两个目标抓取到的所有指标加上environmentproduction和serviceorder的标签。动态服务发现在现代容器化如Kubernetes或云环境中服务实例是动态变化的。Prometheus支持多种服务发现机制Kubernetes SD自动发现Kubernetes集群中的Pod、Service、Endpoint等资源。Consul SD从Consul目录服务中发现实例。DNS SD通过DNS SRV记录或A记录发现目标。文件 SD从指定的JSON或YAML文件中读取目标列表文件变化会自动重载。以Kubernetes为例一个常见的抓取Pod的配置如下scrape_configs: - job_name: kubernetes-pods kubernetes_sd_configs: - role: pod relabel_configs: # 只抓取带有注解 prometheus.io/scrape: true 的Pod - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true # 从Pod注解中获取抓取路径默认为 /metrics - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.) # 从Pod注解中获取抓取端口 - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port] action: replace target_label: __address__ regex: (.);(.) replacement: ${1}:${2} # 添加一些有用的标签如命名空间、Pod名、容器名 - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name - source_labels: [__meta_kubernetes_pod_container_name] action: replace target_label: container这种配置下你只需要在Kubernetes Pod的注解Annotations里加上prometheus.io/scrape: truePrometheus就会自动发现并抓取它极大地简化了管理。4.2 Relabeling重标签的魔法relabel_configs是Prometheus配置中最强大也最令人困惑的部分之一。它发生在抓取之前relabel_configs和抓取之后metric_relabel_configs允许你动态地修改目标的标签甚至决定是否抓取这个目标。核心概念source_labels从目标元数据或已有标签中选择一个或多个标签的值。separator连接多个source_labels值时的分隔符默认为;。regex一个正则表达式用于匹配source_labels连接后的字符串。action执行的动作常见的有keep/drop根据regex匹配结果保留或丢弃此目标。replace用replacement字段的内容替换匹配的部分并赋值给target_label。labelmap将匹配的regex应用于所有标签名并将匹配的部分重命名为replacement中指定的新标签名。labeldrop/labelkeep丢弃或保留匹配regex的标签。一个实用案例假设你的服务暴露的指标里有一个标签叫instance它的值是主机名如host-192-168-1-1。你想把它替换成更易读的别名或者从中提取IP地址作为一个新标签。scrape_configs: - job_name: my-service static_configs: - targets: [svc:8080] metric_relabel_configs: # 对抓取到的指标进行重标签 - source_labels: [instance] regex: host-(\d)-(\d)-(\d)-(\d) target_label: ip_address replacement: ${1}.${2}.${3}.${4} action: replace这样抓取后指标中的instance标签值不变但会多出一个ip_address192.168.1.1的标签。5. 使用Exporters桥接第三方系统不是所有系统都原生支持Prometheus指标暴露比如MySQL、Redis、Kafka、硬件设备等。这时就需要Exporter导出器。Exporter是一个独立的代理程序它从目标系统如MySQL中通过其原生协议如SQL查询拉取运行状态和指标然后转换成Prometheus格式并暴露出来。5.1 部署与配置通用模式以mysqld_exporter为例下载并运行Exporter从Prometheus官网下载对应系统的二进制文件。./mysqld_exporter --config.my-cnf.my.cnf其中.my.cnf文件包含了连接MySQL的凭证[client] userexporter passwordyour_secure_password host127.0.0.1 port3306配置Prometheus抓取在prometheus.yml中添加一个新的抓取任务。- job_name: mysql static_configs: - targets: [mysql-exporter-host:9104] # mysqld_exporter默认端口9104 labels: environment: production db_cluster: order_db验证访问http://mysql-exporter-host:9104/metrics你应该能看到大量以mysql_开头的指标如mysql_global_status_connections当前连接数、mysql_global_status_threads_running正在运行的线程数等。5.2 编写自定义Exporter进阶当没有现成的Exporter满足需求时比如需要监控一个自研的中间件或特定的业务数据源你就需要自己写一个。这本质上就是写一个能查询数据并暴露/metrics端点的小型HTTP服务。用Go语言写一个简单的Exporter框架package main import ( log net/http time github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/promauto github.com/prometheus/client_golang/prometheus/promhttp ) // 假设我们要监控一个外部API的可用性 var ( apiUp promauto.NewGaugeVec( prometheus.GaugeOpts{ Name: external_api_up, Help: Whether the external API is up (1) or down (0)., }, []string{api_name}, ) ) func checkAPI(apiName, apiURL string) { // 这是一个模拟的检查函数 go func() { for { resp, err : http.Get(apiURL) if err nil resp.StatusCode 200 { apiUp.WithLabelValues(apiName).Set(1) } else { apiUp.WithLabelValues(apiName).Set(0) } time.Sleep(30 * time.Second) // 每30秒检查一次 } }() } func main() { // 启动对多个API的监控 checkAPI(payment_gateway, https://api.payment.com/health) checkAPI(sms_service, https://sms.provider.com/status) // 暴露指标 http.Handle(/metrics, promhttp.Handler()) log.Fatal(http.ListenAndServe(:2112, nil)) }这个简单的Exporter会每30秒检查两个外部API的健康状态并通过一个Gauge指标external_api_up暴露出来值1代表健康0代表异常。6. 数据可视化与告警Grafana与Alertmanager联动采集到自定义指标只是第一步让数据产生价值在于可视化分析和及时告警。6.1 在Grafana中创建自定义图表Grafana是Prometheus的最佳搭档。添加Prometheus数据源后你就可以用PromQL自由地创建仪表盘。针对我们之前定义的订单指标可以创建如下面板订单创建速率QPS面板查询rate(myapp_order_service_orders_created_total[5m])图例使用{{payment_method}} - {{status}}来区分不同支付方式和状态的曲线。可视化选择“Time series”图形可以清晰看到不同支付渠道的成功/失败请求趋势。订单处理延迟分布P99面板查询histogram_quantile(0.99, sum(rate(myapp_order_service_order_processing_duration_seconds_bucket[5m])) by (le, order_type))解释这个PromQL查询计算了过去5分钟内按order_type分组的订单处理延迟的99分位数。histogram_quantile函数是计算Histogram类型指标分位数的关键。可视化用“Stat”面板显示当前值或用“Time series”观察其变化趋势。设置一个阈值如1秒超过则标红。当前处理中订单数面板查询myapp_order_service_orders_in_process可视化使用“Gauge”仪表盘设置绿色0-10、黄色10-20、红色20区间一目了然。实操心得在Grafana中不要只做“展示板”更要做“分析板”。多使用“Transform”功能比如“Labels to fields”可以将标签值变成表格的列方便对比。对于重要的业务指标建议设置“Alert”规则直接在Grafana里告警虽然更推荐用Prometheus的Alertmanager并添加“Annotations”在图上标记出每次发布或故障的时间点便于回溯分析。6.2 配置Prometheus告警规则告警规则定义在独立的规则文件如alerts.yml中并在prometheus.yml里通过rule_files配置加载。示例为订单处理延迟和失败率创建告警规则groups: - name: order_service_alerts rules: # 规则1订单处理P99延迟过高 - alert: HighOrderProcessingLatency expr: | histogram_quantile(0.99, sum(rate(myapp_order_service_order_processing_duration_seconds_bucket{order_typenormal}[5m])) by (le)) 2 for: 2m # 持续2分钟满足条件才触发 labels: severity: warning service: order annotations: summary: 订单处理延迟过高 (实例 {{ $labels.instance }}) description: | 普通订单的P99处理延迟已超过2秒当前值为 {{ $value }} 秒。 这可能意味着数据库压力大或下游服务响应慢。 # 规则2订单创建失败率激增 - alert: HighOrderCreationFailureRate expr: | sum(rate(myapp_order_service_orders_created_total{statusfailed}[5m])) by (payment_method) / sum(rate(myapp_order_service_orders_created_total[5m])) by (payment_method) 0.05 # 失败率超过5% for: 3m labels: severity: critical service: order annotations: summary: {{ $labels.payment_method }} 支付方式订单创建失败率过高 description: | {{ $labels.payment_method }} 支付失败率已达 {{ $value | humanizePercentage }}。 请立即检查支付网关或相关服务。告警规则关键字段解析alert告警名称。exprPromQL表达式结果为布尔值True/False或一个数值。当结果为True或非零时表示触发告警条件。for持续时长。只有表达式连续满足该时长告警才会从“Pending”状态进入“Firing”状态防止因瞬时抖动产生误报。labels为触发的告警附加额外的标签这些标签会传递给Alertmanager用于路由、分组和抑制。annotations包含更详细的告警信息如summary摘要和description描述可以使用模板变量如{{ $labels.instance }}{{ $value }}引用告警实例的标签和数值。6.3 使用Alertmanager进行告警管理Prometheus负责“触发”告警而Alertmanager负责“管理”告警——去重、分组、静默、抑制并通过不同渠道如钉钉、企业微信、Slack、邮件、PagerDuty通知给正确的人。一个典型的alertmanager.yml配置如下global: smtp_smarthost: smtp.example.com:587 smtp_from: alertmanagerexample.com smtp_auth_username: user smtp_auth_password: password route: group_by: [alertname, service, severity] # 按告警名、服务、严重程度分组 group_wait: 30s # 同一分组内等待30s收集可能同时发生的其他告警 group_interval: 5m # 同一分组内已发送的告警如果未解决5分钟后再次发送 repeat_interval: 12h # 不同分组的告警重复通知间隔 receiver: default-receiver routes: - match: severity: critical receiver: critical-receiver continue: false # 匹配后不再继续向下路由 receivers: - name: default-receiver email_configs: - to: team-alertsexample.com - name: critical-receiver webhook_configs: - url: http://dingtalk-webhook-proxy/your-secret # 钉钉机器人Webhook地址 send_resolved: true # 发送恢复通知这个配置实现了将所有告警默认发邮件将严重程度为critical的告警额外通过钉钉机器人发送确保紧急问题能被即时响应。7. 实战避坑指南与性能调优在实际大规模使用自定义指标时你会遇到一些典型问题和性能挑战。7.1 高基数问题监控系统的“隐形杀手”这是自定义指标最容易踩的坑。高基数High Cardinality指的是一个指标标签组合产生了海量的、唯一的时间序列。例如如果你把用户ID作为标签http_requests_total{user_id12345, endpoint/home}假设你有100万用户访问10个端点这个指标理论上会产生1000万个时间序列。Prometheus每个时间序列都需要在内存中维护索引这会迅速耗尽内存导致Prometheus崩溃。如何避免绝对不要将UUID、会话ID、IP地址除非经过聚合、完整的URL路径除非经过处理等作为标签。使用有界枚举值将连续值或大量离散值转换为有限的类别。例如将响应时间连续值用Histogram的桶le标签来表示将HTTP状态码如404归类为status_class4xx。在应用层做聚合有时在业务代码中先做一次聚合再暴露指标更合适。例如不暴露每个用户的请求数而是暴露按用户等级如vip normal聚合的请求数。利用metric_relabel_configs丢弃如果某些高基数标签不可避免地被暴露可以在Prometheus抓取时使用metric_relabel_configs的labeldrop动作将其丢弃或者用keep/drop动作过滤掉某些高基数的序列。7.2 指标命名与标签设计规范混乱的命名和标签设计会让后续的查询和告警规则变得极其复杂。命名规范采用snake_case包含单位如_seconds,_bytes,_total。使用前缀标识领域如http_process_business_。我们之前的myapp_order_service_orders_created_total就是一个好例子。标签设计原则正交性标签之间应尽可能独立。例如method和status_code是正交的一个描述“怎么请求”一个描述“结果如何”。稳定性标签值不应频繁变化。避免使用像“当前处理节点”这种随时会变的标签。实用性设计的标签要能切实用于你后续的查询、分组和告警。在设计指标前先想好你要怎么用它。7.3 抓取性能与资源优化调整抓取间隔scrape_interval不是所有指标都需要15秒抓取一次。对于变化缓慢的指标如软件版本号可以设置为几分钟甚至几小时。在scrape_configs的job级别或全局设置。限制抓取超时scrape_timeout默认是10秒。如果某个Exporter响应慢会阻塞抓取循环。根据实际情况调低。使用Prometheus的“抓取池”通过scrape_configs中的scrape_pool相关配置如scrape_limit在较新版本中可以限制并发抓取数避免瞬时负载过高。监控Prometheus自身务必启用并监控Prometheus自身的指标prometheus_开头如prometheus_target_scrape_pool_exceeded抓取目标是否被跳过、prometheus_tsdb_head_series当前时间序列总数等这是发现问题的第一手资料。7.4 指标生命周期与版本管理业务代码在迭代指标也会变化。直接删除或修改一个已有指标的标签会导致Prometheus中存储的旧时间序列和新时间序列变成两个完全不同的序列造成图表中断和告警失效。最佳实践不删不改只增当需要调整指标时优先考虑创建新的指标如orders_created_total_v2让新旧指标并行运行一段时间。设置弃用期在代码和文档中标记旧指标为“已弃用”Deprecated并通过告警规则监控旧指标是否还有数据流入确保所有消费方如图表、告警都已迁移到新指标后再停止暴露旧指标。使用常量标签ConstLabels对于像应用版本version这种全局且不常变的属性可以在创建指标时通过ConstLabels设置而不是作为普通标签。这样版本升级时新版本应用暴露的就是一个全新的指标序列逻辑清晰。自定义指标监控是将Prometheus从“系统监控工具”升级为“业务可观测性平台”的关键一步。它要求开发者和运维者深入协作共同定义出能真实反映系统健康度和业务价值的指标。这个过程始于对Prometheus数据模型的深刻理解成于规范的客户端集成和严谨的标签设计最终在Grafana的图表和Alertmanager的告警中产生价值。记住好的监控不在于指标的数量而在于指标的质量和你能从中学到什么。
返回列表