【问题标题】:Micrometer - Prometheus: Some meters are showing, others are not千分尺 - 普罗米修斯:有些仪表显示,有些不显示
【发布时间】:2022-01-21 07:47:26
【问题描述】:

我有一个 rabbitmq 消息队列,许多其他服务在该消息队列上报告称为 Point 的状态更新。现在,在一个单独的服务(使用 SpringBoot 编写)上,我需要监听那些 Point 更新并将其转换为 Prometheus 可抓取的端点。

所以我的计划是将传入的Point对象转换为Meters,并在MeterRegistry中注册。这有效,但仅适用于某些要点。我还没有弄清楚,哪些确切可见,哪些不可见,因为看起来这取决于它们在重新启动服务后进入的顺序。我想不出任何有助于故障排除的模式。

根据我阅读千分尺文档的理解,Meter 被创建一次,我们给它一个对象和一个函数,允许它从该对象中检索双精度值作为指标。因为,我每隔几秒就会有新的Point 实例出现,所以该值不会随着Meter 引用旧的Point 而更新。

假设这是正确的,我在PointPointWrapper)周围添加了一个小包装器,我自己将其传递给MeterPointWrapper 的缓存实例。现在当一个新的Point 进来时,我检查我是否已经有一个PointWrapper 用于那个Point,如果是,我用新的替换包装器中的Point 实例。

@Service
public class PointSubscriber {
    
    private final MetricsService metrics;

    public PointSubscriber(@Autowired MetricsService metrics) {
        this.metrics = metrics;
    }

    @Bean
    public Consumer<PointUpdate> processPoint() {
        return (update) -> {
            metrics.update(update.getPoint());
        };
    }

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MetricsService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private final MeterRegistry meterRegistry;

    private Map<String, PointWrapper> cache = new HashMap<>();

    public void update(Point point) {

        // Check if wrapper already in cache
        String pointId = point.getId();
        PointWrapper cached = cache.get(pointId);
        
        // Replace the point in the wrapper to update the value
        if (cached != null) {
            logger.debug("Updating value for {}", point.getId());
            cached.setPoint(point);
            
        // Create the wrapper, cache it and register Meter
        } else {
            PointWrapper pointMeter = PointWrapper.from(point.getId(), point);
            // Don't register Meters that will return null
            if (pointMeter.getMetricValue() == null) {
                logger.debug("Not going to register point with null value: {}", point.getId());
                return;
            }
            logger.debug("Registering point {}", point.getId());
            register(pointMeter, meterRegistry);
            cache.put(pointId, pointMeter);
        }
    }
    
    public Meter register(PointWrapper pointMeter, MeterRegistry registry) {
        Set<Tag> tags = new HashSet<>();
        tags.add(Tag.of("pointId", pointMeter.getPoint().getId()));
        tags.addAll(pointMeter.getPoint().getLabels().entrySet().stream()
            .map (e -> Tag.of(e.getKey(),e.getValue()))
            .collect(Collectors.toSet()));
        
        return Gauge.builder(pointMeter.getMetricName(), pointMeter, PointWrapper::getMetricValue)
            .tags(tags)
            .register(registry);
    }
    
}
@Data
@Builder
public class PointWrapper {
    
    public static PointWrapper from(String id, Point point) {       
        return PointWrapper.builder()
            .id(id)
            .metricName("symphony_point")
            .point(point)
            .build();
    }
        
    private String id;
    
    private String metricName;
     
    @EqualsAndHashCode.Exclude
    private Point point; 
    
    public Double getMetricValue() {
        if (point == null)
            return null;
        if (point instanceof QuantityPoint) {
            return ((QuantityPoint) point).getValue();
        } else if (point instanceof StatePoint<?>) {
            StatePoint<?> s = (StatePoint<?>) point;
            if (s.getState() == null)
                return null;
            return Double.valueOf(s.getState().asNumber());
        }
        return null;
    }
        
}

正如我所提到的,这会导致 prometheus 端点中丢失大量数据点。我读到Meters 由他们的nametags 唯一标识。该名称始终为symphony_point,但我将Point 的ID 添加为tag,称为pointId。正因为如此,每个Meter.Id 都是独一无二的。

我可以看到类似的日志

Registering point outdoor_brightness_north

但 Prometheus 端点中缺少该点。

有什么想法吗?

更新 @checketts 指出具有相同名称的指标必须具有相同的标签集。我快速检查可以确认,我使用的数据不是这样:

symphony.point area pointId device property floor room
symphony.point area pointId device property floor room
symphony.point area pointId property room floor device
symphony.point area pointId property room floor device
symphony.point area room pointId device property floor
symphony.point pointId area room device property floor
symphony.point area room pointId device property floor
symphony.point area room property pointId floor device
symphony.point pointId area property device
symphony.point area device property pointId
symphony.point area room pointId floor device property
symphony.point area pointId device property floor room
symphony.point area pointId device property room floor
symphony.point area pointId property floor device room
symphony.point area room property pointId floor device
symphony.point area property room floor pointId device
symphony.point pointId area room property floor device
symphony.point area device pointId property
symphony.point area device property pointId floor room
symphony.point area pointId room device property floor
symphony.point area pointId room device property floor
symphony.point area room pointId device property floor
symphony.point area pointId room floor device property
symphony.point pointId area device property
symphony.point area property room floor device pointId
symphony.point area pointId device room property floor
symphony.point area room device property floor pointId
symphony.point area device pointId property floor room
symphony.point area pointId property floor device room
symphony.point pointId area device property
symphony.point area pointId device property floor room
symphony.point area pointId property room floor device
symphony.point area pointId room device property floor
symphony.point pointId property area device
symphony.point area property pointId floor device room
symphony.point area room property pointId floor device
symphony.point area room pointId property floor device
symphony.point area pointId floor device property room
symphony.point area room device pointId property floor
symphony.point pointId property area device
symphony.point area room device property pointId floor
symphony.point area device property floor pointId room
symphony.point area room pointId floor device property
symphony.point area pointId property room floor device
symphony.point area room device property floor pointId
symphony.point area room device pointId property floor
symphony.point pointId area device property
symphony.point area property floor pointId device room
symphony.point area pointId device property floor room
symphony.point area property pointId device
symphony.point pointId area property floor device room
symphony.point area pointId floor device property room
symphony.point area property pointId floor device room
symphony.point area room pointId floor device property
symphony.point pointId area device property
symphony.point area room pointId property floor device
symphony.point area room pointId floor device property
symphony.point area room device property pointId floor
symphony.point area pointId room property floor device
symphony.point area room device property floor pointId
symphony.point area pointId property room floor device
symphony.point pointId area property device
symphony.point area pointId device property floor room
symphony.point area device pointId property floor room
symphony.point area room pointId property floor device
symphony.point area pointId device property floor room
symphony.point area pointId device room property floor
symphony.point area room pointId device property floor
symphony.point area property room pointId floor device
symphony.point pointId area device property

这是一个大问题,因为来自 Points 的标签(这就是我构建 Tags 的来源)没有明确定义。我仍然需要能够根据它们进行查询。我可以将它们全部添加到名称中,但随后“显示所有室内温度”之类的查询变得非常不愉快。

无论如何,我会尝试验证这是我问题的根本原因。

【问题讨论】:

  • 所有点都有相同的标签吗?使用 Prometheus,所有具有相同名称的仪表都需要具有相同的标签名称(又名标签)
  • 确实解决了问题,谢谢!您可能想创建一个正确的答案,以便我可以将其标记为解决方案

标签: micrometer spring-micrometer


【解决方案1】:

这行很可疑:

tags.addAll(pointMeter.getPoint().getLabels().entrySet().stream()
            .map (e -> Tag.of(e.getKey(),e.getValue()))
            .collect(Collectors.toSet()));

所有点都有相同的标签吗?使用 Prometheus,所有具有相同名称的仪表都需要具有相同的标签名称(也称为标签)。带有标签名称的第一个点将成为默认值,所有其他点将被拒绝。

【讨论】:

    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2019-07-10
    • 2021-11-19
    • 2018-10-30
    • 1970-01-01
    相关资源
    最近更新 更多