diff --git a/pom.xml b/pom.xml
index 94a2f79..1450d83 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
com.github.johrstrom
jmeter-prometheus-plugin
- 0.7.2-SNAPSHOT
+ 0.7.3-SNAPSHOT
Jmeter-Prometheus Listener Plugin
A Jmeter plugin that creates a Prometheus endpoint of results.
https://github.com/johrstrom/jmeter-prometheus-plugin
@@ -104,6 +104,11 @@
simpleclient_hotspot
${prometheus.version}
+
+ io.prometheus
+ simpleclient_pushgateway
+ ${prometheus.version}
+
junit
junit
diff --git a/src/main/java/com/github/johrstrom/listener/PrometheusListener.java b/src/main/java/com/github/johrstrom/listener/PrometheusListener.java
index 23278cc..f4fb350 100644
--- a/src/main/java/com/github/johrstrom/listener/PrometheusListener.java
+++ b/src/main/java/com/github/johrstrom/listener/PrometheusListener.java
@@ -34,8 +34,10 @@
import org.slf4j.LoggerFactory;
import java.io.Serializable;
+import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* The main test element listener class of this library. Jmeter updates this
@@ -55,6 +57,8 @@ public class PrometheusListener extends CollectorElement updaters;
/*
@@ -104,6 +108,7 @@ public void sampleStopped(SampleEvent arg0) {
@Override
public void testEnded() {
try {
+ this.destroyPushGateway();
this.server.stop();
} catch (Exception e) {
log.error("Couldn't stop http server", e);
@@ -123,6 +128,29 @@ public void testEnded(String arg0) {
this.testEnded();
}
+ private void destroyPushGateway() {
+ if (Objects.nonNull(this.pushGateway)) {
+ this.pushGateway.finish();
+ }
+ }
+
+ private void configurePushGateway() {
+ boolean sendToPushGateway = getPropertyAsBoolean("sendToPushGateway", false);
+ log.info("Envio de métricas ao PushGateway está {}", sendToPushGateway ? "habilitado" : "desabilitado");
+ if (sendToPushGateway) {
+ try {
+ this.pushGateway = new PushGateway(
+ getPropertyAsString("pushGatewayHost", "http://localhost:9091"),
+ getPropertyAsString("jobName", "jmeter"),
+ getPropertyAsInt("interval", 30)
+ );
+ this.pushGateway.start();
+ } catch (MalformedURLException e) {
+ log.error("Erro ao configurar PushGateway", e);
+ }
+ }
+ }
+
/*
* (non-Javadoc)
*
@@ -144,6 +172,7 @@ public void testStarted() {
log.error("Couldn't start http server", e);
}
+ this.configurePushGateway();
}
/*
diff --git a/src/main/java/com/github/johrstrom/listener/PushGateway.java b/src/main/java/com/github/johrstrom/listener/PushGateway.java
new file mode 100644
index 0000000..af61b54
--- /dev/null
+++ b/src/main/java/com/github/johrstrom/listener/PushGateway.java
@@ -0,0 +1,55 @@
+package com.github.johrstrom.listener;
+
+import com.github.johrstrom.collector.JMeterCollectorRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.LocalDateTime;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class PushGateway {
+
+ private static final Logger log = LoggerFactory.getLogger(PushGateway.class);
+
+ private final io.prometheus.client.exporter.PushGateway pg;
+ private final String jobName;
+ private final int interval;
+ private final ScheduledExecutorService scheduler;
+
+ public PushGateway(String hostName, String jobName, int interval) throws MalformedURLException {
+ log.info("Configurando PushGateway: Host={}, JobName={}", hostName, jobName);
+
+ URL url = new URL(hostName);
+ pg = new io.prometheus.client.exporter.PushGateway(url);
+ scheduler = Executors.newScheduledThreadPool(1);
+ this.jobName = jobName;
+ this.interval = interval;
+ }
+
+ public void start() {
+ log.info("Iniciando processo que envia métricas ao PushGateway em um intervalo de {} segundos", interval);
+ scheduler.scheduleAtFixedRate(this::send, 0, this.interval, TimeUnit.SECONDS);
+ }
+
+ private void send() {
+ try {
+ log.debug("Enviando as métricas para o PushGateway - {}", LocalDateTime.now());
+ pg.pushAdd(JMeterCollectorRegistry.getInstance(), jobName);
+ log.debug("Métricas enviadas para o PushGateway");
+ } catch (IOException e) {
+ log.error("Erro ao enviar as métricas para o PushGateway", e);
+ }
+ }
+
+ public void finish() {
+ this.send();
+ log.info("Finalizando processo que envia métricas ao PushGateway");
+ this.scheduler.shutdown();
+ }
+
+}
diff --git a/src/main/java/com/github/johrstrom/listener/gui/PrometheusListenerGui.java b/src/main/java/com/github/johrstrom/listener/gui/PrometheusListenerGui.java
index 6bcdaba..f3ca1c8 100644
--- a/src/main/java/com/github/johrstrom/listener/gui/PrometheusListenerGui.java
+++ b/src/main/java/com/github/johrstrom/listener/gui/PrometheusListenerGui.java
@@ -28,6 +28,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
@@ -49,6 +50,11 @@ public class PrometheusListenerGui extends AbstractListenerGui {
private ListenerCollectorTable table = new ListenerCollectorTable();
private Logger log = LoggerFactory.getLogger(PrometheusListenerGui.class);
+ private JCheckBox sendToPushGatewayCheckBox;
+ private JTextField jobNameField;
+ private JTextField pushGatewayHostField;
+ private JTextField intervalField;
+
public PrometheusListenerGui() {
super();
log.debug("making a new listener gui: {}", this.toString());
@@ -106,12 +112,26 @@ public void configure(TestElement ele) {
//ele.getName() == null ? this.setName(ele.getName()) : this.setName(getStaticLabel());;
this.setName(ele.getName() == null ? getStaticLabel() : ele.getName());
this.setComment(ele.getComment() == null ? "" : ele.getComment());
+
+
+ String jobName = ele.getPropertyAsString("jobName");
+ String pushGatewayHost = ele.getPropertyAsString("pushGatewayHost");
+ String interval = ele.getPropertyAsString("interval");
+ String sendToPushGateway = ele.getPropertyAsString("sendToPushGateway");
+
+ sendToPushGatewayCheckBox.setSelected("true".equals(sendToPushGateway));
+ jobNameField.setText(jobName);
+ pushGatewayHostField.setText(pushGatewayHost);
+ intervalField.setText(interval);
+ updatePushGatewayFieldsState();
}
@Override
public TestElement createTestElement() {
PrometheusListener listener = new PrometheusListener();
+ setPushGatewayProperties(listener);
+
listener.setProperty(TestElement.GUI_CLASS, PrometheusListenerGui.class.getName());
listener.setProperty(TestElement.TEST_CLASS, PrometheusListener.class.getName());
this.modifyTestElement(listener);
@@ -119,13 +139,84 @@ public TestElement createTestElement() {
return listener;
}
- private void init() {
- this.setLayout(new BorderLayout(0, 5));
- this.add(makeTitlePanel(), BorderLayout.NORTH);
- this.add(this.table, BorderLayout.CENTER);
- }
+ private void init() {
+ this.setLayout(new BorderLayout(0, 10)); // Aumentei o espaçamento vertical
+ this.add(makeTitlePanel(), BorderLayout.NORTH);
- @Override
+ sendToPushGatewayCheckBox = new JCheckBox("Enviar para Pushgateway?");
+ sendToPushGatewayCheckBox.addActionListener(e -> updatePushGatewayFieldsState());
+
+ jobNameField = new JTextField(20);
+ pushGatewayHostField = new JTextField(20);
+ intervalField = new JTextField(10);
+
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
+
+ JPanel pushGatewayPanel = new JPanel();
+ pushGatewayPanel.setLayout(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = new Insets(5, 5, 5, 5);
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.gridwidth = 2;
+ gbc.anchor = GridBagConstraints.WEST;
+ pushGatewayPanel.add(sendToPushGatewayCheckBox, gbc);
+
+ gbc.gridwidth = 1;
+
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.anchor = GridBagConstraints.WEST;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0;
+ pushGatewayPanel.add(new JLabel("Job Name:"), gbc);
+
+ gbc.gridx = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ pushGatewayPanel.add(jobNameField, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0;
+ pushGatewayPanel.add(new JLabel("Pushgateway Host:"), gbc);
+
+ gbc.gridx = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ pushGatewayPanel.add(pushGatewayHostField, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 3;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0;
+ pushGatewayPanel.add(new JLabel("Interval (em segundos):"), gbc);
+
+ gbc.gridx = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ pushGatewayPanel.add(intervalField, gbc);
+
+ mainPanel.add(pushGatewayPanel);
+ mainPanel.add(new JScrollPane(table));
+
+ add(mainPanel, BorderLayout.CENTER);
+
+ updatePushGatewayFieldsState();
+ }
+
+
+ private void updatePushGatewayFieldsState() {
+ boolean isEnabled = sendToPushGatewayCheckBox.isSelected();
+ jobNameField.setEnabled(isEnabled);
+ pushGatewayHostField.setEnabled(isEnabled);
+ intervalField.setEnabled(isEnabled);
+ }
+
+ @Override
public void modifyTestElement(TestElement ele) {
if (!(ele instanceof CollectorElement)) {
return;
@@ -138,12 +229,33 @@ public void modifyTestElement(TestElement ele) {
config.setName(this.getName());
config.setComment(this.getComment());
- }
- @Override
+ setPushGatewayProperties(ele);
+ }
+
+ private void setPushGatewayProperties(TestElement ele) {
+ ele.setProperty("sendToPushGateway", sendToPushGatewayCheckBox.isSelected());
+ if (sendToPushGatewayCheckBox.isSelected()) {
+ ele.setProperty("jobName", jobNameField.getText());
+ ele.setProperty("pushGatewayHost", pushGatewayHostField.getText());
+ ele.setProperty("interval", intervalField.getText());
+ } else {
+ ele.setProperty("jobName", "");
+ ele.setProperty("pushGatewayHost", "");
+ ele.setProperty("interval", "");
+ }
+ }
+
+ @Override
public void clearGui() {
super.clearGui();
this.table.clearModelData();
+
+ jobNameField.setText("");
+ pushGatewayHostField.setText("");
+ intervalField.setText("");
+ sendToPushGatewayCheckBox.setSelected(false);
+ updatePushGatewayFieldsState();
}