运维咖啡吧

享受技术带来的乐趣,体验生活给予的感动

构建好用的Cloudflare监控大盘

多云监控系统要接入Cloudflare的监控,当初接入时,看了Cloudflare页面里的图表,都是通过GraphQL查询获取数据展示的,随后去查了Cloudflare的官方文档,发现了graphql-api:

https://developers.cloudflare.com/analytics/graphql-api/

根据API文档,获取数据很简单,示例如下:

import json
import requests


class CloudFlareAPI:
    def __init__(self, email: str, token: str):
        self.session = requests.Session()

        self.session.headers = {
            "X-Auth-Email": email,
            "X-Auth-Key": token,
            "Content-Type": "application/json"
        }

    def graphql(self, query):
        _result = self.session.post(
            "https://api.cloudflare.com/client/v4/graphql", 
            data=json.dumps({'query': query})
        )

        return True, 200, _result.json()

可以看出来API很简单,通过email和token认证,认证过之后调用graphql-api,核心就在GraphQL对query语句,GraphQL语句很强大,但同时也很复杂,而我并不熟悉GraphQL语句,于是图方便,就直接拷贝了官方页面请求里对query语句

在后续的使用中虽然可用,但体验不好,由于对query语句并没有很深的了解,导致一个query语句中返回了并不需要的数据,这会造成两个问题,其一就是数据加载速度变慢,查询语句复杂了,返回数据多了,自然就慢了,很好理解,其二是Cloudflare返回的数据是有limit限制的,最大只能限制为10000,当一个query结果中加载的数据多了之后,同一粒度情况下能同时展示的时间段就会变短。更为关键的是如果想要调整还不是很方便,因为对GraphQL不熟悉

随着新项目上线对CDN的关注度增加,查询Cloudflare监控越来越频繁,对监控数据的需求也有改变,是时候再来认真的看看Cloudflare的监控了,短时间内想要对GraphQL能有多深的理解不现实,好在有开源工具GraphiQL来帮忙:

https://github.com/graphql/graphiql

GraphiQL是个专门用户调试GraphQL语句的工具,使用非常简单,填写Header头用于认证,输入URL和query语句即可执行,能够对query进行自动语法检查及提示,这样我即便是不知道详细的参数名字也能根据提示来修改,很好用

借助于官方文档一个简单的例子和AI,同时在工具的加持下,再写起来就快多了,例如我们通常需要获取某个域名一段时间内的总请求量和总数据传输量,就可以通过如下query来查询:

query{
  viewer{
    zones(filter:{zoneTag:"19ebc8************0e8f37"}){
      servedByEdge:httpRequestsAdaptiveGroups(
        limit:10000
        filter:{
          AND:[
          {datetime_geq:"2024-03-28T10:00:00Z", datetime_leq:"2024-03-28T11:00:00Z"},
          {requestSource:"eyeball"},
          {clientRequestHTTPHost: "blog.ops-coffee.cn"},
          ]
        }
      )
      {
        sum{
          edgeResponseBytes
        }
        count
      }
    }
  }
}

其中zoneTag为域名所在zone的id,filter配置过滤条件,指定开始时间datetime_geq、结束时间datetime_leq以及域名clientRequestHTTPHostcount为请求数,edgeResponseBytes则为数据传输量,而requestSource配置的意思则是要过滤掉Cloudflare的一些操作,例如cachepurge、healthchecks等等,以使数据更准确,贴近用户真实数据

如果需要生成图表,就需要时间段内每个时间点的数据,添加dimensions即可,同时可以配合orderBy来实现对结果的排序:

query{
  viewer{
    zones(filter:{zoneTag:"19ebc8************0e8f37"}){
      servedByEdge:httpRequestsAdaptiveGroups(
        limit:10000
        filter:{
          AND:[
          {datetime_geq:"2024-03-28T10:00:00Z", datetime_leq:"2024-03-28T11:00:00Z"},
          {requestSource:"eyeball"},
          {clientRequestHTTPHost: "blog.ops-coffee.cn"},
          ]
        }
        orderBy: [datetimeMinute_ASC]
      )
      {
        sum{
          edgeResponseBytes
        }
        count
        dimensions {
          datetimeMinute
        }        
      }
    }
  }
}

dimensions来配置颗粒度,颗粒度有1分钟datetimeMinute、5分钟datetimeFiveMinutes、15分钟datetimeFifteenMinutes等几个配置,orderBy也可以选择按请求值、数据传输量、时间等多种指标正序或倒序对结果进行排列输出

如果想要获取命中数据,则可以在之前的filter过滤基础上添加cacheStatus来获取命中数据

query{
  viewer{
    zones(filter:{zoneTag:"19ebc8************0e8f37"}){
      servedByEdge:httpRequestsAdaptiveGroups(
        limit:10000
        filter:{
          AND:[
          {datetime_geq:"2024-03-28T10:00:00Z", datetime_leq:"2024-03-28T11:00:00Z"},
          {requestSource:"eyeball"},
          {clientRequestHTTPHost: "blog.ops-coffee.cn"},
          {cacheStatus: "hit"}
          ]
        }
        orderBy: [datetimeMinute_ASC]
      )
      {
        sum{
          edgeResponseBytes
        }
        count
        dimensions {
          datetimeMinute
        }        
      }
    }
  }
}

而对于CDN更为重要的命中率数据通过query没办法直接获取,不过可以通过一个query同时获取到命中数和总数,输出时稍微加工即可获取到命中率,也算简单

query{
  viewer {
    zones(filter:{zoneTag:"19ebc8************0e8f37"}){
      hitData: httpRequestsAdaptiveGroups(
        limit: 10000
        filter: {
          AND: [
          {datetime_geq:"2024-03-28T10:00:00Z", datetime_leq:"2024-03-28T11:00:00Z"},
          {requestSource:"eyeball"},
          {clientRequestHTTPHost: "blog.ops-coffee.cn"},
          {cacheStatus: "hit"}
          ]
        }
        orderBy: [datetimeMinute_ASC]
      ) {
        dimensions {
          datetimeMinute
        }
        count
      }
      servedByEdge: httpRequestsAdaptiveGroups(
        limit: 10000
        filter: {
          AND: [
          {datetime_geq:"2024-03-28T10:00:00Z", datetime_leq:"2024-03-28T11:00:00Z"},
          {requestSource:"eyeball"},
          {clientRequestHTTPHost: "blog.ops-coffee.cn"},
          ]
        }
        orderBy: [datetimeMinute_ASC]
      ) {
        dimensions {
          datetimeMinute
        }
        count
      }
    }
  }
}

如果想要获取其他一些数据但不知道参数名字的话,除了借助于GraphiQL工具通过模糊搜索提示猜测参数名字外,还有一个小技巧是设置Cloudflare控制台为英文,然后去页面上查找对应的参数名字。例如未命中,我们在控制台里看到的名字叫Miss,那过滤名字也一样为miss只是需要小写

有了这些知识,构建一个完善的监控大盘已经足够了,CDN我们主要的关注数据有:总请求量、总数据传输量、总请求命中率、请求量趋势、数据传输量趋势、命中率趋势、请求命中趋势、请求未命中趋势以及2xx、3xx、4xx、5xx状态码趋势了。由此一个好用的监控大盘出现了

最关心的数据一页全展示,响应速度快,确实好用