如何用 Grafana 和 Elasticsearch 搭建 API 监控

从零搭建生产级 API 监控 —— Elasticsearch 数据源、Lucene 查询、Grafana 面板与告警规则。

zhuermu··18 分钟
GrafanaElasticsearch监控可观测性告警DevOps

你的 API 正在生产环境中运行。用户在访问各个端点,服务之间相互调用,一切看起来都很正常 —— 直到出问题为止。某个支付端点开始返回 500 错误;搜索路由的延迟从 200ms 悄悄爬升到 3 秒;某个下游依赖挂掉,错误率从 0.1% 飙升到 12%。如果没有监控,你只能从愤怒的用户口中得知这些问题。而有了合适的仪表盘,你能在几分钟内发现问题,往往在用户察觉之前就已经知道。

本文将带你使用 Grafana 11.x 搭配 Elasticsearch 作为数据源,构建一套完整的 API 监控仪表盘。我们会讲解整体架构、数据源配置、六个核心仪表盘面板(附带真实的查询语法)、基于 Grafana 统一告警(Unified Alerting)系统的告警配置,以及那些能让仪表盘从”随便瞥一眼”进化为”真正预防故障”的生产实战技巧。


为什么 API 监控很重要

在深入具体工具之前,值得先用现代运维团队思考可靠性的框架来铺垫一下这个话题:SLO、SLI 与错误预算

服务水平指标(SLI) 是你实际测量的指标 —— 请求延迟、错误率、吞吐量。服务水平目标(SLO) 是你为这些指标设定的目标 —— 比如”99.5% 的请求成功完成”或”P95 延迟保持在 300ms 以下”。错误预算 则是完美与你的 SLO 之间的差距:如果 SLO 是 99.5% 的成功率,那么每个测量窗口内你就有 0.5% 的错误预算。

本文要构建的仪表盘直接测量了 Google SRE 手册中定义的四大黄金信号里的三个:

  1. 延迟(Latency) —— 请求耗时(P50、P95、P99)
  2. 流量(Traffic) —— 每分钟有多少请求流经系统
  3. 错误(Errors) —— 有多少百分比的请求失败

第四个信号 饱和度(Saturation) 通常来自基础设施指标(CPU、内存、磁盘),而非访问日志。这四个信号合在一起,能为你勾勒出 API 健康状况的全景图。

它的实用价值立竿见影:当凌晨 3 点因为 /api/v1/payments 的错误率超过 2% 而触发告警时,值班工程师打开仪表盘,看到这次飙升恰好始于一次新部署上线,再关联到同一端点上的延迟增长,就有了足够的上下文来决定是回滚还是深入排查具体的故障模式 —— 整个过程只需几分钟。


架构

监控管线其实很简单:API 流量产生访问日志,这些日志流入 Elasticsearch,Grafana 再查询 Elasticsearch 来驱动仪表盘和告警。

监控架构

下面是各个组件的职责:

API 网关(nginx、AWS ALB、Kong 等) 作为所有 API 流量的入口。网关为每个请求写入结构化的访问日志,包括 HTTP 方法、路径、状态码、响应时间、客户端 IP 和请求大小。这里的关键决策是日志格式 —— 尽可能使用 JSON,因为它能省去下游复杂的解析规则。

一个典型的 nginx JSON 日志配置如下:

log_format json_combined escape=json
  '{'
    '"timestamp":"$time_iso8601",'
    '"method":"$request_method",'
    '"path":"$uri",'
    '"status":$status,'
    '"response_time":$request_time,'
    '"bytes_sent":$bytes_sent,'
    '"remote_addr":"$remote_addr",'
    '"user_agent":"$http_user_agent",'
    '"upstream_response_time":"$upstream_response_time",'
    '"request_id":"$request_id"'
  '}';

access_log /var/log/nginx/api_access.log json_combined;

日志采集器(Filebeat 或 Fluentd) 负责读取日志文件、解析它们,并发送到 Elasticsearch。Filebeat 更轻量,且与 Elastic Stack 原生集成。如果你需要把日志路由到多个目的地,Fluentd 则更灵活。

一个用于采集 nginx JSON 日志的最小化 Filebeat 配置:

filebeat.inputs:
  - type: filestream
    id: api-access-logs
    paths:
      - /var/log/nginx/api_access.log
    parsers:
      - ndjson:
          target: ""
          add_error_key: true

output.elasticsearch:
  hosts: ["https://elasticsearch:9200"]
  index: "api-access-%{+yyyy.MM.dd}"
  username: "${ES_USERNAME}"
  password: "${ES_PASSWORD}"

setup.ilm.enabled: true
setup.ilm.rollover_alias: "api-access"
setup.ilm.pattern: "{now/d}-000001"

Elasticsearch 存储访问日志,并提供 Grafana 查询所依赖的聚合引擎。每条访问日志都会成为时序索引(例如 api-access-2023.01.08)中的一个文档。正是 Elasticsearch 的聚合框架 —— terms、date histogram、percentiles、filters —— 让”按端点分组统计过去一小时的 P99 延迟”这类指标能够实时计算出来。

Grafana 查询 Elasticsearch 以渲染仪表盘面板并评估告警规则。Grafana 的 Elasticsearch 数据源插件原生支持 Elasticsearch 查询 DSL,因此你可以在面板编辑器中使用 Lucene 语法和聚合构建器来配置查询。


配置 Grafana 与 Elasticsearch

3.1 添加 Elasticsearch 数据源

在 Grafana 11.x 中,进入 Connections > Data sources > Add data source,选择 Elasticsearch。关键配置字段如下:

字段说明
URLhttps://elasticsearch:9200生产环境请使用 HTTPS
AuthenticationBasic Auth 或 API Key绝不要禁用认证
Index nameapi-access-*通配符匹配每日索引
Time fieldtimestamp必须与日志中的时间戳字段一致
Max concurrent shard requests5防止仪表盘查询压垮 ES
Min time interval1m与日志粒度保持一致

如果你使用的是 Amazon OpenSearch Service,配置方式完全相同 —— Grafana 的 Elasticsearch 插件与 OpenSearch 兼容。只需将 URL 指向你的 OpenSearch 域名端点,并通过 Sigv4 auth 选项使用基于 IAM 的认证即可。

3.2 索引模式与映射注意事项

要让仪表盘查询正常工作,你的 Elasticsearch 索引映射需要满足几个条件:

  • timestamp 字段必须是 date 类型(而非 textkeyword)。
  • status 字段应为 integerkeyword。如果是 text,聚合将无法工作。
  • response_time 字段必须是 floatdouble,才能进行百分位计算。
  • path 字段应为 keyword(而非 text),这样 terms 聚合才能返回完整的路径,而不是被分词后的碎片。

你可以用以下命令验证映射:

curl -s "https://elasticsearch:9200/api-access-*/_mapping" | jq '.[] .mappings.properties | {timestamp, status, response_time, path}'

如果字段被错误地映射成了 text,可以创建一个索引模板来强制使用正确的类型:

PUT _index_template/api-access
{
  "index_patterns": ["api-access-*"],
  "template": {
    "mappings": {
      "properties": {
        "timestamp": { "type": "date" },
        "method": { "type": "keyword" },
        "path": { "type": "keyword" },
        "status": { "type": "integer" },
        "response_time": { "type": "float" },
        "bytes_sent": { "type": "long" },
        "remote_addr": { "type": "ip" },
        "user_agent": { "type": "text" },
        "request_id": { "type": "keyword" }
      }
    }
  }
}

构建仪表盘面板

仪表盘布局

仪表盘分为两行,每行三个面板。上面一行展示高层次的健康指标(请求速率、成功率、延迟),下面一行展示详细的拆解(状态码分布、最慢端点、按路由的错误情况)。

4.1 请求速率(requests/min)

这个面板展示 API 每分钟处理多少请求,并按状态码类别拆分。

面板类型: Time series(时序图)

Elasticsearch 查询配置:

  • Metric: Count
  • Group by:timestamp 做 Date Histogram,间隔 1m
  • Group by(第二层):status 做 Terms(用于按状态码拆分)

在 Grafana 面板编辑器中,查询大致如下:

Query: *
Metric: Count
Group by: Date Histogram (timestamp) — Interval: 1m
         Terms (status) — Order: Top, Size: 10

如果想要一个更清爽的视图,按状态码类别(2xx、3xx、4xx、5xx)而非单个状态码分组,可以采用多条 Lucene 查询 的方式:

  • Query A: status:[200 TO 299] —— 标签:“2xx”
  • Query B: status:[300 TO 399] —— 标签:“3xx”
  • Query C: status:[400 TO 499] —— 标签:“4xx”
  • Query D: status:[500 TO 599] —— 标签:“5xx”

每条查询都使用 Count 作为指标,并对 timestamp 做间隔为 1m 的 Date Histogram。

4.2 成功率(%)

成功率是指返回 2xx 状态码的请求所占的百分比。这是你衡量可用性的首要 SLI。

面板类型: Stat(用于展示大数字)或 Time series(用于展示趋势)

在 Grafana 中用 Elasticsearch 计算比率需要一些额外配置。有两种方法:

方法一:使用 Bucket Script(推荐用于 Grafana 11.x)

配置一条 Elasticsearch 查询:

Metric A: Count (all requests)
Metric B: Count with Lucene query filter: status:[200 TO 299]
Pipeline: Bucket Script
  Expression: params.B / params.A * 100
Group by: Date Histogram (timestamp) — Interval: 1m

Bucket Script 管线聚合能让你在每个时间桶上计算 (成功请求数 / 总请求数) * 100

方法二:使用 Grafana Transformations

创建两条查询 —— 一条统计总请求数(Count,无过滤),另一条统计成功请求数(Count,过滤条件 status:[200 TO 299])。然后添加一个 Transform > Calculate field 步骤,操作为 Query B / Query A * 100

对于展示大数字的 Stat 面板,将 Value options > Calculation 设为 “Last” 或 “Mean”,取决于你想看当前值还是平均成功率。并在 SLO 边界处设置阈值:

{
  "thresholds": {
    "steps": [
      { "color": "red", "value": null },
      { "color": "orange", "value": 99 },
      { "color": "green", "value": 99.5 }
    ]
  }
}

4.3 P50/P95/P99 延迟

延迟百分位告诉你请求对中位数用户(P50)、尾部用户(P95)以及极端尾部用户(P99)分别有多快。问题往往就藏在 P99 里 —— 某个端点对大多数用户来说可能感觉很快,但对 1% 的用户却慢得令人痛苦。

面板类型: Time series(时序图)

Elasticsearch 查询配置:

Query: *
Metric: Percentiles on field "response_time"
  Percentile values: 50, 95, 99
Group by: Date Histogram (timestamp) — Interval: 1m

Elasticsearch 的百分位聚合使用 t-digest 算法,它是近似计算但内存效率很高 —— 适合处理高基数的时序数据。

要添加一条可视化的 SLO 参考线(例如”P95 必须保持在 300ms 以下”),可以使用 Dashboard > Annotations > Add annotation query,或者干脆在面板的 Thresholds 配置中添加一条阈值线,设为 300 并用红色标示。

4.4 HTTP 状态码分布

用饼图展示 HTTP 状态码的整体分布,能帮你一眼发现异常模式 —— 例如 429(限流)或 401(认证失败)突然激增。

面板类型: Pie chart(饼图)

Elasticsearch 查询配置:

Query: *
Metric: Count
Group by: Terms on "status" — Order: Top, Size: 20

可以按语义含义覆盖颜色:

状态码范围颜色
200-299绿色
301、302、304蓝色
400-499橙色
500-599红色

4.5 最慢的端点 Top 榜

这个面板回答了一个问题:“现在哪些端点最慢?“它在部署后识别性能回退时格外有价值。

面板类型: Table(表格)

Elasticsearch 查询配置:

Query: *
Metric: Average on field "response_time"
Group by: Terms on "path" — Order by: Average response_time (desc), Size: 15

为了让表格更有用,可以添加额外的指标:

Metric A: Average on "response_time" (alias: "Avg Latency (ms)")
Metric B: Percentiles on "response_time", value: 99 (alias: "P99 (ms)")
Metric C: Count (alias: "Request Count")
Group by: Terms on "path" — Order by: Metric A desc, Size: 15

这样你就能看到每个端点的平均延迟、P99 延迟和请求量 —— 足以区分”这个端点慢是因为某个离群值”和”这个端点一直都很慢”这两种情况。

4.6 按端点划分的错误率

这个面板展示哪些具体端点的错误率最高,帮助你确定排查的优先级。

面板类型: Bar gauge(水平柱状仪表)

Elasticsearch 查询配置:

这需要一个两步聚合。首先计算每个端点的错误数和总数,然后计算比率:

Query A: status:[400 TO 599]
  Metric: Count
  Group by: Terms on "path" — Order: Top, Size: 10

Query B: *
  Metric: Count
  Group by: Terms on "path" — Order: Top, Size: 10

然后对 path 应用 Transform > Join by field,再接一个 Transform > Add field from calculation,公式为 Query A / Query B * 100。或者,也可以在单条查询中使用 Bucket Script 方式:

Metric A: Count (all requests per path)
Metric B: Count with inline filter: status:[400 TO 599]
Pipeline: Bucket Script — Expression: params.B / params.A * 100
Group by: Terms on "path" — Order by: Bucket Script desc, Size: 10

Grafana 告警

Grafana 9+ 用 统一告警(Unified Alerting) 取代了老旧的按面板告警系统。它是一个独立的告警引擎,支持多维度评估、专用的规则编辑器,以及完整的通知管线。如果你还在用旧系统,很值得迁移 —— 统一告警的能力要强大得多。

5.1 告警规则

Grafana 中的告警规则会按计划评估一个查询表达式,并在条件满足时触发。下面是一个针对高错误率的告警规则示例:

# Alert: API Error Rate > 2%
apiVersion: 1
groups:
  - orgId: 1
    name: api-monitoring
    folder: API Alerts
    interval: 1m
    rules:
      - uid: api-error-rate-high
        title: "API Error Rate Exceeds 2%"
        condition: C
        data:
          - refId: A
            relativeTimeRange:
              from: 300  # last 5 minutes
              to: 0
            datasourceUid: elasticsearch-ds
            model:
              query: "*"
              metrics:
                - type: count
                  id: "1"
              bucketAggs:
                - type: date_histogram
                  field: timestamp
                  id: "2"
                  settings:
                    interval: 1m
          - refId: B
            relativeTimeRange:
              from: 300
              to: 0
            datasourceUid: elasticsearch-ds
            model:
              query: "status:[400 TO 599]"
              metrics:
                - type: count
                  id: "1"
              bucketAggs:
                - type: date_histogram
                  field: timestamp
                  id: "2"
                  settings:
                    interval: 1m
          - refId: C
            datasourceUid: __expr__
            model:
              type: math
              expression: "$B / $A * 100"
              conditions:
                - evaluator:
                    type: gt
                    params: [2]
        for: 5m  # must breach for 5 consecutive minutes
        labels:
          severity: critical
          team: platform
        annotations:
          summary: "API error rate is {{ $value }}%, exceeding 2% threshold"
          dashboard_url: "https://grafana.example.com/d/api-monitoring"

对于 延迟告警,也适用类似的模式。监控 P99 延迟何时超过你的 SLO:

      - uid: api-p99-latency-high
        title: "API P99 Latency Exceeds 500ms"
        condition: B
        data:
          - refId: A
            datasourceUid: elasticsearch-ds
            model:
              query: "*"
              metrics:
                - type: percentiles
                  field: response_time
                  id: "1"
                  settings:
                    percents: ["99"]
              bucketAggs:
                - type: date_histogram
                  field: timestamp
                  id: "2"
                  settings:
                    interval: 1m
          - refId: B
            datasourceUid: __expr__
            model:
              type: threshold
              expression: A
              conditions:
                - evaluator:
                    type: gt
                    params: [500]
        for: 3m
        labels:
          severity: warning
          team: platform

5.2 联络点(Contact Points)

联络点定义了告警发送到哪里。Grafana 支持 Slack、PagerDuty、邮件、Microsoft Teams、Opsgenie、webhook 等众多渠道。

一个 Slack 联络点配置:

apiVersion: 1
contactPoints:
  - orgId: 1
    name: platform-team-slack
    receivers:
      - uid: slack-platform
        type: slack
        settings:
          recipient: "#platform-alerts"
          token: "${SLACK_BOT_TOKEN}"
          title: |
            {{ `{{ .Status | toUpper }}` }} {{ `{{ .CommonLabels.alertname }}` }}
          text: |
            {{ `{{ range .Alerts }}` }}
            *{{ `{{ .Labels.alertname }}` }}*
            {{ `{{ .Annotations.summary }}` }}
            Dashboard: {{ `{{ .Annotations.dashboard_url }}` }}
            {{ `{{ end }}` }}

用于 PagerDuty 集成(需要呼叫值班工程师的关键告警):

      - uid: pagerduty-platform
        type: pagerduty
        settings:
          integrationKey: "${PAGERDUTY_INTEGRATION_KEY}"
          severity: "{{ `{{ .CommonLabels.severity }}` }}"
          class: "api-monitoring"

5.3 通知策略与路由

通知策略根据标签将告警路由到正确的联络点。你就在这里实现”关键告警发往 PagerDuty,警告发往 Slack”这样的逻辑:

apiVersion: 1
policies:
  - orgId: 1
    receiver: platform-team-slack  # default receiver
    group_by: ["alertname", "team"]
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 4h
    routes:
      - receiver: pagerduty-platform
        matchers:
          - severity = critical
        continue: true  # also send to the default Slack receiver
      - receiver: platform-team-slack
        matchers:
          - severity = warning

5.4 静默(Silences)与静音时段(Mute Timings)

在计划内的维护窗口期间,你不希望告警乱响。Grafana 提供了两种机制:

静音时段(Mute timings) 定义周期性的窗口(例如”每周六 UTC 时间凌晨 2 点到 6 点”),在此期间抑制告警:

apiVersion: 1
muteTimes:
  - orgId: 1
    name: weekly-maintenance
    time_intervals:
      - times:
          - start_time: "02:00"
            end_time: "06:00"
        weekdays: ["saturday"]

静默(Silences) 是通过 Grafana UI 或 API 为特定维护事件创建的一次性抑制。它们按标签匹配告警,并在指定时长后过期。


仪表盘即代码(Dashboard as Code)

通过 Grafana UI 手动配置仪表盘在原型阶段没问题,但生产环境的仪表盘应当纳入版本控制并通过代码部署。Grafana 支持三种方式:

1. JSON Provisioning —— 把仪表盘 JSON 文件放到 Grafana 的 provisioning 目录(/etc/grafana/provisioning/dashboards/)中,Grafana 会在启动时加载它们。这是最简单的方式,也很适合基于 Git 的工作流。

# /etc/grafana/provisioning/dashboards/api-monitoring.yaml
apiVersion: 1
providers:
  - name: API Monitoring
    folder: Production
    type: file
    options:
      path: /var/lib/grafana/dashboards
      foldersFromFilesStructure: true

2. Terraform Provider —— Grafana Terraform provider 让你能把仪表盘、数据源、告警规则和联络点当作 Terraform 资源来管理。这与基础设施即代码的工作流天然契合:

resource "grafana_dashboard" "api_monitoring" {
  config_json = file("dashboards/api-monitoring.json")
  folder      = grafana_folder.production.id
}

resource "grafana_rule_group" "api_alerts" {
  org_id           = 1
  name             = "api-monitoring"
  folder_uid       = grafana_folder.production.uid
  interval_seconds = 60

  rule {
    name      = "API Error Rate Exceeds 2%"
    condition = "C"
    for       = "5m"
    # ... data and expressions
  }
}

3. Grafonnet(Jsonnet 库) —— 对于需要管理大量共享同一模式的仪表盘的团队,Grafonnet 提供了一种编程化的方式,从可复用的模板生成仪表盘 JSON。这就避免了手工编辑 JSON 常见的复制粘贴漂移问题。


生产实战技巧

7.1 用仪表盘变量做筛选

在查询中硬编码具体值会让仪表盘变得僵化。使用 Grafana 模板变量,让用户能按服务、环境或端点动态筛选。

定义一个环境变量:

Name: environment
Type: Query
Data source: Elasticsearch
Query: {"find": "terms", "field": "environment.keyword", "size": 20}

定义一个 API 路径变量:

Name: path
Type: Query
Data source: Elasticsearch
Query: {"find": "terms", "field": "path.keyword", "size": 100}

然后在面板查询中用 Lucene 语法引用它们:

environment:$environment AND path:$path

这样一来,这一个仪表盘就能服务于每个服务和每个环境。顶部的下拉框让任何人都能精确筛选出自己需要的内容。

7.2 来自 CI/CD 部署的注解

当出问题时,第一个问题永远是”有什么变化吗?“注解(Annotations) 把部署事件直接叠加在你的时序图上,让部署与指标变化之间的关联一目了然。

从你的 CI/CD 管线推送注解:

curl -X POST "https://grafana.example.com/api/annotations" \
  -H "Authorization: Bearer ${GRAFANA_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "dashboardUID": "api-monitoring",
    "time": '"$(date +%s)000"',
    "tags": ["deploy", "api-service"],
    "text": "Deployed api-service v2.4.1 (commit: abc123)"
  }'

这些注解会以竖线的形式出现在时序面板上,让你能在部署与指标变化之间瞬间建立起可视化的关联。

7.3 索引生命周期管理

访问日志可能产生海量数据。配置 Elasticsearch 的 索引生命周期管理(ILM),自动滚动、收缩并删除旧索引:

PUT _ilm/policy/api-access-policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50gb",
            "max_age": "1d"
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "shrink": { "number_of_shards": 1 },
          "forcemerge": { "max_num_segments": 1 }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": { "delete": {} }
      }
    }
  }
}

这能让你的热数据保持快速、可查询,同时自动清理旧数据。

7.4 仪表盘的组织结构

随着监控规模的增长,组织结构变得很重要。一个实用的结构:

Production/
  API Monitoring/
    Overview (the dashboard we built)
    Per-Service Deep Dive
    SLO Tracking
  Infrastructure/
    ECS/EC2 Metrics
    RDS Performance
    ElastiCache Metrics

仪表盘链接(dashboard links) 把相关的仪表盘串联起来。总览仪表盘应当链接到按服务的深度分析页,并预先筛选到相关的服务。这就形成了一条自然的下钻路径:告警触发,值班工程师打开总览,锁定受影响的服务,点击进入深度分析页寻找根因。

7.5 规避常见的坑

有几点是我们用血泪教训换来的:

托管版 Grafana 上的插件安装。 如果你运行的是托管版 Grafana 实例(例如 Amazon Managed Grafana、Azure Managed Grafana,或某个云厂商托管的产品),插件安装可能会受限。某些未签名的插件需要在 grafana.ini 中显式加入白名单:

[plugins]
allow_loading_unsigned_plugins = goshposh-metaqueries-datasource

不过,凭借现代 Grafana 内置的 Bucket Script 和转换能力,对第三方 MetaQuery 插件的需求已基本消失。Bucket Script 管线聚合(见 4.2 节)原生就能处理比率计算。

数据源连通性。 配置 Elasticsearch 数据源时,务必确认你使用的主机名或 IP 是从 Grafana 服务器实际可达的地址。在容器化环境中,管理控制台里显示的”内网 IP”可能是负载均衡器的 VIP,而非真正的容器 IP。请始终从 Grafana 容器内部验证连通性:

# From inside the Grafana container
curl -v "https://elasticsearch-host:9200/_cluster/health"

查询性能。 那些查询高基数字段(如 user_agentremote_addr)并带有大 terms 聚合的仪表盘面板可能会很慢。把 terms 聚合中的 size 参数保持在合理范围(仪表盘面板用 10-20),并使用数据源配置中的 Min time interval 设置来防止查询粒度过细。


结语

我们构建的这套仪表盘让你对 API 健康状况有了全面的可见性:请求量、成功率、延迟百分位、状态码分布、最慢端点,以及按路由的错误率。再结合 Grafana 的统一告警,你就能在 SLO 面临风险时获得主动通知,并通过正确的渠道送达正确的人。

不过,真正的价值并不在于任何单个面板或告警,而在于它们的组合:当告警触发时,仪表盘为排查提供即时的上下文;当部署出错时,注解精确显示它发生的时刻;当有人问”API 健康吗?“时,你可以直接指向一个 URL,而不必临时跑一堆查询。

如果你是从零开始,先从最重要的三个面板做起 —— 成功率、P99 延迟和按端点的错误率 —— 并为每个配一条告警。你随时可以之后再添加更多面板,但这三个已经能捕获生产环境中绝大多数的问题。先把告警做对,再让仪表盘变得好用,最后再打磨细节。

参考资料

  1. Grafana documentation — Grafana
  2. Elasticsearch reference — Elastic
  3. Prometheus overview — Prometheus