|
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"; |
| 30 | + public static final String CF_PROPERTY_FORMAT_STRING = "cf.%s.channel.count"; |
27 | 31 | public static final String CF_CHANNEL_COUNT = "cf.channel.count"; |
28 | 32 | private static final String METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT = "Count of all ChannelFinder channels"; |
29 | 33 | private static final String METRIC_DESCRIPTION_PROPERTY_COUNT = "Count of all ChannelFinder properties"; |
30 | 34 | 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"; |
| 35 | + |
33 | 36 | private final ChannelRepository channelRepository; |
34 | 37 | private final PropertyRepository propertyRepository; |
35 | 38 | private final TagRepository tagRepository; |
36 | 39 | private final MeterRegistry meterRegistry; |
37 | 40 |
|
38 | | - MultiGauge channelCounts; |
39 | | - |
40 | 41 | @Value("${metrics.tags}") |
41 | 42 | private String[] tags; |
42 | 43 |
|
43 | | - @Value("#{${metrics.properties:{{'pvStatus', 'Active'}, {'pvStatus', 'Inactive'}}}}") |
44 | | - private String[][] properties; |
| 44 | + @Value("${metrics.properties}") |
| 45 | + private String metricProperties; |
| 46 | + |
| 47 | + Map<String, List<String>> parseProperties() { |
| 48 | + if (metricProperties == null || metricProperties.isEmpty()) { |
| 49 | + return new LinkedMultiValueMap<>(); |
| 50 | + } |
| 51 | + return Arrays.stream(metricProperties.split(";")).map(s -> |
| 52 | + { |
| 53 | + String[] split = s.split(":"); |
| 54 | + String k = split[0].trim(); |
| 55 | + List<String> v = Arrays.stream(split[1].split(",")).map(String::trim).toList(); |
| 56 | + return Map.entry(k, v); |
| 57 | + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
| 58 | + } |
45 | 59 |
|
46 | 60 | @Autowired |
47 | 61 | public MetricsService( |
48 | | - final ChannelRepository channelRepository, |
49 | | - final PropertyRepository propertyRepository, |
50 | | - final TagRepository tagRepository, |
51 | | - final MeterRegistry meterRegistry) { |
| 62 | + final ChannelRepository channelRepository, |
| 63 | + final PropertyRepository propertyRepository, |
| 64 | + final TagRepository tagRepository, |
| 65 | + final MeterRegistry meterRegistry) { |
52 | 66 | this.channelRepository = channelRepository; |
53 | 67 | this.propertyRepository = propertyRepository; |
54 | 68 | this.tagRepository = tagRepository; |
55 | 69 | this.meterRegistry = meterRegistry; |
56 | | - registerGaugeMetrics(); |
57 | 70 | } |
58 | 71 |
|
| 72 | + @PostConstruct |
59 | 73 | private void registerGaugeMetrics() { |
60 | 74 | Gauge.builder(CF_TOTAL_CHANNEL_COUNT, () -> channelRepository.count(new LinkedMultiValueMap<>())) |
61 | | - .description(METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT) |
62 | | - .register(meterRegistry); |
| 75 | + .description(METRIC_DESCRIPTION_TOTAL_CHANNEL_COUNT) |
| 76 | + .register(meterRegistry); |
63 | 77 | Gauge.builder(CF_PROPERTY_COUNT, propertyRepository::count) |
64 | | - .description(METRIC_DESCRIPTION_PROPERTY_COUNT) |
65 | | - .register(meterRegistry); |
| 78 | + .description(METRIC_DESCRIPTION_PROPERTY_COUNT) |
| 79 | + .register(meterRegistry); |
66 | 80 | 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); |
| 81 | + .description(METRIC_DESCRIPTION_TAG_COUNT) |
| 82 | + .register(meterRegistry); |
| 83 | + registerTagMetrics(); |
| 84 | + registerPropertyMetrics(); |
73 | 85 | } |
74 | 86 |
|
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<>(); |
| 87 | + private void registerTagMetrics() { |
81 | 88 |
|
82 | 89 | // 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); |
| 90 | + for (String tag : tags) { |
| 91 | + Gauge.builder(CF_CHANNEL_COUNT, () -> channelRepository.countByTag(tag)) |
| 92 | + .description("Number of channels with tag") |
| 93 | + .tag("tag", tag) |
| 94 | + .baseUnit("channels") |
| 95 | + .register(meterRegistry); |
89 | 96 | } |
| 97 | + } |
90 | 98 |
|
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 | | - } |
| 99 | + private void registerPropertyMetrics() { |
| 100 | + Map<String, List<String>> properties = parseProperties(); |
99 | 101 |
|
100 | | - channelCounts.register(rows, true); |
| 102 | + properties.forEach((propertyName, propertyValues) -> propertyValues.forEach(propertyValue -> |
| 103 | + Gauge.builder(String.format(CF_PROPERTY_FORMAT_STRING, propertyName), () -> channelRepository.countByProperty(propertyName, propertyValue)) |
| 104 | + .description(String.format("Number of channels with property '%s'", propertyName)) |
| 105 | + .tag(propertyName, propertyValue) |
| 106 | + .baseUnit("channels") |
| 107 | + .register(meterRegistry)) |
| 108 | + ); |
101 | 109 | } |
102 | 110 | } |
0 commit comments