|
11 | 11 | import org.springframework.stereotype.Service; |
12 | 12 | import org.springframework.util.LinkedMultiValueMap; |
13 | 13 |
|
| 14 | +import javax.annotation.PostConstruct; |
14 | 15 | import java.util.ArrayList; |
15 | 16 | import java.util.Arrays; |
| 17 | +import java.util.List; |
| 18 | +import java.util.Map; |
16 | 19 | import java.util.logging.Level; |
17 | 20 | import java.util.logging.Logger; |
| 21 | +import java.util.stream.Collectors; |
18 | 22 |
|
19 | 23 | @Service |
20 | 24 | @PropertySource(value = "classpath:application.properties") |
21 | 25 | public class MetricsService { |
22 | 26 |
|
23 | | - private static final Logger logger = Logger.getLogger(MetricsService.class.getName()); |
24 | 27 | public static final String CF_TOTAL_CHANNEL_COUNT = "cf.total.channel.count"; |
25 | 28 | public static final String CF_PROPERTY_COUNT = "cf.property.count"; |
26 | 29 | public static final String CF_TAG_COUNT = "cf.tag.count"; |
27 | 30 | public static final String CF_CHANNEL_COUNT = "cf.channel.count"; |
28 | 31 | private static final String METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT = "Count of all ChannelFinder channels"; |
29 | 32 | private static final String METRIC_DESCRIPTION_PROPERTY_COUNT = "Count of all ChannelFinder properties"; |
30 | 33 | private static final String METRIC_DESCRIPTION_TAG_COUNT = "Count of all ChannelFinder tags"; |
31 | | - private static final String METRIC_DESCRIPTION_CHANNEL_COUNT = |
32 | | - "Count of channels with specific property with and specific value"; |
| 34 | + |
33 | 35 | private final ChannelRepository channelRepository; |
34 | 36 | private final PropertyRepository propertyRepository; |
35 | 37 | private final TagRepository tagRepository; |
36 | 38 | private final MeterRegistry meterRegistry; |
37 | 39 |
|
38 | | - MultiGauge channelCounts; |
39 | | - |
40 | 40 | @Value("${metrics.tags}") |
41 | 41 | private String[] tags; |
42 | 42 |
|
43 | | - @Value("#{${metrics.properties:{{'pvStatus', 'Active'}, {'pvStatus', 'Inactive'}}}}") |
44 | | - private String[][] properties; |
| 43 | + @Value("${metrics.properties}") |
| 44 | + private String metricProperties; |
| 45 | + |
| 46 | + Map<String, List<String>> parseProperties() { |
| 47 | + if (metricProperties == null || metricProperties.isEmpty()) { |
| 48 | + return new LinkedMultiValueMap<>(); |
| 49 | + } |
| 50 | + return Arrays.stream(metricProperties.split(";")).map(s -> |
| 51 | + { |
| 52 | + String[] split = s.split(":"); |
| 53 | + String k = split[0].trim(); |
| 54 | + List<String> v = Arrays.stream(split[1].split(",")).map(String::trim).toList(); |
| 55 | + return Map.entry(k, v); |
| 56 | + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
| 57 | + } |
45 | 58 |
|
46 | 59 | @Autowired |
47 | 60 | public MetricsService( |
48 | | - final ChannelRepository channelRepository, |
49 | | - final PropertyRepository propertyRepository, |
50 | | - final TagRepository tagRepository, |
51 | | - final MeterRegistry meterRegistry) { |
| 61 | + final ChannelRepository channelRepository, |
| 62 | + final PropertyRepository propertyRepository, |
| 63 | + final TagRepository tagRepository, |
| 64 | + final MeterRegistry meterRegistry) { |
52 | 65 | this.channelRepository = channelRepository; |
53 | 66 | this.propertyRepository = propertyRepository; |
54 | 67 | this.tagRepository = tagRepository; |
55 | 68 | this.meterRegistry = meterRegistry; |
56 | | - registerGaugeMetrics(); |
57 | 69 | } |
58 | 70 |
|
| 71 | + @PostConstruct |
59 | 72 | private void registerGaugeMetrics() { |
60 | 73 | Gauge.builder(CF_TOTAL_CHANNEL_COUNT, () -> channelRepository.count(new LinkedMultiValueMap<>())) |
61 | | - .description(METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT) |
62 | | - .register(meterRegistry); |
| 74 | + .description(METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT) |
| 75 | + .register(meterRegistry); |
63 | 76 | Gauge.builder(CF_PROPERTY_COUNT, propertyRepository::count) |
64 | | - .description(METRIC_DESCRIPTION_PROPERTY_COUNT) |
65 | | - .register(meterRegistry); |
| 77 | + .description(METRIC_DESCRIPTION_PROPERTY_COUNT) |
| 78 | + .register(meterRegistry); |
66 | 79 | Gauge.builder(CF_TAG_COUNT, tagRepository::count) |
67 | | - .description(METRIC_DESCRIPTION_TAG_COUNT) |
68 | | - .register(meterRegistry); |
69 | | - channelCounts = MultiGauge.builder(CF_CHANNEL_COUNT) |
70 | | - .description(METRIC_DESCRIPTION_CHANNEL_COUNT) |
71 | | - .baseUnit("channels") |
72 | | - .register(meterRegistry); |
| 80 | + .description(METRIC_DESCRIPTION_TAG_COUNT) |
| 81 | + .register(meterRegistry); |
| 82 | + registerTagMetrics(); |
| 83 | + registerPropertyMetrics(); |
73 | 84 | } |
74 | 85 |
|
75 | | - @Scheduled(fixedRate = 5000) |
76 | | - public void updateMetrics() { |
77 | | - logger.log( |
78 | | - Level.FINER, |
79 | | - () -> "Updating metrics for properties " + Arrays.deepToString(properties) + " and tags " + Arrays.toString(tags)); |
80 | | - ArrayList<MultiGauge.Row<?>> rows = new ArrayList<>(); |
| 86 | + private void registerTagMetrics() { |
81 | 87 |
|
82 | 88 | // Add tags |
83 | | - for (String tag: tags) { |
84 | | - long count = channelRepository.countByTag(tag); |
85 | | - rows.add(MultiGauge.Row.of(Tags.of("tag", tag), count )); |
86 | | - logger.log( |
87 | | - Level.FINER, |
88 | | - () -> "Updating metrics for tag " + tag + " to " + count); |
| 89 | + for (String tag : tags) { |
| 90 | + Gauge.builder(CF_CHANNEL_COUNT, () -> channelRepository.countByTag(tag)) |
| 91 | + .description("Number of channels with tag") |
| 92 | + .tag("tag", tag) |
| 93 | + .baseUnit("channels") |
| 94 | + .register(meterRegistry); |
89 | 95 | } |
| 96 | + } |
90 | 97 |
|
91 | | - // Add properties |
92 | | - for (String[] propertyValue: properties) { |
93 | | - long count = channelRepository.countByProperty(propertyValue[0], propertyValue[1]); |
94 | | - rows.add(MultiGauge.Row.of(Tags.of(propertyValue[0], propertyValue[1]), count)); |
95 | | - logger.log( |
96 | | - Level.FINER, |
97 | | - () -> "Updating metrics for property " + propertyValue[0] + ":" + propertyValue[1] + " to " + count); |
98 | | - } |
| 98 | + private void registerPropertyMetrics() { |
| 99 | + Map<String, List<String>> properties = parseProperties(); |
99 | 100 |
|
100 | | - channelCounts.register(rows, true); |
| 101 | + properties.forEach((propertyName, propertyValues) -> propertyValues.forEach(propertyValue -> |
| 102 | + Gauge.builder(CF_CHANNEL_COUNT + "." + propertyName, () -> channelRepository.countByProperty(propertyName, propertyValue)) |
| 103 | + .description(String.format("Number of channels with property '%s'", propertyName)) |
| 104 | + .tag(propertyName, propertyValue) |
| 105 | + .baseUnit("channels") |
| 106 | + .register(meterRegistry)) |
| 107 | + ); |
101 | 108 | } |
102 | 109 | } |
0 commit comments