Metrics.java 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package com.provectus.kafka.ui.model;
  2. import static io.prometheus.client.Collector.MetricFamilySamples;
  3. import static java.util.stream.Collectors.toMap;
  4. import com.google.common.collect.Streams;
  5. import com.provectus.kafka.ui.service.metrics.scrape.inferred.InferredMetrics;
  6. import groovy.lang.Tuple;
  7. import java.math.BigDecimal;
  8. import java.util.Collection;
  9. import java.util.LinkedHashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Optional;
  13. import java.util.stream.Stream;
  14. import lombok.Builder;
  15. import lombok.Value;
  16. @Builder
  17. @Value
  18. public class Metrics {
  19. IoRates ioRates;
  20. InferredMetrics inferredMetrics;
  21. Map<Integer, List<MetricFamilySamples>> perBrokerScrapedMetrics;
  22. public static Metrics empty() {
  23. return Metrics.builder()
  24. .ioRates(IoRates.empty())
  25. .perBrokerScrapedMetrics(Map.of())
  26. .inferredMetrics(InferredMetrics.empty())
  27. .build();
  28. }
  29. @Builder
  30. public record IoRates(Map<Integer, BigDecimal> brokerBytesInPerSec,
  31. Map<Integer, BigDecimal> brokerBytesOutPerSec,
  32. Map<String, BigDecimal> topicBytesInPerSec,
  33. Map<String, BigDecimal> topicBytesOutPerSec) {
  34. static IoRates empty() {
  35. return IoRates.builder()
  36. .brokerBytesOutPerSec(Map.of())
  37. .brokerBytesInPerSec(Map.of())
  38. .topicBytesOutPerSec(Map.of())
  39. .topicBytesInPerSec(Map.of())
  40. .build();
  41. }
  42. }
  43. public Stream<MetricFamilySamples> getSummarizedMetrics() {
  44. return Streams.concat(
  45. inferredMetrics.asStream(),
  46. perBrokerScrapedMetrics
  47. .values()
  48. .stream()
  49. .flatMap(Collection::stream)
  50. .collect(toMap(mfs -> mfs.name, Optional::of, Metrics::summarizeMfs, LinkedHashMap::new))
  51. .values()
  52. .stream()
  53. .filter(Optional::isPresent)
  54. .map(Optional::get)
  55. );
  56. }
  57. //returns Optional.empty if merging not supported for metric type
  58. private static Optional<MetricFamilySamples> summarizeMfs(Optional<MetricFamilySamples> mfs1opt,
  59. Optional<MetricFamilySamples> mfs2opt) {
  60. if ((mfs1opt.isEmpty() || mfs2opt.isEmpty()) || (mfs1opt.get().type != mfs2opt.get().type)) {
  61. return Optional.empty();
  62. }
  63. var mfs1 = mfs1opt.get();
  64. return switch (mfs1.type) {
  65. case GAUGE, COUNTER -> Optional.of(
  66. new MetricFamilySamples(
  67. mfs1.name,
  68. mfs1.type,
  69. mfs1.help,
  70. Stream.concat(mfs1.samples.stream(), mfs2opt.get().samples.stream())
  71. .collect(
  72. toMap(
  73. // merging samples with same labels
  74. s -> Tuple.tuple(s.name, s.labelNames, s.labelValues),
  75. s -> s,
  76. (s1, s2) -> new MetricFamilySamples.Sample(
  77. s1.name,
  78. s1.labelNames,
  79. s1.labelValues,
  80. s1.value + s2.value
  81. ),
  82. LinkedHashMap::new
  83. )
  84. )
  85. .values()
  86. .stream()
  87. .toList()
  88. )
  89. );
  90. default -> Optional.empty();
  91. };
  92. }
  93. }