菜单
文档breadcrumb arrow Beylabreadcrumb arrow 指标基数
Grafana Cloud

Beyla 指标基数

Beyla 指标的基数高度依赖于被插桩环境的大小和复杂性,因此无法提供一个简单准确的公式。

本文档试图提供 Beyla 默认安装可能产生的指标基数近似值。文档按 Beyla 可生成的每种指标类型分为几个部分,因为每种指标族都可以选择性地启用或禁用。

为简单起见,下面的公式假设只有一个集群。您应该将基数乘以您的集群数量。

术语

在继续之前,我们应澄清一些可能模糊或容易引起误解的术语

  • Instance:是每个插桩目标。在应用程序级别指标中,它是服务或客户端实例。在 Kubernetes 中,它是 Pod。在进程级别指标中,每个实例是每个报告的进程。一个应用程序实例可能运行在多个进程中。在网络级别指标中,每个实例是 Beyla 实例,它负责插桩给定主机中的所有网络流。
  • Instance Owner:在 Kubernetes 中,大多数实例 (Pod) 都有一个所有者资源。有时您可能更喜欢报告有关所有者而非实例的数据,以控制基数。实例所有者的示例包括 Deployments、DaemonSets、ReplicaSets 和 StatefulSets,但如果 Pod 没有所有者(独立 Pod),则 Pod 本身被报告为所有者。
  • URL Path:是 URL 请求的原始路径,由客户端发送并由服务器接收,例如:/clients/348579843/command/833
  • URL Route:是 URL 请求的聚合路径,进行语义分组以控制基数。它通常模仿某些 Web 框架允许您在代码中定义 HTTP 请求的方式,例如:/clients/{clientId}/command/{command_num}
  • Operation:描述了请求的功能
    • HTTP:所有 HTTP 动词,例如 GET,后跟 URL 路由
    • gRPC:服务的路径
    • SQL:SQL 命令,例如 SELECTUPDATE 或其他命令,后跟目标表
    • Kafka:Produce/Fetch
  • Server:是接收和处理 HTTP 或 gRPC 请求的任何实例。服务器也可以是客户端。
  • Client:是提交 HTTP、gRPC、数据库或 MQ 请求的任何实例。客户端也可以是服务器。
  • Service:在 Kubernetes 上下文中,是由一组服务器提供的功能,通过公共主机名和端口进行访问。
  • Endpoint:是标识服务、服务器或客户端的 IP 或主机名和端口。
  • Return code:由每次服务调用返回,描述了一些关于执行的元信息。对于 HTTP,它们是 HTTP 状态码,对于其他协议,通常是 0(成功)或 1(错误)。

进程级别指标

进程级别指标是最容易计算的指标,因为进程之间没有连接,并且进程实例属于唯一的应用程序实例。

基数,根据 Beyla 中默认启用的属性集

#Instances * #Metrics * #AttributeValues
  • Instances 是被插桩进程的数量
  • Metrics 是每个进程报告的指标数量,而 AttributeValues 是需要乘以每个指标实例的一些实例级属性
    • process.cpu.utilization
      • cpu.mode={用户, 系统, 等待}
    • Process.cpu.time
      • cpu.mode={用户, 系统, 等待}
    • Process.memory.usage
    • Process.memory.virtual
    • process.disk.io
      • disk.io.direction={读取, 写入}
    • process.network.io
      • network.io.direction={接收, 发送}

总而言之,计算进程基数的公式为

#ProcessInstances * 12

其中 12 是上面列举的所有 #Metrics * #AttributeValues 的总数。

应用程序级别指标

对于应用程序级别指标,我们不能像进程级别指标那样遵循简单的乘法公式,因为有多个因素影响基数,并且它们之间不是线性关系。

例如,HTTP 路由的数量和服务器地址都会增加基数,但我们不能简单地将它们相乘,因为并非所有服务器实例都接受相同的 HTTP 路由。

下面的公式可以提供一个非常粗略的最大上限,但在我们的测量中,实际基数比计算结果低了两个数量级。因此,我们建议采用以测量为主的方法,而不是事先尝试计算基数。

但是,以下是可能影响总体基数的一些因素列表

  • Instances:被插桩实体的数量。它们可以是服务,也可以是客户端。
  • MetricNames:应用程序级别指标名称的数量。这取决于 Beyla 插桩的应用程序类型。为将要报告的每个指标计数。
  • 客户端指标,当 Beyla 插桩执行对其他应用程序请求的应用程序时
    • http.client.request.duration
    • http.client.request.body.size
    • rpc.client.duration
    • sql.client.duration
    • redis.client.duration
    • messaging.publish.duration
    • messaging.process.duration
  • 服务器端指标,当 Beyla 插桩分发来自其他应用程序请求的应用程序时
    • http.server.request.duration
    • http.server.request.body.size
    • rpc.server.duration
  • HistogramBuckets 需要被计算并乘以每个指标,因为每个应用程序级别指标都是一个直方图。桶的数量可以在 Beyla 中配置,但默认数量是持续时间指标 15 个,请求体大小指标 11 个,再加上另外 2 个指标(直方图总和和计数)。
  • Operations 等同于被调用的功能。在 HTTP 服务中,它将分组 HTTP 方法和 HTTP 路由,在 RPC 中是 RPC 方法名。
  • Endpoints 是服务器地址和端口的计数。
  • ReturnCodes 是操作可能结果的数量。通常在 GRPC 中是 Ok/Err,或 HTTP 状态码。

示例计算

显示的基数公式中的操作数可能会重叠。例如,一个被插桩的客户端应用程序可能会发送 /foo/bar HTTP 请求,并连接到服务 A 和服务 B,所以

  • Operations: 2
  • Endpoints: 2

Operations * Endpoints 的商会将基数乘以 4。然而,如果 /foo 路由是服务 A 独有的,而 /bar 路由是服务 B 独有的,则实际基数乘数将仅为 2。

在计算基数时,为您的计算设置乐观和悲观界限。

以下示例说明如何计算示例系统的基数。客户端和后端都由 Beyla 插桩。其他组件是外部的

Example architecture

悲观计算结果为

#Instances * #MetricNames * #HistoBuckets * #Operations * #Endpoints * #ReturnCodes =
= 2 * 5 * 177/3 * 37/3 =2771

作为参考的数字

  • 2 个实例,客户端和后端
  • 5 种指标类型,根据它们的角色和协议
    • 客户端
      • rpc.client.duration
    • 作为 RPC 服务器的后端
      • rpc.server.duration
    • 作为 SQL 和 HTTP 客户端的后端
      • http.client.request.duration
      • http.client.request.body.size
      • sql.client.duration
  • 17 个直方图指标,因为大多数指标都是基于持续时间的
  • 7 个操作:RPC Add/List/Delete,HTTP PUT,SQL Insert/Select/Delete
  • 3 个端点:后端,身份提供者和数据库
  • 7 个返回码:RPC OK/Err,HTTP 200/401/500,SQL OK/Err

看起来基数不应超过 163。但是,这个数字既不现实也不准确,因为并非所有乘数都适用于整个系统。例如,SQL 方法不应与 RPC 和 HTTP 指标相乘。

在这个简单的场景中,我们可以手动计算最大基数,结果是 396,这远低于初始计算的 2771

#实例指标端点操作代码
1客户端rpc.client.duration后端AddOk
2客户端rpc.client.duration后端AddErr
3客户端rpc.client.duration后端ListOk
4客户端rpc.client.duration后端ListErr
5客户端rpc.client.duration后端DeleteOk
6客户端rpc.client.duration后端DeleteErr
7后端rpc.server.durationAddOk
8后端rpc.server.durationAddErr
9后端rpc.server.durationListOk
10后端rpc.server.durationListErr
11后端rpc.server.durationDeleteOk
12后端rpc.server.durationDeleteErr
13后端http.client.request.duration身份提供者PUT /login200
14后端http.client.request.duration身份提供者PUT /login401
15后端http.client.request.duration身份提供者PUT /login500
16后端http.client.request.body.size身份提供者PUT /login200
17后端http.client.request.body.size身份提供者PUT /login401
18后端http.client.request.body.size身份提供者PUT /login500
19后端sql.client.duration数据库InsertOk
20后端sql.client.duration数据库InsertErr
21后端sql.client.duration数据库SelectOk
22后端sql.client.duration数据库SelectErr
23后端sql.client.duration数据库DeleteOk
24后端sql.client.duration数据库DeleteErr

为简洁起见,我们尚未计算直方图桶。接下来我们将指标实例乘以直方图桶,再加上直方图 _count_sum

  • 3 个请求体大小指标实例 x 13 = 39
  • 21 个持续时间指标实例 x 17 = 357

总计基数:396

以上示例说明了提供一个公式来计算基数影响的难度。我们成功计算了一个非常简单的示例的精确基数,其中所有信息都是已知的。在大型 Kubernetes 集群中,我们对应用程序以及它们如何相互连接的信息很少或根本没有,这种计算将是不可能的。

网络级别指标

网络级别指标比应用程序级别指标更容易计算,因为 Beyla 只提供一个计数器:beyla.network.flow.bytes。但是,基数也取决于您的应用程序相互连接的程度。

beyla.network.flow.bytes 的默认属性是

  • 方向(请求/响应)
  • Kubernetes 中的源和目标端点所有者:k8s_src_owner_namek8s_dst_owner_namek8s_src_owner_typek8s_dst_owner_typek8s_src_namespacek8s_dst_namespace
  • k8s_cluster_name:每个集群唯一。我们假设只有一个集群,与其他指标一样。

简化的悲观计算公式为

#Directions * #SourceOwners * #DestinationOwners

我们假设所有源所有者都连接到所有目标所有者。更实际的做法是应用一个连接因子,例如一个有 100 个 Deployments/DaemonSets/StatefulSets 的集群,其中每个所有者平均连接到另外 2 个所有者,其基数将为

2 个方向 x 100 个源所有者 x 2 个目标所有者 = 400

服务图指标

服务图指标针对可以使用应用程序指标(例如 HTTP、RPC、SQL、Redis 和 Kafka)插桩的实例生成。网络指标针对任何具有网络流量的实例生成,无论其使用何种协议。

服务图指标生成以下指标

  • traces_service_graph_request_client:具有 15 个桶的直方图
  • traces_service_graph_request_server:具有 15 个桶的直方图
  • traces_service_graph_request_failed_total:计数器
  • traces_service_graph_request_total:计数器

每个指标还具有以下属性

  • source:Beyla
  • clientclient_namespace
  • serverserver_namespace

计算类似于网络指标,但基数更高

  • 我们报告的是一组指标/直方图,总基数为 36,包括两个 15+2 直方图 + 2 个计数器,而不是单个计数器指标。
  • 服务图指标通常忽略内部 Kubernetes 流量或任何来自未在应用程序级别插桩的实例的流量,而不是按实例的所有者(例如 Deployment)进行聚合。

测量结果为

  • traces_spanmetrics_latency:带有 15 + 2 个桶的直方图
  • traces_spanmetrics_calls_total:计数器
  • traces_spanmetrics_size_total:计数器
  • traces_spanmetrics_response_size_total:计数器

可能增加每个指标基数的属性有:

  • 服务/服务命名空间/实例 ID
  • Span 类型:客户端/服务端/内部
  • Span 名称:通常是操作的名称,可能具有高基数
  • 返回码

最大基数可以粗略计算为:

19 metric buckets * 3 span kinds * #Instances * #Operations * #ReturnCodes

正如前面关于应用程序指标计算的示例所示,我们假设大量的 HTTP 返回码只会影响到 HTTP 服务,或者某些实例组只包含总路由的子集。

案例研究:OpenTelemetry Demo 的基数

在本节中,我们将计算部署在由 3 个节点组成的本地集群中的 OpenTelemetry Demo 的基数。我们禁用了示例应用程序中所有捆绑的 OpenTelemetry 仪表,并部署了 Beyla 来执行仪表。

衡量进程级别指标

除非您对应用程序的内部结构有深入了解,否则很难确定正在运行的进程数。我们通过实验测量得出 OpenTelemetry demo 大约运行 140 个进程。

按照公式:

#实例 #指标 #属性值

已知所有进程指标和属性值的总和为 12,我们理论上预期进程级别指标的基数为:

141 * 12 = 1680

这与我们通过 PromQL 测量的基数值非常接近:count({__name__=~"process_.*"})~1,600

衡量应用程序级别指标

由于大多数被监控的实例既是客户端又是服务,为了更准确,我们在公式中忽略 #实例 这个参数。

#MetricNames * (#HistoBuckets+2) * #Operations * #Endpoints * #ReturnCodes

为了最小化属性对最终基数非线性影响,我们分开计算所有指标类型(HTTP、gRPC 和 Kafka)的基数。

HTTP 指标

  • 4 个指标:客户端、服务端、请求大小和时间
  • 平均 15 个直方图桶
  • 已知操作:75 个,通过运行中的 OTEL Demo 使用 PromQL 查询测量:group by (http_request_method, http_route)({__name__=~"http_.*"})
  • 26 个端点,通过运行中的 OTEL Demo 使用 PromQL 查询测量:group by (server_address, server_port)({__name__=~"http_.*"})
  • 6 种响应状态码:200、301、308、403、408 和 504,从运行中的 OTEL demo 中提取

HTTP 指标的总最大计算限制是:

4 x 15 x 75 x 26 x 6 =~ 702,000

这表明该公式对于应用程序级别指标是多么无效,因为测得的数值要低得多,即使包含了所有已知的应用程序指标类型:

count({__name__=~"http_.*|rpc_.*|sql_.*|redis_.*|messaging_.*"}) → 9,600

衡量网络级别指标

对于网络级别指标,如果我们假设 2 个方向(请求/响应)以及 21 个部署向所有 21 个部署请求信息,我们将得到以下基数:

2×21×21 = 882

如果了解架构,并且只计算架构图中的箭头并假设它们是双向的,我们可以得到一个较低的估算值:

2x29 = 58

网络指标衡量 OpenTelemetry Demo 的连接、其他内部集群连接以及仪表流量,因此实际基数更高:

count(beyla_network_flow_bytes_total) → 330

我们可以通过以下查询按命名空间对流量进行分组,以便更好地了解哪些部分属于 OpenTelemetry demo:

count(beyla_network_flow_bytes_total) by (k8s_src_namespace, k8s_dst_namespace)

这将返回以下信息:

k8s_源命名空间k8s_目标命名空间计数
defaultdefault156
kube-systemdefault47
defaultkube-system47
default14
default14
kube-system13
kube-system13
gmp-system3
gmp-system3
defaultgmp-system1
gmp-systemdefault1

OpenTelemetry demo 为 demo 组件之间的流量生成的网络指标数量为 156。default 命名空间既是源也是目标。还有其他到 kube-systemgmp-system 或根本没有命名空间的流量,这些流量属于外部连接、遥测或 Kubernetes 管理。

衡量服务图指标

网络指标通常用于构建服务图,但实际的服务图指标会有不同的形态。

  • 除了单个计数器指标,我们还有 2 个计数器指标和另外 2 个带有 16+2 个桶的直方图指标。
  • 服务图指标通常忽略内部 Kubernetes 流量或任何来自未在应用程序级别插桩的实例的流量。

测量结果为

count({__name__=~".*service_graph.*"}) → 2300

测量 Span 指标

在应用程序级别指标计算中,我们演示了由于涉及的参数数量众多,尝试获得分析数字是很困难的。我们可以通过 PromQL 测量来获得基数的正确测量值

count({__name__=~".*spanmetrics.*"}) → 3900