From 394bf2cc6a5da4e7151bd7bc448fc7b59a6185ca Mon Sep 17 00:00:00 2001 From: "gaspar.barancelli" Date: Tue, 12 Aug 2025 17:44:47 -0300 Subject: [PATCH] =?UTF-8?q?configura=C3=A7=C3=A3o=20para=20fazer=20envio?= =?UTF-8?q?=20das=20metricas=20ao=20PushGateway?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 +- .../listener/PrometheusListener.java | 29 ++++ .../johrstrom/listener/PushGateway.java | 55 ++++++++ .../listener/gui/PrometheusListenerGui.java | 128 ++++++++++++++++-- 4 files changed, 210 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/github/johrstrom/listener/PushGateway.java 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(); }