From fb82aaa68572ec0e2d06bb4afa7e65048e9dddec Mon Sep 17 00:00:00 2001 From: Shawn Stafford Date: Fri, 26 Jul 2024 13:39:52 -0400 Subject: [PATCH] New metric indicating whether Jenkins is in quietdown mode This metric exposes the Jenkins isQuietingDown status as a gauge. When Jenkins is in quiet mode, the new metric will represent this as a '1', otherwise the value will be '0' Exposing this metric allows Prometheus to determine whether Jenkins is in quiet mode. This can be useful in cases where an alert should be triggered if quiet mode has been enabled for too long or falls outside of a maintenance window. Fixes issue #686 --- docs/metrics/index.md | 1 + .../prometheus/JenkinsStatusCollector.java | 1 + .../prometheus/collectors/CollectorType.java | 1 + .../jenkins/JenkinsCollectorFactory.java | 2 + .../jenkins/JenkinsQuietDownGauge.java | 37 ++++++++++ .../jenkins/JenkinsQuietDownGaugeTest.java | 71 +++++++++++++++++++ 6 files changed, 113 insertions(+) create mode 100644 src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGauge.java create mode 100644 src/test/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGaugeTest.java diff --git a/docs/metrics/index.md b/docs/metrics/index.md index ae7dead44..31c55ced9 100644 --- a/docs/metrics/index.md +++ b/docs/metrics/index.md @@ -40,6 +40,7 @@ Required Plugin: | default_jenkins_up | Shows if jenkins ready to receive requests | gauge | | default_jenkins_uptime | Shows time since Jenkins was initialized | gauge | | default_jenkins_nodes_online | Shows Nodes online status | gauge | +| default_jenkins_quietdown | Shows if jenkins is in quiet mode | gauge | ## JobCollector diff --git a/src/main/java/org/jenkinsci/plugins/prometheus/JenkinsStatusCollector.java b/src/main/java/org/jenkinsci/plugins/prometheus/JenkinsStatusCollector.java index aec8d657b..258429939 100644 --- a/src/main/java/org/jenkinsci/plugins/prometheus/JenkinsStatusCollector.java +++ b/src/main/java/org/jenkinsci/plugins/prometheus/JenkinsStatusCollector.java @@ -23,6 +23,7 @@ public List collect() { collectors.add(factory.createJenkinsCollector(CollectorType.JENKINS_UP_GAUGE, new String[]{})); collectors.add(factory.createJenkinsCollector(CollectorType.JENKINS_UPTIME_GAUGE, new String[]{})); collectors.add(factory.createJenkinsCollector(CollectorType.NODES_ONLINE_GAUGE, new String[]{"node"})); + collectors.add(factory.createJenkinsCollector(CollectorType.JENKINS_QUIETDOWN_GAUGE, new String[]{})); collectors.forEach(c -> c.calculateMetric(jenkins, new String[]{})); diff --git a/src/main/java/org/jenkinsci/plugins/prometheus/collectors/CollectorType.java b/src/main/java/org/jenkinsci/plugins/prometheus/collectors/CollectorType.java index fdbe2e390..80309e717 100644 --- a/src/main/java/org/jenkinsci/plugins/prometheus/collectors/CollectorType.java +++ b/src/main/java/org/jenkinsci/plugins/prometheus/collectors/CollectorType.java @@ -5,6 +5,7 @@ public enum CollectorType { JENKINS_UP_GAUGE("up"), JENKINS_UPTIME_GAUGE("uptime"), JENKINS_VERSION_INFO_GAUGE("version"), + JENKINS_QUIETDOWN_GAUGE("quietdown"), NODES_ONLINE_GAUGE("nodes_online"), BUILD_DURATION_GAUGE("build_duration_milliseconds"), BUILD_LOGFILE_SIZE_GAUGE("build_logfile_size_bytes"), diff --git a/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsCollectorFactory.java b/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsCollectorFactory.java index f568130b8..21491e467 100644 --- a/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsCollectorFactory.java +++ b/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsCollectorFactory.java @@ -17,6 +17,8 @@ public class JenkinsCollectorFactory extends BaseCollectorFactory { switch (type) { case JENKINS_UP_GAUGE: return saveBuildCollector(new JenkinsUpGauge(labelNames, namespace, subsystem)); + case JENKINS_QUIETDOWN_GAUGE: + return saveBuildCollector(new JenkinsQuietDownGauge(labelNames, namespace, subsystem)); case NODES_ONLINE_GAUGE: if (!isNodeOnlineGaugeEnabled()) { return new NoOpMetricCollector<>(); diff --git a/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGauge.java b/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGauge.java new file mode 100644 index 000000000..e22f42ba6 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGauge.java @@ -0,0 +1,37 @@ +package org.jenkinsci.plugins.prometheus.collectors.jenkins; + +import io.prometheus.client.Gauge; +import io.prometheus.client.SimpleCollector; +import jenkins.model.Jenkins; +import org.jenkinsci.plugins.prometheus.collectors.BaseMetricCollector; +import org.jenkinsci.plugins.prometheus.collectors.CollectorType; + +public class JenkinsQuietDownGauge extends BaseMetricCollector { + + JenkinsQuietDownGauge(String[] labelNames, String namespace, String subsystem) { + super(labelNames, namespace, subsystem); + } + + @Override + protected CollectorType getCollectorType() { + return CollectorType.JENKINS_QUIETDOWN_GAUGE; + } + + @Override + protected String getHelpText() { + return "Is Jenkins in quiet mode"; + } + + @Override + protected SimpleCollector.Builder getCollectorBuilder() { + return Gauge.build(); + } + + @Override + public void calculateMetric(Jenkins jenkinsObject, String[] labelValues) { + if (jenkinsObject == null) { + return; + } + this.collector.set(jenkinsObject.isQuietingDown() ? 1 : 0); + } +} diff --git a/src/test/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGaugeTest.java b/src/test/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGaugeTest.java new file mode 100644 index 000000000..676075cc6 --- /dev/null +++ b/src/test/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsQuietDownGaugeTest.java @@ -0,0 +1,71 @@ +package org.jenkinsci.plugins.prometheus.collectors.jenkins; + +import io.prometheus.client.Collector; +import org.jenkinsci.plugins.prometheus.collectors.testutils.MockedJenkinsTest; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.mockito.Mockito.when; + +public class JenkinsQuietDownGaugeTest extends MockedJenkinsTest { + + + @Test + public void testCollectResultForJenkinsQuietModeEnabled() { + + when(mock.isQuietingDown()).thenReturn(true); + + JenkinsQuietDownGauge sut = new JenkinsQuietDownGauge(new String[]{}, getNamespace(), getSubSystem()); + sut.calculateMetric(mock, getLabelValues()); + + List collect = sut.collect(); + + validateMetricFamilySampleListSize(collect, 1); + + Collector.MetricFamilySamples samples = collect.get(0); + + validateNames(samples, new String[]{"default_jenkins_quietdown"}); + validateMetricFamilySampleSize(samples, 1); + validateHelp(samples, "Is Jenkins in quiet mode"); + validateValue(samples, 0, 1.0); + } + + + @Test + public void testCollectResultForJenkinsQuietModeDisabled() { + + when(mock.isQuietingDown()).thenReturn(false); + + JenkinsQuietDownGauge sut = new JenkinsQuietDownGauge(new String[]{}, getNamespace(), getSubSystem()); + sut.calculateMetric(mock, getLabelValues()); + + List collect = sut.collect(); + + validateMetricFamilySampleListSize(collect, 1); + + Collector.MetricFamilySamples samples = collect.get(0); + + validateNames(samples, new String[]{"default_jenkins_quietdown"}); + validateMetricFamilySampleSize(samples, 1); + validateHelp(samples, "Is Jenkins in quiet mode"); + validateValue(samples, 0, 0.0); + } + + @Test + public void testJenkinsIsNull() { + JenkinsQuietDownGauge sut = new JenkinsQuietDownGauge(new String[]{}, getNamespace(), getSubSystem()); + sut.calculateMetric(null, getLabelValues()); + + List collect = sut.collect(); + + validateMetricFamilySampleListSize(collect, 1); + + Collector.MetricFamilySamples samples = collect.get(0); + + validateNames(samples, new String[]{"default_jenkins_quietdown"}); + validateMetricFamilySampleSize(samples, 1); + validateHelp(samples, "Is Jenkins in quiet mode"); + validateValue(samples, 0, 0.0); + } +} \ No newline at end of file