Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/583 offline nodes metrics #584

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum CollectorType {
JENKINS_UPTIME_GAUGE("uptime"),
JENKINS_VERSION_INFO_GAUGE("version"),
NODES_ONLINE_GAUGE("nodes_online"),
NODES_OFFLINE_GAUGE("nodes_offline"),
BUILD_DURATION_GAUGE("build_duration_milliseconds"),
BUILD_DURATION_SUMMARY("duration_milliseconds_summary"),
BUILD_FAILED_COUNTER("failed_build_count"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@
case JENKINS_UP_GAUGE:
return saveBuildCollector(new JenkinsUpGauge(labelNames, namespace, subsystem));
case NODES_ONLINE_GAUGE:
if (!isNodeOnlineGaugeEnabled()) {
if (!isNodeStatusGaugeEnabled()) {
return new NoOpMetricCollector<>();
}
return saveBuildCollector(new NodesOnlineGauge(labelNames, namespace, subsystem));
case NODES_OFFLINE_GAUGE:
if (!isNodeStatusGaugeEnabled()) {
return new NoOpMetricCollector<>();
}
return saveBuildCollector(new NodesOfflineGauge(labelNames, namespace, subsystem));

Check warning on line 33 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/JenkinsCollectorFactory.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 30-33 are not covered by tests
case JENKINS_UPTIME_GAUGE:
return saveBuildCollector(new JenkinsUptimeGauge(labelNames, namespace, subsystem));
case JENKINS_VERSION_INFO_GAUGE:
Expand All @@ -35,7 +40,7 @@
}
}

private boolean isNodeOnlineGaugeEnabled() {
private boolean isNodeStatusGaugeEnabled() {
return PrometheusConfiguration.get().isCollectNodeStatus();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.jenkinsci.plugins.prometheus.collectors.jenkins;

import hudson.model.Computer;
import hudson.model.Node;
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 NodesOfflineGauge extends BaseMetricCollector<Jenkins, Gauge> {

NodesOfflineGauge(String[] labelNames, String namespace, String subsystem) {
super(labelNames, namespace, subsystem);
}

@Override
protected CollectorType getCollectorType() {
return CollectorType.NODES_OFFLINE_GAUGE;
}

@Override
protected String getHelpText() {
return "Jenkins nodes offline status";
}

@Override
protected SimpleCollector.Builder<?, Gauge> getCollectorBuilder() {
return Gauge.build();
}

@Override
public void calculateMetric(Jenkins jenkinsObject, String[] labelValues) {
if (jenkinsObject == null) {

Check warning on line 34 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/NodesOfflineGauge.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 34 is only partially covered, one branch is missing
return;

Check warning on line 35 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/jenkins/NodesOfflineGauge.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 35 is not covered by tests
}
for (Node node : jenkinsObject.getNodes()) {
//Check whether the node is online or offline
Computer comp = node.toComputer();
if (comp == null) {
continue;
}

if (comp.isOffline()) { // https://javadoc.jenkins.io/hudson/model/Computer.html
this.collector.labels(node.getNodeName()).set(1);
} else {
this.collector.labels(node.getNodeName()).set(0);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ public void testCollectResult() throws Exception {

static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.jenkinsci.plugins.prometheus.collectors.jenkins;

import hudson.model.Computer;
import hudson.model.Node;
import io.prometheus.client.Collector;
import jenkins.model.Jenkins;

import org.jenkinsci.plugins.prometheus.collectors.testutils.MockedJenkinsTest;
import org.junit.Test;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class NodesOfflineGaugeTest extends MockedJenkinsTest {

@Test
public void testCollectResult() throws Exception {

Check notice

Code scanning / Pmd (reported by Codacy)

JUnit tests should include assert() or fail() Note test

JUnit tests should include assert() or fail()


setFinalStatic(Jenkins.class.getDeclaredField("VERSION"), "123");

List<Node> nodes = new ArrayList<>();
nodes.add(mockNode("node1", true));
nodes.add(mockNode("node2", false));
nodes.add(mockNode("node3", true));
nodes.add(mockNode("nullNode", false));
when(mock.getNodes()).thenReturn(nodes);

NodesOfflineGauge sut = new NodesOfflineGauge(new String[]{"node"}, getNamespace(), getSubSystem());
sut.calculateMetric(mock, getLabelValues());

List<Collector.MetricFamilySamples> collect = sut.collect();

validateMetricFamilySampleListSize(collect, 1);

Collector.MetricFamilySamples samples = collect.get(0);
// we pass 4 nodes but we only get 3 -> there's a node with null computer
validateMetricFamilySampleSize(samples, 3);
for (Collector.MetricFamilySamples.Sample sample : samples.samples) {
System.out.println(sample);
if (sample.labelValues.contains("node1")) {
validateValue(sample, 1.0);
}
if (sample.labelValues.contains("node2")) {
validateValue(sample, 0.0);
}
if (sample.labelValues.contains("node3")) {
validateValue(sample, 1.0);
}
}
System.out.println(samples);
validateNames(samples, new String[]{"default_jenkins_nodes_offline"});
}

private Node mockNode(String nodeName, boolean isOnline) {
Node nodeMock = mock(Node.class);
if (!"nullNode".equalsIgnoreCase(nodeName)) {
Computer computerMock = mock(Computer.class);
when(computerMock.isOffline()).thenReturn(isOnline);
when(nodeMock.toComputer()).thenReturn(computerMock);
}
when(nodeMock.getNodeName()).thenReturn(nodeName);
return nodeMock;
}

static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);

Check notice

Code scanning / Pmd (reported by Codacy)

You should not modify visibility of constructors, methods or fields using setAccessible() Note test

You should not modify visibility of constructors, methods or fields using setAccessible()
field.set(null, newValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ private Node mockNode(String nodeName, boolean isOnline) {

static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}
Loading