Skip to content

Commit f405c10

Browse files
authored
Merge pull request #99 from rabbitmq/rabbitmq-perf-test-metrics-prometheus
Add support for metrics with Prometheus
2 parents fbe032b + 8145085 commit f405c10

18 files changed

+794
-88
lines changed

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export PATH :=$(CURDIR):$(CURDIR)/scripts:$(PATH)
1010
#
1111

1212
binary: clean ## Build the binary distribution
13-
@mvnw package -P assemblies -Dgpg.skip=true
13+
@mvnw package -P assemblies -Dgpg.skip=true -Dmaven.test.skip
1414

1515
help:
1616
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@@ -21,6 +21,9 @@ clean: ## Clean all build artefacts
2121
compile: ## Compile the source code
2222
@mvnw compile
2323

24+
install: clean ## Create and copy the binaries into the local Maven repository
25+
@mvnw install -Dmaven.test.skip
26+
2427
jar: clean ## Build the JAR file
2528
@mvnw package
2629

pom.xml

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,15 @@
5757
<rabbitmq.version>5.2.0</rabbitmq.version>
5858
<commons-cli.version>1.1</commons-cli.version>
5959
<metrics.version>4.0.2</metrics.version>
60+
<micrometer.version>1.0.4</micrometer.version>
6061
<logback.version>1.2.3</logback.version>
61-
<jetty.version>9.4.9.v20180320</jetty.version>
62-
<junit.jupiter.version>5.1.0</junit.jupiter.version>
63-
<junit.platform.version>1.1.0</junit.platform.version>
64-
<mockito.version>2.16.0</mockito.version>
62+
<jetty.version>9.4.11.v20180605</jetty.version>
63+
<junit.jupiter.version>5.2.0</junit.jupiter.version>
64+
<junit.platform.version>1.2.0</junit.platform.version>
65+
<mockito.version>2.18.3</mockito.version>
6566
<hamcrest.version>2.0.0.0</hamcrest.version>
6667
<awaitility.version>3.1.0</awaitility.version>
68+
<jmh.version>1.20</jmh.version>
6769

6870
<!-- to sign artifacts when releasing -->
6971
<gpg.keyname>6026DFCA</gpg.keyname>
@@ -72,21 +74,20 @@
7274
<versions.maven.plugin.version>2.3</versions.maven.plugin.version>
7375
<maven.release.plugin.version>2.5.3</maven.release.plugin.version>
7476
<maven.source.plugin.version>3.0.1</maven.source.plugin.version>
75-
<maven.javadoc.plugin.version>3.0.0-M1</maven.javadoc.plugin.version>
77+
<maven.javadoc.plugin.version>3.0.1</maven.javadoc.plugin.version>
7678
<maven.gpg.plugin.version>1.6</maven.gpg.plugin.version>
7779
<maven.assembly.plugin.version>3.1.0</maven.assembly.plugin.version>
7880
<maven.install.plugin.version>2.5.2</maven.install.plugin.version>
7981
<checksum.maven.plugin.version>1.6</checksum.maven.plugin.version>
8082
<maven.jar.plugin.version>3.0.2</maven.jar.plugin.version>
8183
<buildnumber.plugin.version>1.4</buildnumber.plugin.version>
82-
<maven.surefire.plugin.version>2.19.1</maven.surefire.plugin.version>
84+
<maven.surefire.plugin.version>2.21.0</maven.surefire.plugin.version>
8385

8486
<!-- because of https://issues.apache.org/jira/browse/MRESOURCES-99 -->
8587
<build.timestamp>${maven.build.timestamp}</build.timestamp>
8688
<maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format>
8789

8890
<finalName>rabbitmq-${project.build.finalName}</finalName>
89-
<jmh.version>1.20</jmh.version>
9091
</properties>
9192

9293
<dependencies>
@@ -110,6 +111,29 @@
110111
<artifactId>jetty-servlet</artifactId>
111112
<version>${jetty.version}</version>
112113
</dependency>
114+
<dependency>
115+
<groupId>io.micrometer</groupId>
116+
<artifactId>micrometer-core</artifactId>
117+
<version>${micrometer.version}</version>
118+
</dependency>
119+
<dependency>
120+
<groupId>io.micrometer</groupId>
121+
<artifactId>micrometer-registry-prometheus</artifactId>
122+
<version>${micrometer.version}</version>
123+
</dependency>
124+
<dependency>
125+
<groupId>ch.qos.logback</groupId>
126+
<artifactId>logback-classic</artifactId>
127+
<version>${logback.version}</version>
128+
<optional>true</optional>
129+
</dependency>
130+
<dependency>
131+
<groupId>ch.qos.logback</groupId>
132+
<artifactId>logback-core</artifactId>
133+
<version>${logback.version}</version>
134+
<optional>true</optional>
135+
</dependency>
136+
113137

114138
<dependency>
115139
<groupId>org.junit.jupiter</groupId>
@@ -168,13 +192,6 @@
168192
<scope>test</scope>
169193
</dependency>
170194

171-
<dependency>
172-
<groupId>ch.qos.logback</groupId>
173-
<artifactId>logback-classic</artifactId>
174-
<version>${logback.version}</version>
175-
<scope>test</scope>
176-
</dependency>
177-
178195
<dependency>
179196
<groupId>org.openjdk.jmh</groupId>
180197
<artifactId>jmh-core</artifactId>
@@ -453,6 +470,12 @@
453470
<version>${logback.version}</version>
454471
</dependency>
455472

473+
<dependency>
474+
<groupId>ch.qos.logback</groupId>
475+
<artifactId>logback-core</artifactId>
476+
<version>${logback.version}</version>
477+
</dependency>
478+
456479
</dependencies>
457480
<build>
458481
<plugins>

src/main/java/com/rabbitmq/perf/AgentBase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ protected void delay(long now, AgentState state) {
2424

2525
long elapsed = now - state.getLastStatsTime();
2626
//example: rateLimit is 5000 msg/s,
27-
//10 ms have elapsed, we have sent 200 messages
28-
//the 200 msgs we have actually sent should have taken us
27+
//10 ms have elapsed, we have published 200 messages
28+
//the 200 msgs we have actually published should have taken us
2929
//200 * 1000 / 5000 = 40 ms. So we pause for 40ms - 10ms
3030
long pause = (long) (state.getRateLimit() == 0.0f ?
3131
0.0f : (state.getMsgCount() * 1000.0 / state.getRateLimit() - elapsed));
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved.
2+
//
3+
// This software, the RabbitMQ Java client library, is triple-licensed under the
4+
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
5+
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
6+
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
7+
// please see LICENSE-APACHE2.
8+
//
9+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
10+
// either express or implied. See the LICENSE file for specific language governing
11+
// rights and limitations of this software.
12+
//
13+
// If you have any questions regarding licensing, please contact us at
14+
15+
16+
package com.rabbitmq.perf;
17+
18+
import com.rabbitmq.client.ConnectionFactory;
19+
import com.rabbitmq.client.impl.MicrometerMetricsCollector;
20+
import io.micrometer.core.instrument.Tag;
21+
import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics;
22+
import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics;
23+
import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics;
24+
import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics;
25+
import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
26+
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
27+
import org.apache.commons.cli.Option;
28+
import org.apache.commons.cli.Options;
29+
30+
import java.util.ArrayList;
31+
import java.util.Collection;
32+
33+
import static com.rabbitmq.perf.PerfTest.strArg;
34+
35+
/**
36+
*
37+
*/
38+
public class BaseMetrics implements Metrics {
39+
40+
@Override
41+
public Options options() {
42+
Options options = new Options();
43+
options.addOption(new Option("mt", "metrics-tags", true, "metrics tags as key-value pairs separated by commas"));
44+
options.addOption(new Option("mpx", "metrics-prefix", true, "prefix for PerfTest metrics, default is perftest_"));
45+
options.addOption(new Option("mc", "metrics-client", false, "enable client metrics"));
46+
options.addOption(new Option("mcl", "metrics-class-loader", false, "enable JVM class loader metrics"));
47+
options.addOption(new Option("mjm", "metrics-jvm-memory", false, "enable JVM memory metrics"));
48+
options.addOption(new Option("mjgc", "metrics-jvm-gc", false, "enable JVM GC metrics"));
49+
options.addOption(new Option("mjp", "metrics-processor", false, "enable processor metrics (gathered by JVM)"));
50+
options.addOption(new Option("mjt", "metrics-jvm-thread", false, "enable JVM thread metrics"));
51+
52+
return options;
53+
}
54+
55+
@Override
56+
public void configure(CommandLineProxy cmd, CompositeMeterRegistry meterRegistry, ConnectionFactory factory) {
57+
String argumentTags = strArg(cmd, "mt", null);
58+
Collection<Tag> tags = new ArrayList<>();
59+
if (argumentTags != null) {
60+
for (String tag : argumentTags.split(",")) {
61+
String[] keyValue = tag.split("=");
62+
tags.add(Tag.of(keyValue[0], keyValue[1]));
63+
}
64+
}
65+
meterRegistry.config().commonTags(tags);
66+
if (cmd.hasOption("mc")) {
67+
factory.setMetricsCollector(new MicrometerMetricsCollector(meterRegistry, "client"));
68+
}
69+
70+
if (cmd.hasOption("mcl")) {
71+
new ClassLoaderMetrics().bindTo(meterRegistry);
72+
}
73+
if (cmd.hasOption("mjm")) {
74+
new JvmMemoryMetrics().bindTo(meterRegistry);
75+
}
76+
if (cmd.hasOption("mjgc")) {
77+
new JvmGcMetrics().bindTo(meterRegistry);
78+
}
79+
if (cmd.hasOption("mjp")) {
80+
new ProcessorMetrics().bindTo(meterRegistry);
81+
}
82+
if (cmd.hasOption("mjt")) {
83+
new JvmThreadMetrics().bindTo(meterRegistry);
84+
}
85+
}
86+
87+
@Override
88+
public String toString() {
89+
return "Base Metrics";
90+
}
91+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved.
2+
//
3+
// This software, the RabbitMQ Java client library, is triple-licensed under the
4+
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
5+
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
6+
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
7+
// please see LICENSE-APACHE2.
8+
//
9+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
10+
// either express or implied. See the LICENSE file for specific language governing
11+
// rights and limitations of this software.
12+
//
13+
// If you have any questions regarding licensing, please contact us at
14+
15+
16+
package com.rabbitmq.perf;
17+
18+
import com.rabbitmq.client.ConnectionFactory;
19+
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
20+
import org.apache.commons.cli.Options;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
27+
import static com.rabbitmq.perf.OptionsUtils.forEach;
28+
29+
/**
30+
*
31+
*/
32+
public class CompositeMetrics implements Metrics {
33+
34+
private static final Logger LOGGER = LoggerFactory.getLogger(CompositeMetrics.class);
35+
36+
private final List<Metrics> metrics = new ArrayList<>();
37+
38+
public CompositeMetrics() {
39+
metrics.add(new BaseMetrics());
40+
metrics.add(new PrometheusMetrics());
41+
}
42+
43+
@Override
44+
public Options options() {
45+
Options options = new Options();
46+
for (Metrics metric : metrics) {
47+
forEach(metric.options(), option -> {
48+
if (options.hasOption(option.getOpt())) {
49+
throw new IllegalStateException("Option already existing: " + option.getOpt());
50+
} else {
51+
options.addOption(option);
52+
}
53+
});
54+
}
55+
return options;
56+
}
57+
58+
@Override
59+
public void configure(CommandLineProxy cmd, CompositeMeterRegistry meterRegistry, ConnectionFactory factory) throws Exception {
60+
for (Metrics metric : metrics) {
61+
metric.configure(cmd, meterRegistry, factory);
62+
}
63+
}
64+
65+
@Override
66+
public boolean isEnabled(CommandLineProxy cmd) {
67+
for (Metrics metric : metrics) {
68+
if (metric.isEnabled(cmd)) {
69+
return true;
70+
}
71+
}
72+
return false;
73+
}
74+
75+
@Override
76+
public void close() {
77+
for (Metrics metric : metrics) {
78+
try {
79+
metric.close();
80+
} catch (Exception e) {
81+
LOGGER.warn("Error while closing metrics {}", metrics, e);
82+
}
83+
}
84+
}
85+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved.
2+
//
3+
// This software, the RabbitMQ Java client library, is triple-licensed under the
4+
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
5+
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
6+
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
7+
// please see LICENSE-APACHE2.
8+
//
9+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
10+
// either express or implied. See the LICENSE file for specific language governing
11+
// rights and limitations of this software.
12+
//
13+
// If you have any questions regarding licensing, please contact us at
14+
15+
16+
package com.rabbitmq.perf;
17+
18+
import com.rabbitmq.client.ConnectionFactory;
19+
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
20+
import org.apache.commons.cli.Option;
21+
import org.apache.commons.cli.Options;
22+
23+
/**
24+
*
25+
*/
26+
public interface Metrics {
27+
28+
Options options();
29+
30+
default void configure(CommandLineProxy cmd, CompositeMeterRegistry meterRegistry, ConnectionFactory factory) throws Exception { }
31+
32+
default boolean isEnabled(CommandLineProxy cmd) {
33+
for (Object optObj : this.options().getOptions()) {
34+
Option option = (Option) optObj;
35+
if (cmd.hasOption(option.getOpt())) {
36+
return true;
37+
}
38+
}
39+
return false;
40+
}
41+
42+
default void close() throws Exception { }
43+
44+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved.
2+
//
3+
// This software, the RabbitMQ Java client library, is triple-licensed under the
4+
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
5+
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
6+
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
7+
// please see LICENSE-APACHE2.
8+
//
9+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
10+
// either express or implied. See the LICENSE file for specific language governing
11+
// rights and limitations of this software.
12+
//
13+
// If you have any questions regarding licensing, please contact us at
14+
15+
16+
package com.rabbitmq.perf;
17+
18+
import org.apache.commons.cli.Option;
19+
import org.apache.commons.cli.Options;
20+
21+
/**
22+
*
23+
*/
24+
public class OptionsUtils {
25+
26+
static void forEach(Options options, OptionConsumer action) {
27+
for (Object option : options.getOptions()) {
28+
try {
29+
action.apply((Option) option);
30+
} catch (Exception e) {
31+
throw new RuntimeException(e);
32+
}
33+
}
34+
}
35+
36+
@FunctionalInterface
37+
interface OptionConsumer {
38+
39+
void apply(Option option) throws Exception;
40+
41+
}
42+
43+
}

0 commit comments

Comments
 (0)