[spring-projects/spring-boot]支持基于属性的 MeterFilters

2024-04-29 496 views

回答

6

为了帮助您更好地想象使用过滤器来控制分布统计数据的用例,请考虑在低级核心库中检测的计时器(例如 HikariCP 和 Rabbit 中现在存在的检测)。这些作者无法就其库的用户查看某些摘要统计信息(例如客户端百分位数)是否有用做出通用决策。例如:

  1. Billy 使用的是 InfluxDB,它没有足够丰富的查询语言来计算直方图的可聚合百分位数。 Billy 可能会选择发送 Micrometer 计算的 P95,因为他知道它的用处仅限于基础指标的标签基数。例如,如果计时器标记为“主机”和“结果”,并且他的组织仅运行 10 个服务实例,其中有 2 个可能的结果,那么他可以通过简单地独立绘制所有单独的时间序列来合理地绘制不可聚合的 P95,并且监控异常值。

  2. Sue 使用的是 Prometheus,并且从不想发送 Micrometer 计算的百分位数,因为她可以访问histogram_quantile,因此她的图的有用性不需要受到标签基数的限制。她选择运送直方图桶。

  3. Jane 使用的是 Wavefront,根本不关心百分位分布。她很乐意监控分布平均值(一般情况下不比 P50 更好或更差的中心性度量)和最大值之间的范围。 Wavefront 发布了一篇有关其新的可聚合百分位数功能的博客,Jane 通过附加属性获得了关键延迟指标上的 P99。

  4. 组织已采用“检测所有事物”的方法,但担心其本地 Prometheus 集群的可扩展性。如果他们的 Prometheus 集群受到压力,他们希望能够删除一些不太关键的延迟指标的摘要统计数据,并可能禁用整个其他指标。他们希望以属性驱动的方式实现这两个目标,这样他们就可以通过结合 Archaius/Config Server 等方式来减轻整个堆栈中监控系统的压力。

如果不向我们每个假想用户发送浪费的额外时间序列,Rabbit 客户端作者就无法满足所有这些需求。我们对库作者的建议始终只是使用普通计时器,让应用程序开发人员在最后一刻通过过滤器决定他们想要哪些汇总统计数据。

7

@jkschneider 它是否必须基于财产?应用程序开发人员可能会根据使用 DSL 等可用的内容来制作他们想要的统计数据?选项的数量很密集,而且我们必须重组命名空间这一事实是否表明 DSL 可能更适合?

3

理想情况下,它是基于财产的,是的。我们希望人们能够利用配置服务器来动态影响长期某些指标的启用/保真度。

8

我们必须重组命名空间这一事实是否表明 DSL 可能更适合?

也许这只是原始结构设计不佳的一个迹象。毕竟,这是我想出来的;)

2

@jkschneider我一直在思考这个问题,我想知道我们所做的事情是否OAuth2ClientProperties可行?如果我们将属性分成两部分怎么办?命名定义然后引用它?

就像是

metrics.config.light.percentiles=1,2,3
metrics.config.light.somethingelse=forsure

metrics.config.heavy.percentiles=10,20,30
metrics.config.light.somethingelse=noway

metrics.apply.net.foo.bar=light
metrics.apply.net.foo.baz=light
metrics.apply.net.foo=heavy

额外的间接层有用吗?

我们甚至可以为常见场景提供内置配置。

8

@philwebb 哦有趣。这看起来很有用。

2

@philwebb 我非常喜欢这个。但请记住,选项的数量“各不相同”(因此您没有像提供者情况那样的单个 Pojo,如果我理解正确的话,这取决于您的指标类型)。

因此,对配置的引用可能有点脆弱,因为您可以将任何指标链接到任何配置类型,包括那些不合法的配置类型。这也是我的 DSL 想法的基本原理。

3

两部分配置有助于更复杂的百分位设置,但最好不必这样做只是为了启用/禁用指标

4

@checketts 启用可以是与该apply事物分开的设置。

management.metrics.enable.net.foo.bar=false
0

选项数量“变化”

对于某些属性,如mimiumExpectedValuesla根据仪表的基本单位确定尺寸,配置将仅具有两种变体:表示时间单位的和不表示时间单位的。

我们特别对待时间,因为对于时间的基本单位应该是什么有很多不同的期望(由于“真正的”时间基本单位,秒,对于我们所测量的东西来说是一个如此粗糙的单位)。

5

@checketts

两部分配置有助于更复杂的百分位设置,但最好不必这样做只是为了启用/禁用指标

我想知道我们是否可以将“禁用”作为内置配置。这样你就可以这样做:

management.metrics.filter.net.foo.bar=disable
1

你好,我想在这里提到我们的用例,看看这个问题是否会涵盖它。

我们目前使用 3 米注册表、JMX(通过 Spring Boot Admin 访问)、Prometheus(用于 Grafana 仪表板)和 CloudWatch(主要用于警报)

为了降低成本并专注于最关键的警报(例如 500 个状态代码),我们仅将大量仪表过滤器应用于 CloudWatch 注册表。这些包括:

  • 使用 MeterFilter.replaceTagValues 聚合 4xx 和 5xx 状态代码。
  • 使用 MeterFilter.ignoreTags 忽略标签(例如 http 指标中的“异常”)
  • 使用 MeterFilter.deny 拒绝除了基于属性的白名单中的指标之外的指标:即我们只允许某些指标名称(例如 http.server.requests)和某些标记值(即我们的业务 uri 而不是执行器的) 事实上,这是基于属性允许各个服务在需要时导出特定的自定义指标。
  • 使用 MeterFilter.maximumAllowableMetrics 作为基于属性的上限

(我们还在 CloudWatchMeterRegistry 上设置了一个通用标签,即应用程序名称 - 我们在 Prometheus 或 JMX 上不需要这个)

目前,我们在共享库中实现了这一点,并使用一些 Spring Boot 自动配置来创建和配置 CloudWatch 计量注册表。我们将其作为所有服务的依赖项,尽管理想情况下我们只依赖标准的 CloudWatch 自动配置并使用 Spring Cloud 配置服务器的属性来配置计量过滤器。

这里提出的内容是否能满足我们的大部分(如果不是全部)需求?

7

@djgeary 我所看到的是,通过属性为单个注册表设置属性值的复杂性一度成为其自己的 DSL。例如,我尝试了配置replaceTagValues,但想让它依赖于仪表名称。我想出了类似的东西...filters.meter.name.combine: tag1|allowedValue1,defaultNonMatchingValue;tag2|otherAllowedValue (etc),所有的横杠、分号、逗号垃圾对于我的用例来说都是如此特定,以至于在上游发布没有意义。

从我到目前为止所遵循的情况来看,默认配置适用于所有注册表,并且仅支持配置摘要(百分位数/直方图)和排除仪表。

4

@checketts是的,我意识到可能无法通过属性来完成所有这些工作,并且它很容易变得非常特定于用例。我只是想添加我们正在做的事情,以防它对这里的设计有用。具体来说,我们仅在 CompositeMeterRegistry 设置中的一个 MeterRegistry 上进行过滤,以及我们如何以及为何进行过滤的示例。我同意 ReplaceTagValues 功能可能最适合在代码中执行(尽管我们所做的是直接从示例复制,因此可能它很常见并且可以是内置选项?),但是我们的“白名单”机制可能可以完成在属性中 - 我们当前的实现在 yml 中如下所示:

management:
  metrics.export.cloudwatch:
    namespace: microservice-testing     
    enabled: true
    whitelist:
      - name: http.server.requests
        tags: 
          uri: /lookup,/actions
      - name: custom1
      - name: custom2
7

我们将尝试将其范围缩小到仅enablementpercentilespercentilesHistogramSLA

9

哇!感谢@philwebb 的繁重工作