├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── itelg
│ └── spring
│ └── actuator
│ └── rabbitmq
│ ├── QueueCheck.java
│ ├── RabbitQueueProperties.java
│ ├── RabbitQueuePropertiesManager.java
│ ├── health
│ └── RabbitQueueCheckHealthIndicator.java
│ └── metric
│ ├── RabbitQueueMetrics.java
│ └── configuration
│ ├── EnableRabbitMetrics.java
│ └── RabbitMetricConfiguration.java
└── test
└── java
└── com
└── itelg
└── spring
└── actuator
└── rabbitmq
├── QueueCheckTest.java
├── RabbitQueuePropertiesManagerTest.java
├── RabbitQueuePropertiesTest.java
├── health
└── RabbitQueueCheckHealthIndicatorTest.java
├── metric
├── RabbitQueueMetricsTest.java
└── configuration
│ └── RabbitMetricConfigurationTest.java
└── util
└── QueueUtil.java
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.settings/
3 | /.classpath
4 | /.project
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 |
3 | services:
4 | - docker
5 |
6 | language: java
7 |
8 | jdk:
9 | - oraclejdk8
10 | - oraclejdk11
11 |
12 | cache:
13 | directories:
14 | - $HOME/.m2
15 |
16 | install: mvn verify -Dgpg.skip=true
17 |
18 | before_install:
19 | - wget -O ~/codacy-coverage-reporter-assembly.jar https://github.com/codacy/codacy-coverage-reporter/releases/download/4.0.5/codacy-coverage-reporter-4.0.5-assembly.jar
20 |
21 | after_success:
22 | - java -jar ~/codacy-coverage-reporter-assembly.jar report -l Java -r target/site/jacoco/jacoco.xml
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Julian Eggers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | spring-rabbitmq-actuator
2 | ========================
3 |
4 | [](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.itelg.spring%22%20AND%20a%3A%22spring-rabbitmq-actuator%22)
5 | [](https://www.codacy.com/app/eggers-julian/spring-rabbitmq-actuator)
6 | [](https://www.codacy.com/app/eggers-julian/spring-rabbitmq-actuator)
7 | [](https://travis-ci.org/julian-eggers/spring-rabbitmq-actuator)
8 |
9 | SpringBoot RabbitMQ Actuator (Queue Metrics & Health-Checks)
10 |
11 | #### Maven
12 | ```xml
13 |
14 | com.itelg.spring
15 | spring-rabbitmq-actuator
16 | 0.6.0-RC2
17 |
18 | ```
19 |
20 | #### Precondition ([Example](https://github.com/julian-eggers/spring-rabbitmq-dead-letter-queue-example/blob/master/src/main/java/com/itelg/spring/rabbitmq/example/configuration/RabbitConfiguration.java#L76))
21 | You have to add the declaring RabbitAdmin to each queue.
22 | The specific RabbitAdmin is required to fetch the queue-information.
23 | ```java
24 | @Bean
25 | public Queue exampleQueue()
26 | {
27 | Queue queue = new Queue("com.itelg.spring.rabbitmq.test");
28 | queue.setAdminsThatShouldDeclare(rabbitAdmin());
29 | return queue;
30 | }
31 | ```
32 |
33 |
34 | ## Health-Checks
35 |
36 | #### Example
37 | ```java
38 | @Bean
39 | public HealthIndicator rabbitQueueCheckHealthIndicator()
40 | {
41 | RabbitQueueCheckHealthIndicator healthIndicator = new RabbitQueueCheckHealthIndicator();
42 | healthIndicator.addQueueCheck(exampleQueue1, 10000, 1);
43 | healthIndicator.addQueueCheck(exampleQueue2, 50000, 3);
44 | return healthIndicator;
45 | }
46 | ```
47 |
48 | #### Response ([/actuator/health](http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#production-ready-health))
49 | ```json
50 | {
51 | "status" : "DOWN",
52 | "rabbitQueueCheck" :
53 | {
54 | "status" : "DOWN",
55 | "com.examle.exampleQueue1" :
56 | {
57 | "status" : "UP",
58 | "currentMessageCount" : 214,
59 | "maxMessageCount" : 10000,
60 | "currentConsumerCount" : 5,
61 | "minConsumerCount" : 1
62 | },
63 | "com.example.exampleQueue2" :
64 | {
65 | "status" : "DOWN",
66 | "currentMessageCount" : 67377,
67 | "maxMessageCount" : 50000,
68 | "currentConsumerCount" : 0,
69 | "minConsumerCount" : 3
70 | }
71 | }
72 | }
73 | ```
74 |
75 |
76 | ## Metrics
77 |
78 | #### Example (Autowires all queue-beans)
79 | ```java
80 | @EnableRabbitMetrics
81 | @Configuration
82 | public class RabbitMetricsConfiguration
83 | {
84 | }
85 | ```
86 |
87 | #### Response ([/actuator/metrics](http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html))
88 | ```json
89 | {
90 | "names" :
91 | [
92 | "jvm.memory.used",
93 | "process.cpu.usage",
94 | "...",
95 | "rabbitmq.queue.messages.current",
96 | "rabbitmq.queue.consumers.current",
97 | "rabbitmq.queue.messages.max",
98 | "rabbitmq.queue.consumers.min",
99 | "..."
100 | ]
101 | }
102 | ```
103 |
104 | Detailed:
105 | ```json
106 | {
107 | "name": "rabbitmq.queue.messages.current",
108 | "description": null,
109 | "baseUnit": null,
110 | "measurements": [
111 | {
112 | "statistic": "VALUE",
113 | "value": 215
114 | }
115 | ],
116 | "availableTags" : [ {
117 | "tag" : "queue",
118 | "values" : [ "dlq-example-simple-queue-dlq", "dlq-example-simple-queue" ]
119 | } ]
120 | }
121 | ```
122 |
123 | Prometheus-Example:
124 | ```
125 | # HELP rabbitmq_queue_messages_current
126 | # TYPE rabbitmq_queue_messages_current gauge
127 | rabbitmq_queue_messages_current{queue="dlq-example-simple-queue",} 0.0
128 | rabbitmq_queue_messages_current{queue="dlq-example-simple-queue-dlq",} 371.0
129 | # HELP rabbitmq_queue_consumers_current
130 | # TYPE rabbitmq_queue_consumers_current gauge
131 | rabbitmq_queue_consumers_current{queue="dlq-example-simple-queue",} 1.0
132 | rabbitmq_queue_consumers_current{queue="dlq-example-simple-queue-dlq",} 0.0
133 | ```
134 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.itelg.spring
4 | spring-rabbitmq-actuator
5 | spring-rabbitmq-actuator
6 | SpringBoot RabbitMQ actuator (Queue Metrics & Health-Checks)
7 | https://github.com/julian-eggers/spring-rabbitmq-actuator
8 | 0.6.0-RC2
9 |
10 |
11 |
12 | ${maven.build.timestamp}
13 | dd.MM.yyyy HH:mm
14 | UTF-8
15 | 1.8
16 |
17 | 0.8.2
18 | 2.0.0
19 | 4.0.2
20 |
21 | 3.8.0
22 | 3.0.1
23 | 3.0.1
24 | 1.6
25 | 2.22.1
26 | 2.22.1
27 | 3.0.0-M2
28 | 2.5.3
29 | 1.11.1
30 | 0.0.6
31 | 1.2.0
32 | 1.6.8
33 |
34 |
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-actuator
40 | 2.1.2.RELEASE
41 |
42 |
43 | org.springframework.amqp
44 | spring-rabbit
45 | 2.1.3.RELEASE
46 |
47 |
48 | io.micrometer
49 | micrometer-core
50 | 1.1.2
51 |
52 |
53 |
54 |
55 | org.slf4j
56 | slf4j-api
57 | 1.7.25
58 |
59 |
60 |
61 |
62 | org.easymock
63 | easymock
64 | ${easymock.version}
65 | test
66 |
67 |
68 | org.powermock
69 | powermock-module-junit4
70 | ${powermock.version}
71 | test
72 |
73 |
74 | org.powermock
75 | powermock-api-easymock
76 | ${powermock.version}
77 | test
78 |
79 |
80 | org.jacoco
81 | org.jacoco.agent
82 | runtime
83 | ${jacoco.version}
84 | test
85 |
86 |
87 |
88 |
89 | https://github.com/julian-eggers/spring-rabbitmq-actuator
90 | scm:git:https://github.com/julian-eggers/spring-rabbitmq-actuator.git
91 | scm:git:https://github.com/julian-eggers/spring-rabbitmq-actuator.git
92 |
93 |
94 |
95 |
96 | Julian Eggers
97 | eggers.julian@gmail.com
98 |
99 |
100 |
101 |
102 |
103 | MIT License
104 | http://www.opensource.org/licenses/mit-license.php
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | maven-compiler-plugin
113 | ${maven-compiler-plugin.version}
114 |
115 | ${java.version}
116 | ${java.version}
117 | UTF-8
118 |
119 |
120 |
121 | org.apache.maven.plugins
122 | maven-source-plugin
123 | ${maven-source-plugin.version}
124 |
125 |
126 | attach-sources
127 |
128 | jar-no-fork
129 |
130 |
131 |
132 |
133 |
134 | org.apache.maven.plugins
135 | maven-javadoc-plugin
136 | ${maven-javadoc-plugin.version}
137 |
138 |
139 | false
140 |
141 |
142 |
143 | attach-javadocs
144 |
145 | jar
146 |
147 |
148 |
149 |
150 |
151 | org.apache.maven.plugins
152 | maven-gpg-plugin
153 | ${maven-gpg-plugin.version}
154 |
155 |
156 | sign-artifacts
157 | verify
158 |
159 | sign
160 |
161 |
162 |
163 |
164 |
165 |
166 | org.apache.maven.plugins
167 | maven-surefire-plugin
168 | ${maven-surefire-plugin.version}
169 |
170 | -Duser.timezone=Europe/Berlin
171 |
172 | target/jacoco.exec
173 |
174 |
175 |
176 |
177 | org.apache.maven.plugins
178 | maven-failsafe-plugin
179 | ${maven-failsafe-plugin.version}
180 |
181 | target/surefire-reports
182 |
183 |
184 |
185 |
186 | integration-test
187 | verify
188 |
189 |
190 |
191 |
192 |
193 | org.apache.maven.plugins
194 | maven-enforcer-plugin
195 | ${maven-enforcer-plugin.version}
196 |
197 |
198 |
199 |
200 | false
201 |
202 |
203 |
204 | org.jacoco
205 | jacoco-maven-plugin
206 | ${jacoco.version}
207 |
208 |
209 | default-instrument
210 |
211 | instrument
212 |
213 |
214 |
215 | default-restore-instrumented-classes
216 |
217 | restore-instrumented-classes
218 |
219 |
220 |
221 | default-report
222 | prepare-package
223 |
224 | report
225 |
226 |
227 | target/jacoco-ut.exec
228 | target/jacoco-ut
229 |
230 |
231 |
232 | integration-test-report
233 | post-integration-test
234 |
235 | report
236 |
237 |
238 | target/jacoco-it.exec
239 | target/jacoco-it
240 |
241 |
242 |
243 | agent
244 |
245 | prepare-agent
246 |
247 |
248 |
249 | merge-results
250 | verify
251 |
252 | merge
253 |
254 |
255 |
256 |
257 | target
258 |
259 | *.exec
260 |
261 |
262 |
263 | target/jacoco.exec
264 |
265 |
266 |
267 | post-merge-report
268 | verify
269 |
270 | report
271 |
272 |
273 | target/jacoco.exec
274 | target/site/jacoco
275 |
276 |
277 |
278 |
279 |
280 |
281 | maven-release-plugin
282 | ${maven-release-plugin.version}
283 |
284 | true
285 | false
286 | release
287 | deploy
288 |
289 |
290 |
291 | org.apache.maven.scm
292 | maven-scm-provider-gitexe
293 | ${maven-scm-provider-gitexe.version}
294 |
295 |
296 |
297 |
298 | org.honton.chas
299 | exists-maven-plugin
300 | ${exists-maven-plugin.version}
301 |
302 | skip-deploy-to-central
303 | https://oss.sonatype.org/content/repositories/releases/
304 |
305 |
306 |
307 |
308 | remote
309 |
310 |
311 |
312 |
313 |
314 | de.jutzig
315 | github-release-plugin
316 | ${github-release-plugin.version}
317 |
318 |
319 | github-upload
320 | deploy
321 |
322 | release
323 |
324 |
325 | ${project.version}
326 | ${project.version}
327 | ${project.build.directory}/${project.artifactId}-${project.version}.jar
328 |
329 |
330 |
331 |
332 |
333 | org.sonatype.plugins
334 | nexus-staging-maven-plugin
335 | ${nexus-staging-maven-plugin.version}
336 | true
337 |
338 | ossrh
339 | https://oss.sonatype.org/
340 | true
341 | ${skip-deploy-to-central}
342 |
343 |
344 |
345 |
346 |
347 |
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/QueueCheck.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq;
2 |
3 | import org.springframework.amqp.core.Queue;
4 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
5 | import org.springframework.util.Assert;
6 |
7 | public class QueueCheck
8 | {
9 | private Queue queue;
10 | private RabbitAdmin rabbitAdmin;
11 | private int maxMessageCount;
12 | private int minConsumerCount;
13 |
14 | public QueueCheck(Queue queue, int maxMessageCount, int minConsumerCount)
15 | {
16 | this.queue = queue;
17 | this.maxMessageCount = maxMessageCount;
18 | this.minConsumerCount = minConsumerCount;
19 | validateRabbitAdmin(queue);
20 | }
21 |
22 | private void validateRabbitAdmin(Queue queue)
23 | {
24 | Assert.notEmpty(queue.getDeclaringAdmins(), "At least one RabbitAdmin must be declared (Queue: " + queue.getName() + ")");
25 | Object object = queue.getDeclaringAdmins().iterator().next();
26 | Assert.isInstanceOf(RabbitAdmin.class, object, "DeclaringAdmin must be a RabbitAdmin (Queue: " + queue.getName() + ")");
27 | this.rabbitAdmin = (RabbitAdmin) object;
28 | }
29 |
30 | public Queue getQueue()
31 | {
32 | return queue;
33 | }
34 |
35 | public RabbitAdmin getRabbitAdmin()
36 | {
37 | return rabbitAdmin;
38 | }
39 |
40 | public int getMaxMessageCount()
41 | {
42 | return maxMessageCount;
43 | }
44 |
45 | public int getMinConsumerCount()
46 | {
47 | return minConsumerCount;
48 | }
49 |
50 | @Override
51 | public String toString()
52 | {
53 | return "QueueCheck [queue=" + queue.getName() + ", maxMessageCount=" + maxMessageCount + ", minConsumerCount=" + minConsumerCount + "]";
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/RabbitQueueProperties.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq;
2 |
3 | public class RabbitQueueProperties
4 | {
5 | private int messageCount;
6 | private int consumerCount;
7 |
8 | public int getMessageCount()
9 | {
10 | return messageCount;
11 | }
12 |
13 | public void setMessageCount(int messageCount)
14 | {
15 | this.messageCount = messageCount;
16 | }
17 |
18 | public int getConsumerCount()
19 | {
20 | return consumerCount;
21 | }
22 |
23 | public void setConsumerCount(int consumerCount)
24 | {
25 | this.consumerCount = consumerCount;
26 | }
27 |
28 | @Override
29 | public String toString()
30 | {
31 | return "RabbitQueueProperties [messageCount=" + messageCount + ", consumerCount=" + consumerCount + "]";
32 | }
33 | }
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/RabbitQueuePropertiesManager.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq;
2 |
3 | import java.util.Properties;
4 |
5 | import org.springframework.amqp.core.Queue;
6 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
7 | import org.springframework.util.Assert;
8 |
9 | public class RabbitQueuePropertiesManager
10 | {
11 | public RabbitQueueProperties request(Queue queue)
12 | {
13 | RabbitAdmin rabbitAdmin = validateRabbitAdmin(queue);
14 | Properties queueProperties = rabbitAdmin.getQueueProperties(queue.getName());
15 |
16 | if (queueProperties == null)
17 | {
18 | throw new RuntimeException("Failed to fetch queue-properties (Queue: " + queue.getName() + ")");
19 | }
20 |
21 | RabbitQueueProperties properties = new RabbitQueueProperties();
22 | properties.setConsumerCount(Integer.parseInt(queueProperties.get("QUEUE_CONSUMER_COUNT").toString()));
23 | properties.setMessageCount(Integer.parseInt(queueProperties.get("QUEUE_MESSAGE_COUNT").toString()));
24 | return properties;
25 | }
26 |
27 | private RabbitAdmin validateRabbitAdmin(Queue queue)
28 | {
29 | Assert.notEmpty(queue.getDeclaringAdmins(), "At least one RabbitAdmin must be declared (Queue: " + queue.getName() + ")");
30 | Object object = queue.getDeclaringAdmins().iterator().next();
31 | Assert.isInstanceOf(RabbitAdmin.class, object, "DeclaringAdmin must be a RabbitAdmin (Queue: " + queue.getName() + ")");
32 | return (RabbitAdmin) object;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/health/RabbitQueueCheckHealthIndicator.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.health;
2 |
3 | import java.util.ArrayList;
4 | import java.util.LinkedHashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.springframework.amqp.core.Queue;
11 | import org.springframework.boot.actuate.health.AbstractHealthIndicator;
12 | import org.springframework.boot.actuate.health.Health.Builder;
13 |
14 | import com.itelg.spring.actuator.rabbitmq.QueueCheck;
15 | import com.itelg.spring.actuator.rabbitmq.RabbitQueueProperties;
16 | import com.itelg.spring.actuator.rabbitmq.RabbitQueuePropertiesManager;
17 |
18 | import org.springframework.boot.actuate.health.Status;
19 |
20 | public class RabbitQueueCheckHealthIndicator extends AbstractHealthIndicator
21 | {
22 | private static final Logger log = LoggerFactory.getLogger(RabbitQueueCheckHealthIndicator.class);
23 | private List queueChecks = new ArrayList();
24 | private RabbitQueuePropertiesManager propertiesManager = new RabbitQueuePropertiesManager();
25 |
26 | @Override
27 | protected void doHealthCheck(Builder builder) throws Exception
28 | {
29 | builder.up();
30 |
31 | for (QueueCheck queueCheck : queueChecks)
32 | {
33 | try
34 | {
35 | RabbitQueueProperties queueProperties = propertiesManager.request(queueCheck.getQueue());
36 | String queueName = queueCheck.getQueue().getName();
37 | int currentMessageCount = queueProperties.getMessageCount();
38 | int maxMessageCount = queueCheck.getMaxMessageCount();
39 | int currentConsumerCount = queueProperties.getConsumerCount();
40 | int minConsumerCount = queueCheck.getMinConsumerCount();
41 |
42 | Map details = new LinkedHashMap();
43 | details.put("status", Status.UP.getCode());
44 | details.put("currentMessageCount", Integer.valueOf(currentMessageCount));
45 | details.put("maxMessageCount", Integer.valueOf(maxMessageCount));
46 | details.put("currentConsumerCount", Integer.valueOf(currentConsumerCount));
47 | details.put("minConsumerCount", Integer.valueOf(minConsumerCount));
48 | builder.withDetail(queueName, details);
49 |
50 | if (currentMessageCount > maxMessageCount)
51 | {
52 | builder.down();
53 | details.put("status", Status.DOWN.getCode());
54 | log.warn(queueName + ": Too many messages ready (Current: " + currentMessageCount + ", " + "Max-Messages: " + queueCheck.getMaxMessageCount() + ")");
55 | }
56 |
57 | if (currentConsumerCount < minConsumerCount)
58 | {
59 | builder.down();
60 | details.put("status", Status.DOWN.getCode());
61 | log.warn(queueName + ": Not enough consumers active (Current: " + currentConsumerCount + ", " + "Min-Consumers: " + queueCheck.getMinConsumerCount() + ")");
62 | }
63 | }
64 | catch (Exception e)
65 | {
66 | log.error(e.getMessage(), e);
67 | builder.down();
68 | }
69 | }
70 | }
71 |
72 | public void addQueueCheck(Queue queue, int maxMessageCount)
73 | {
74 | queueChecks.add(new QueueCheck(queue, maxMessageCount, 1));
75 | }
76 |
77 | public void addQueueCheck(Queue queue, int maxMessageCount, int minConsumerCount)
78 | {
79 | queueChecks.add(new QueueCheck(queue, maxMessageCount, minConsumerCount));
80 | }
81 |
82 | public List getQueueChecks()
83 | {
84 | return queueChecks;
85 | }
86 | }
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/metric/RabbitQueueMetrics.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.metric;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.amqp.core.Queue;
9 |
10 | import com.itelg.spring.actuator.rabbitmq.QueueCheck;
11 | import com.itelg.spring.actuator.rabbitmq.RabbitQueuePropertiesManager;
12 |
13 | import io.micrometer.core.instrument.MeterRegistry;
14 | import io.micrometer.core.instrument.Tags;
15 | import io.micrometer.core.instrument.binder.MeterBinder;
16 |
17 | public class RabbitQueueMetrics implements MeterBinder
18 | {
19 | private static final Logger log = LoggerFactory.getLogger(RabbitQueueMetrics.class);
20 | private RabbitQueuePropertiesManager propertiesManager = new RabbitQueuePropertiesManager();
21 | private List queueChecks = new ArrayList<>();
22 |
23 | public RabbitQueueMetrics(List queues)
24 | {
25 | for (Queue queue : queues)
26 | {
27 | addQueue(queue);
28 | }
29 | }
30 |
31 | public RabbitQueueMetrics()
32 | {
33 | }
34 |
35 | public void addQueue(Queue queue)
36 | {
37 | queueChecks.add(new QueueCheck(queue, 0, 0));
38 | }
39 |
40 | public void addQueue(Queue queue, int maxMessageCount)
41 | {
42 | queueChecks.add(new QueueCheck(queue, maxMessageCount, 0));
43 | }
44 |
45 | public void addQueue(Queue queue, int maxMessageCount, int minConsumerCount)
46 | {
47 | queueChecks.add(new QueueCheck(queue, maxMessageCount, minConsumerCount));
48 | }
49 |
50 | @Override
51 | public void bindTo(MeterRegistry meterRegistry)
52 | {
53 | for (QueueCheck queueCheck : queueChecks)
54 | {
55 | Queue queue = queueCheck.getQueue();
56 | Tags tags = Tags.of("queue", queue.getName());
57 |
58 | try
59 | {
60 | meterRegistry.gauge("rabbitmq.queue.messages.current", tags, queue, q -> propertiesManager.request(q).getMessageCount());
61 | meterRegistry.gauge("rabbitmq.queue.consumers.current", tags, queue, q -> propertiesManager.request(q).getConsumerCount());
62 |
63 | if (queueCheck.getMaxMessageCount() > 0)
64 | {
65 | meterRegistry.gauge("rabbitmq.queue.messages.max", tags, queueCheck, QueueCheck::getMaxMessageCount);
66 | }
67 |
68 | if (queueCheck.getMinConsumerCount() > 0)
69 | {
70 | meterRegistry.gauge("rabbitmq.queue.consumers.min", tags, queueCheck, QueueCheck::getMinConsumerCount);
71 | }
72 | }
73 | catch (Exception e)
74 | {
75 | log.warn("Failed to fetch queue-information for {}", queue.getName(), e);
76 | }
77 | }
78 | }
79 |
80 | public List getQueueChecks()
81 | {
82 | return queueChecks;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/metric/configuration/EnableRabbitMetrics.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.metric.configuration;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | import org.springframework.context.annotation.Import;
10 |
11 | @Retention(RUNTIME)
12 | @Target(TYPE)
13 | @Import(RabbitMetricConfiguration.class)
14 | public @interface EnableRabbitMetrics
15 | {
16 |
17 | }
--------------------------------------------------------------------------------
/src/main/java/com/itelg/spring/actuator/rabbitmq/metric/configuration/RabbitMetricConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.metric.configuration;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.amqp.core.Queue;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | import com.itelg.spring.actuator.rabbitmq.metric.RabbitQueueMetrics;
10 |
11 | @Configuration
12 | public class RabbitMetricConfiguration
13 | {
14 | @Bean
15 | public RabbitQueueMetrics rabbitQueueMetrics(List queues)
16 | {
17 | return new RabbitQueueMetrics(queues);
18 | }
19 | }
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/QueueCheckTest.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 | import org.springframework.amqp.core.Queue;
6 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
7 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
8 |
9 | import com.itelg.spring.actuator.rabbitmq.QueueCheck;
10 |
11 | public class QueueCheckTest
12 | {
13 | @Test
14 | public void testConstructor()
15 | {
16 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
17 | RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
18 |
19 | Queue queue = new Queue("test");
20 | queue.setAdminsThatShouldDeclare(rabbitAdmin);
21 |
22 | QueueCheck queueCheck = new QueueCheck(queue, 10000, 2);
23 | Assert.assertEquals(10000, queueCheck.getMaxMessageCount());
24 | Assert.assertEquals(2, queueCheck.getMinConsumerCount());
25 | Assert.assertNotNull(queueCheck.getQueue());
26 | Assert.assertNotNull(queueCheck.getRabbitAdmin());
27 | }
28 | }
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/RabbitQueuePropertiesManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq;
2 |
3 | import java.util.Properties;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 | import org.powermock.api.easymock.PowerMock;
9 | import org.powermock.api.easymock.annotation.MockStrict;
10 | import org.powermock.modules.junit4.PowerMockRunner;
11 | import org.springframework.amqp.core.Queue;
12 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
13 |
14 | @RunWith(PowerMockRunner.class)
15 | public class RabbitQueuePropertiesManagerTest
16 | {
17 | private RabbitQueuePropertiesManager propertiesManager = new RabbitQueuePropertiesManager();
18 |
19 | @MockStrict
20 | private RabbitAdmin rabbitAdmin;
21 |
22 | @Test
23 | public void testRequest()
24 | {
25 | Queue queue = new Queue("test");
26 | queue.setAdminsThatShouldDeclare(rabbitAdmin);
27 |
28 | rabbitAdmin.getQueueProperties("test");
29 | PowerMock.expectLastCall().andAnswer(() ->
30 | {
31 | Properties properties = new Properties();
32 | properties.setProperty("QUEUE_CONSUMER_COUNT", "2");
33 | properties.setProperty("QUEUE_MESSAGE_COUNT", "234");
34 | return properties;
35 | });
36 |
37 | PowerMock.replayAll();
38 | RabbitQueueProperties queueProperties = propertiesManager.request(queue);
39 | PowerMock.verifyAll();
40 |
41 | Assert.assertEquals(2, queueProperties.getConsumerCount());
42 | Assert.assertEquals(234, queueProperties.getMessageCount());
43 | }
44 |
45 | @Test(expected = RuntimeException.class)
46 | public void testRequestWithFailed()
47 | {
48 | Queue queue = new Queue("test");
49 | queue.setAdminsThatShouldDeclare(rabbitAdmin);
50 |
51 | rabbitAdmin.getQueueProperties("test");
52 | PowerMock.expectLastCall().andReturn(null);
53 |
54 | PowerMock.replayAll();
55 | propertiesManager.request(queue);
56 | PowerMock.verifyAll();
57 | }
58 | }
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/RabbitQueuePropertiesTest.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import com.itelg.spring.actuator.rabbitmq.RabbitQueueProperties;
7 |
8 | public class RabbitQueuePropertiesTest
9 | {
10 | @Test
11 | public void testToString()
12 | {
13 | Assert.assertTrue(new RabbitQueueProperties().toString().startsWith("RabbitQueueProperties"));
14 | }
15 | }
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/health/RabbitQueueCheckHealthIndicatorTest.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.health;
2 |
3 | import static com.itelg.spring.actuator.rabbitmq.util.QueueUtil.generateQueue;
4 |
5 | import java.util.Map;
6 |
7 | import org.junit.Assert;
8 | import org.junit.Before;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.powermock.api.easymock.PowerMock;
12 | import org.powermock.api.easymock.annotation.Mock;
13 | import org.powermock.modules.junit4.PowerMockRunner;
14 | import org.powermock.reflect.Whitebox;
15 | import org.springframework.amqp.core.Queue;
16 | import org.springframework.boot.actuate.health.Health;
17 | import org.springframework.boot.actuate.health.Health.Builder;
18 |
19 | import com.itelg.spring.actuator.rabbitmq.RabbitQueueProperties;
20 | import com.itelg.spring.actuator.rabbitmq.RabbitQueuePropertiesManager;
21 | import com.itelg.spring.actuator.rabbitmq.health.RabbitQueueCheckHealthIndicator;
22 |
23 | import org.springframework.boot.actuate.health.Status;
24 |
25 | @RunWith(PowerMockRunner.class)
26 | public class RabbitQueueCheckHealthIndicatorTest
27 | {
28 | private RabbitQueueCheckHealthIndicator healthIndicator;
29 |
30 | @Mock
31 | private RabbitQueuePropertiesManager propertiesManager;
32 |
33 | @Before
34 | public void before()
35 | {
36 | healthIndicator = new RabbitQueueCheckHealthIndicator();
37 | Whitebox.setInternalState(healthIndicator, propertiesManager);
38 | }
39 |
40 | @Test
41 | public void testDoHealthCheckNoQueueChecks() throws Exception
42 | {
43 | Builder builder = new Builder(Status.OUT_OF_SERVICE);
44 | healthIndicator.doHealthCheck(builder);
45 | Assert.assertEquals(Status.UP, builder.build().getStatus());
46 | }
47 |
48 | @SuppressWarnings({ "unchecked", "boxing" })
49 | @Test
50 | public void testDoHealthCheckSingleQueueCheckUp() throws Exception
51 | {
52 | Queue queue = generateQueue("test");
53 | healthIndicator.addQueueCheck(queue, 10000, 2);
54 |
55 | RabbitQueueProperties properties = new RabbitQueueProperties();
56 | properties.setConsumerCount(4);
57 | properties.setMessageCount(5883);
58 | propertiesManager.request(queue);
59 | PowerMock.expectLastCall().andReturn(properties);
60 |
61 | PowerMock.replayAll();
62 | Builder builder = new Builder(Status.OUT_OF_SERVICE);
63 | healthIndicator.doHealthCheck(builder);
64 | PowerMock.verifyAll();
65 |
66 | Health health = builder.build();
67 | Assert.assertEquals(Status.UP, health.getStatus());
68 | Assert.assertNotNull(health.getDetails().get("test"));
69 | Map details = (Map) health.getDetails().get("test");
70 | Assert.assertEquals(Status.UP.getCode(), details.get("status"));
71 | Assert.assertEquals(5883, details.get("currentMessageCount"));
72 | Assert.assertEquals(10000, details.get("maxMessageCount"));
73 | Assert.assertEquals(4, details.get("currentConsumerCount"));
74 | Assert.assertEquals(2, details.get("minConsumerCount"));
75 | }
76 |
77 | @SuppressWarnings({ "unchecked", "boxing" })
78 | @Test
79 | public void testDoHealthCheckSingleQueueCheckQueueSizeDown() throws Exception
80 | {
81 | Queue queue = generateQueue("test");
82 | healthIndicator.addQueueCheck(queue, 10000, 2);
83 |
84 | RabbitQueueProperties properties = new RabbitQueueProperties();
85 | properties.setConsumerCount(4);
86 | properties.setMessageCount(15883);
87 | propertiesManager.request(queue);
88 | PowerMock.expectLastCall().andReturn(properties);
89 |
90 | PowerMock.replayAll();
91 | Builder builder = new Builder(Status.OUT_OF_SERVICE);
92 | healthIndicator.doHealthCheck(builder);
93 | PowerMock.verifyAll();
94 |
95 | Health health = builder.build();
96 | Assert.assertEquals(Status.DOWN, health.getStatus());
97 | Assert.assertNotNull(health.getDetails().get("test"));
98 | Map details = (Map) health.getDetails().get("test");
99 | Assert.assertEquals(Status.DOWN.getCode(), details.get("status"));
100 | Assert.assertEquals(15883, details.get("currentMessageCount"));
101 | Assert.assertEquals(10000, details.get("maxMessageCount"));
102 | Assert.assertEquals(4, details.get("currentConsumerCount"));
103 | Assert.assertEquals(2, details.get("minConsumerCount"));
104 | }
105 |
106 | @SuppressWarnings({ "unchecked", "boxing" })
107 | @Test
108 | public void testDoHealthCheckSingleQueueCheckConsumerDown() throws Exception
109 | {
110 | Queue queue = generateQueue("test");
111 | healthIndicator.addQueueCheck(queue, 10000, 2);
112 |
113 | RabbitQueueProperties properties = new RabbitQueueProperties();
114 | properties.setConsumerCount(1);
115 | properties.setMessageCount(5883);
116 | propertiesManager.request(queue);
117 | PowerMock.expectLastCall().andReturn(properties);
118 |
119 | PowerMock.replayAll();
120 | Builder builder = new Builder(Status.OUT_OF_SERVICE);
121 | healthIndicator.doHealthCheck(builder);
122 | PowerMock.verifyAll();
123 |
124 | Health health = builder.build();
125 | Assert.assertEquals(Status.DOWN, health.getStatus());
126 | Assert.assertNotNull(health.getDetails().get("test"));
127 | Map details = (Map) health.getDetails().get("test");
128 | Assert.assertEquals(Status.DOWN.getCode(), details.get("status"));
129 | Assert.assertEquals(5883, details.get("currentMessageCount"));
130 | Assert.assertEquals(10000, details.get("maxMessageCount"));
131 | Assert.assertEquals(1, details.get("currentConsumerCount"));
132 | Assert.assertEquals(2, details.get("minConsumerCount"));
133 | }
134 |
135 | @Test
136 | public void testDoHealthCheckSingleQueueCheckMetricException() throws Exception
137 | {
138 | Queue queue = generateQueue("test");
139 | healthIndicator.addQueueCheck(queue, 10000, 2);
140 |
141 | propertiesManager.request(queue);
142 | PowerMock.expectLastCall().andThrow(new RuntimeException());
143 |
144 | PowerMock.replayAll();
145 | Builder builder = new Builder(Status.OUT_OF_SERVICE);
146 | healthIndicator.doHealthCheck(builder);
147 | PowerMock.verifyAll();
148 |
149 | Health health = builder.build();
150 | Assert.assertEquals(Status.DOWN, health.getStatus());
151 | Assert.assertNull(health.getDetails().get("test"));
152 | }
153 |
154 | @SuppressWarnings({ "unchecked", "boxing" })
155 | @Test
156 | public void testDoHealthCheckMultipleQueueChecksOneUpOneDown() throws Exception
157 | {
158 | Queue queue1 = generateQueue("test1");
159 | healthIndicator.addQueueCheck(queue1, 10000, 2);
160 | Queue queue2 = generateQueue("test2");
161 | healthIndicator.addQueueCheck(queue2, 40000, 5);
162 |
163 | RabbitQueueProperties properties1 = new RabbitQueueProperties();
164 | properties1.setConsumerCount(1);
165 | properties1.setMessageCount(15883);
166 | propertiesManager.request(queue1);
167 | PowerMock.expectLastCall().andReturn(properties1);
168 |
169 | RabbitQueueProperties properties2 = new RabbitQueueProperties();
170 | properties2.setConsumerCount(10);
171 | properties2.setMessageCount(5883);
172 | propertiesManager.request(queue2);
173 | PowerMock.expectLastCall().andReturn(properties2);
174 |
175 | PowerMock.replayAll();
176 | Builder builder = new Builder(Status.OUT_OF_SERVICE);
177 | healthIndicator.doHealthCheck(builder);
178 | PowerMock.verifyAll();
179 |
180 | Health health = builder.build();
181 | Assert.assertEquals(Status.DOWN, health.getStatus());
182 | Assert.assertEquals(2, health.getDetails().size());
183 |
184 | Assert.assertNotNull(health.getDetails().get("test1"));
185 | Map details1 = (Map) health.getDetails().get("test1");
186 | Assert.assertEquals(Status.DOWN.getCode(), details1.get("status"));
187 | Assert.assertEquals(15883, details1.get("currentMessageCount"));
188 | Assert.assertEquals(10000, details1.get("maxMessageCount"));
189 | Assert.assertEquals(1, details1.get("currentConsumerCount"));
190 | Assert.assertEquals(2, details1.get("minConsumerCount"));
191 |
192 | Assert.assertNotNull(health.getDetails().get("test2"));
193 | Map details2 = (Map) health.getDetails().get("test2");
194 | Assert.assertEquals(Status.UP.getCode(), details2.get("status"));
195 | Assert.assertEquals(5883, details2.get("currentMessageCount"));
196 | Assert.assertEquals(40000, details2.get("maxMessageCount"));
197 | Assert.assertEquals(10, details2.get("currentConsumerCount"));
198 | Assert.assertEquals(5, details2.get("minConsumerCount"));
199 | }
200 |
201 | @Test
202 | public void testAddQueueCheckMaxMessageCountAndMinConsumerCount()
203 | {
204 | healthIndicator.addQueueCheck(generateQueue("test"), 10000, 5);
205 | healthIndicator.addQueueCheck(generateQueue("test"), 5000, 2);
206 | Assert.assertEquals(2, healthIndicator.getQueueChecks().size());
207 | }
208 |
209 | @Test
210 | public void testAddQueueCheckMaxMessageCount()
211 | {
212 | healthIndicator.addQueueCheck(generateQueue("test"), 10000);
213 | healthIndicator.addQueueCheck(generateQueue("test"), 5000);
214 | Assert.assertEquals(2, healthIndicator.getQueueChecks().size());
215 | }
216 |
217 | @Test
218 | public void testGetQueueChecks()
219 | {
220 | Assert.assertNotNull(healthIndicator.getQueueChecks());
221 |
222 | Queue queue = generateQueue("test");
223 | healthIndicator.addQueueCheck(queue, 1);
224 | healthIndicator.addQueueCheck(queue, 1);
225 | Assert.assertEquals(2, healthIndicator.getQueueChecks().size());
226 | }
227 | }
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/metric/RabbitQueueMetricsTest.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.metric;
2 |
3 | import static com.itelg.spring.actuator.rabbitmq.util.QueueUtil.generateQueue;
4 | import static java.util.Collections.singletonList;
5 |
6 | import java.util.function.ToDoubleFunction;
7 |
8 | import org.easymock.Capture;
9 | import org.easymock.EasyMock;
10 | import org.junit.Assert;
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 | import org.powermock.api.easymock.PowerMock;
15 | import org.powermock.api.easymock.annotation.MockStrict;
16 | import org.powermock.modules.junit4.PowerMockRunner;
17 | import org.powermock.reflect.Whitebox;
18 | import org.springframework.amqp.core.Queue;
19 |
20 | import com.itelg.spring.actuator.rabbitmq.QueueCheck;
21 | import com.itelg.spring.actuator.rabbitmq.RabbitQueueProperties;
22 | import com.itelg.spring.actuator.rabbitmq.RabbitQueuePropertiesManager;
23 |
24 | import io.micrometer.core.instrument.MeterRegistry;
25 | import io.micrometer.core.instrument.Tags;
26 |
27 | @RunWith(PowerMockRunner.class)
28 | public class RabbitQueueMetricsTest
29 | {
30 | private RabbitQueueMetrics rabbitQueueMetrics;
31 |
32 | @MockStrict
33 | private RabbitQueuePropertiesManager propertiesManager;
34 |
35 | @MockStrict
36 | private MeterRegistry meterRegistry;
37 |
38 | @Before
39 | public void before()
40 | {
41 | rabbitQueueMetrics = new RabbitQueueMetrics();
42 | Whitebox.setInternalState(rabbitQueueMetrics, propertiesManager);
43 | }
44 |
45 | @Test
46 | public void testConstructor()
47 | {
48 | rabbitQueueMetrics = new RabbitQueueMetrics(singletonList(generateQueue("test.queue")));
49 | QueueCheck queueCheck = rabbitQueueMetrics.getQueueChecks().get(0);
50 | Assert.assertEquals(0, queueCheck.getMaxMessageCount());
51 | Assert.assertEquals(0, queueCheck.getMinConsumerCount());
52 | }
53 |
54 | @Test
55 | public void testAddQueue()
56 | {
57 | rabbitQueueMetrics.addQueue(generateQueue("test.queue"));
58 | QueueCheck queueCheck = rabbitQueueMetrics.getQueueChecks().get(0);
59 | Assert.assertEquals(0, queueCheck.getMaxMessageCount());
60 | Assert.assertEquals(0, queueCheck.getMinConsumerCount());
61 | }
62 |
63 | @Test
64 | public void testAddQueueWithMaxMessageCount()
65 | {
66 | rabbitQueueMetrics.addQueue(generateQueue("test.queue"), 10000);
67 | QueueCheck queueCheck = rabbitQueueMetrics.getQueueChecks().get(0);
68 | Assert.assertEquals(10000, queueCheck.getMaxMessageCount());
69 | Assert.assertEquals(0, queueCheck.getMinConsumerCount());
70 | }
71 |
72 | @Test
73 | public void testAddQueueWithMaxMessageAndMinConsumerCount()
74 | {
75 | rabbitQueueMetrics.addQueue(generateQueue("test.queue"), 10000, 2);
76 | QueueCheck queueCheck = rabbitQueueMetrics.getQueueChecks().get(0);
77 | Assert.assertEquals(10000, queueCheck.getMaxMessageCount());
78 | Assert.assertEquals(2, queueCheck.getMinConsumerCount());
79 | }
80 |
81 | @Test
82 | public void testMetrics()
83 | {
84 | Queue queue = generateQueue("test.queue");
85 | rabbitQueueMetrics.addQueue(queue, 0, 0);
86 |
87 | EasyMock.expect(propertiesManager.request(queue)).andAnswer(this::buildQueueProperties).times(2);
88 |
89 | Capture> currentMessageCountFunctionCapture = EasyMock.newCapture();
90 | Capture> currentConsumerCountFunctionCapture = EasyMock.newCapture();
91 |
92 | EasyMock.expect(meterRegistry
93 | .gauge(EasyMock.eq("rabbitmq.queue.messages.current"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queue), EasyMock
94 | .capture(currentMessageCountFunctionCapture)))
95 | .andReturn(queue);
96 |
97 | EasyMock.expect(meterRegistry
98 | .gauge(EasyMock.eq("rabbitmq.queue.consumers.current"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queue), EasyMock
99 | .capture(currentConsumerCountFunctionCapture)))
100 | .andReturn(queue);
101 |
102 | PowerMock.replayAll();
103 | rabbitQueueMetrics.bindTo(meterRegistry);
104 |
105 | Assert.assertEquals(5432.0, currentMessageCountFunctionCapture.getValue().applyAsDouble(queue), 0.0);
106 | Assert.assertEquals(2.0, currentConsumerCountFunctionCapture.getValue().applyAsDouble(queue), 0.0);
107 |
108 | PowerMock.verifyAll();
109 | }
110 |
111 | @Test
112 | public void testMetricsWithThreshold()
113 | {
114 | Queue queue = generateQueue("test.queue");
115 | rabbitQueueMetrics.addQueue(queue, 10000, 5);
116 | QueueCheck queueCheck = rabbitQueueMetrics.getQueueChecks().get(0);
117 |
118 | EasyMock.expect(propertiesManager.request(queue)).andAnswer(this::buildQueueProperties).times(2);
119 |
120 | Capture> currentMessageCountFunctionCapture = EasyMock.newCapture();
121 | Capture> currentConsumerCountFunctionCapture = EasyMock.newCapture();
122 | Capture> minConsumerCountFunctionCapture = EasyMock.newCapture();
123 | Capture> maxMessageCountFunctionCapture = EasyMock.newCapture();
124 |
125 | EasyMock.expect(meterRegistry
126 | .gauge(EasyMock.eq("rabbitmq.queue.messages.current"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queue), EasyMock
127 | .capture(currentMessageCountFunctionCapture)))
128 | .andReturn(queue);
129 |
130 | EasyMock.expect(meterRegistry
131 | .gauge(EasyMock.eq("rabbitmq.queue.consumers.current"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queue), EasyMock
132 | .capture(currentConsumerCountFunctionCapture)))
133 | .andReturn(queue);
134 |
135 | EasyMock.expect(meterRegistry
136 | .gauge(EasyMock.eq("rabbitmq.queue.messages.max"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queueCheck), EasyMock
137 | .capture(maxMessageCountFunctionCapture)))
138 | .andReturn(queueCheck);
139 |
140 | EasyMock.expect(meterRegistry
141 | .gauge(EasyMock.eq("rabbitmq.queue.consumers.min"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queueCheck), EasyMock
142 | .capture(minConsumerCountFunctionCapture)))
143 | .andReturn(queueCheck);
144 |
145 | PowerMock.replayAll();
146 | rabbitQueueMetrics.bindTo(meterRegistry);
147 |
148 | Assert.assertEquals(5432.0, currentMessageCountFunctionCapture.getValue().applyAsDouble(queue), 0.0);
149 | Assert.assertEquals(2.0, currentConsumerCountFunctionCapture.getValue().applyAsDouble(queue), 0.0);
150 | Assert.assertEquals(5.0, minConsumerCountFunctionCapture.getValue().applyAsDouble(queueCheck), 0.0);
151 | Assert.assertEquals(10000.0, maxMessageCountFunctionCapture.getValue().applyAsDouble(queueCheck), 0.0);
152 |
153 | PowerMock.verifyAll();
154 | }
155 |
156 | @Test
157 | public void testMetricsWithException()
158 | {
159 | Queue queue = generateQueue("test.queue");
160 | rabbitQueueMetrics.addQueue(queue, 10000, 5);
161 |
162 | EasyMock.expect(meterRegistry
163 | .gauge(EasyMock.eq("rabbitmq.queue.messages.current"), EasyMock.eq(Tags.of("queue", "test.queue")), EasyMock.eq(queue), EasyMock.anyObject()))
164 | .andThrow(new RuntimeException());
165 |
166 | PowerMock.replayAll();
167 | rabbitQueueMetrics.bindTo(meterRegistry);
168 | PowerMock.verifyAll();
169 |
170 | // no exception expected
171 | }
172 |
173 | private RabbitQueueProperties buildQueueProperties()
174 | {
175 | RabbitQueueProperties properties = new RabbitQueueProperties();
176 | properties.setMessageCount(5432);
177 | properties.setConsumerCount(2);
178 | return properties;
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/metric/configuration/RabbitMetricConfigurationTest.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.metric.configuration;
2 |
3 | import java.util.Collections;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.springframework.amqp.core.Queue;
8 |
9 | import com.itelg.spring.actuator.rabbitmq.metric.RabbitQueueMetrics;
10 | import com.itelg.spring.actuator.rabbitmq.util.QueueUtil;
11 |
12 | public class RabbitMetricConfigurationTest
13 | {
14 | @Test
15 | public void testRabbitQueueMetrics()
16 | {
17 | Queue queue = QueueUtil.generateQueue("test");
18 | RabbitQueueMetrics metrics = new RabbitMetricConfiguration().rabbitQueueMetrics(Collections.singletonList(queue));
19 | Assert.assertEquals(1, metrics.getQueueChecks().size());
20 | }
21 | }
--------------------------------------------------------------------------------
/src/test/java/com/itelg/spring/actuator/rabbitmq/util/QueueUtil.java:
--------------------------------------------------------------------------------
1 | package com.itelg.spring.actuator.rabbitmq.util;
2 |
3 | import org.springframework.amqp.core.Queue;
4 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
5 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
6 |
7 | public class QueueUtil
8 | {
9 | public static Queue generateQueue(String name)
10 | {
11 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
12 | RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
13 |
14 | Queue queue = new Queue(name);
15 | queue.setAdminsThatShouldDeclare(rabbitAdmin);
16 |
17 | return queue;
18 | }
19 | }
--------------------------------------------------------------------------------