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/516 add ignored metrics regexp option to ignore specific metrics based on regexp #542

Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
- Metrics from [Metrics-plugin](https://github.com/jenkinsci/metrics-plugin)
- Metrics from this plugin. Refer [Prometheus-plugin](docs/metrics/index.md)

## Configuring the plugin

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 1; Actual: 0; Below Warning

Expected: 1; Actual: 0; Below
You can find some examples in this documentation [Configuring Plugin](docs/configuration/configuration.md)

## Environment variables

Expand Down
18 changes: 18 additions & 0 deletions docs/configuration/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Plugin configuration
Fixed Show fixed Hide fixed

This page is under construction.

## Disable Metrics (since v2.3.0)

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 1; Actual: 0; Below Warning documentation

Expected: 1; Actual: 0; Below
Sometimes you don't need all metrics in your prometheus endpoint which this plugin provides.

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 80; Actual: 93 Warning documentation

Expected: 80; Actual: 93

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 0 or 2; Actual: 1 Warning documentation

Expected: 0 or 2; Actual: 1
You can disable certain metrics. These metrics are not being collected by the plugin and therefore not added in the

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 80; Actual: 116 Warning documentation

Expected: 80; Actual: 116

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 0 or 2; Actual: 1 Warning documentation

Expected: 0 or 2; Actual: 1
prometheus endpoint.
A
![img.png](img/disabled_metrics.png)

### Regex Entry

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 1; Actual: 0; Below Warning documentation

Expected: 1; Actual: 0; Below
A Regex entry can be used to disable a group of metrics. E.g. if you want to disable everything with

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 0 or 2; Actual: 1 Warning documentation

Expected: 0 or 2; Actual: 1

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 80; Actual: 101 Warning documentation

Expected: 80; Actual: 101
default_jenkins_disk.*

### Fully qualified Name Entry

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 1; Actual: 0; Below Warning documentation

Expected: 1; Actual: 0; Below
If you want to disable certain individual entries you can do it with this entry. The value should be the same

Check warning

Code scanning / Markdownlint (reported by Codacy)

Expected: 80; Actual: 109 Warning documentation

Expected: 80; Actual: 109
as you can see it in the prometheus endpoint. It's case-insensitive.
Binary file added docs/configuration/img/disabled_metrics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@

import com.cloudbees.simplediskusage.DiskItem;
import com.cloudbees.simplediskusage.JobDiskItem;
import hudson.model.LoadStatistics;
import io.prometheus.client.Collector;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.prometheus.collectors.CollectorFactory;
import org.jenkinsci.plugins.prometheus.collectors.CollectorType;
import org.jenkinsci.plugins.prometheus.collectors.MetricCollector;
import org.jenkinsci.plugins.prometheus.collectors.disk.DiskUsageBytesGauge;
import org.jenkinsci.plugins.prometheus.collectors.disk.FileStoreAvailableGauge;
import org.jenkinsci.plugins.prometheus.collectors.disk.FileStoreCapacityGauge;
import org.jenkinsci.plugins.prometheus.collectors.disk.JobUsageBytesGauge;
import org.jenkinsci.plugins.prometheus.config.PrometheusConfiguration;
import org.jenkinsci.plugins.prometheus.util.ConfigurationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -79,8 +73,8 @@ private static List<MetricFamilySamples> collectDiskUsage() throws IOException {
});

List<MetricCollector<FileStore, ? extends Collector>> fileStoreCollectors = new ArrayList<>();
fileStoreCollectors.add(factory.createFileStoreCollector(CollectorType.FILE_STORE_CAPACITY_GAUGE,new String[]{"file_store"} ));
fileStoreCollectors.add(factory.createFileStoreCollector(CollectorType.FILE_STORE_AVAILABLE_GAUGE ,new String[]{"file_store"} ));
fileStoreCollectors.add(factory.createFileStoreCollector(CollectorType.FILE_STORE_CAPACITY_GAUGE, new String[]{"file_store"}));
fileStoreCollectors.add(factory.createFileStoreCollector(CollectorType.FILE_STORE_AVAILABLE_GAUGE, new String[]{"file_store"}));

usedFileStores.forEach(store -> {
final String labelValue = toLabelValue(Optional.of(store));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
public class ExecutorCollector extends Collector {

private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorCollector.class);

@Override
public List<MetricFamilySamples> collect() {
LOGGER.debug("Collecting executor metrics for prometheus");
Expand All @@ -41,7 +42,7 @@ public List<MetricFamilySamples> collect() {

Label[] labels = Jenkins.get().getLabels().toArray(new Label[0]);
for (Label l : labels) {
collectors.forEach(c -> c.calculateMetric(l.loadStatistics.computeSnapshot(), new String[] {l.getDisplayName()}));
collectors.forEach(c -> c.calculateMetric(l.loadStatistics.computeSnapshot(), new String[]{l.getDisplayName()}));
}

return collectors.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import org.jenkinsci.plugins.prometheus.collectors.CollectorFactory;
import org.jenkinsci.plugins.prometheus.collectors.CollectorType;
import org.jenkinsci.plugins.prometheus.collectors.MetricCollector;
import org.jenkinsci.plugins.prometheus.config.PrometheusConfiguration;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -23,7 +22,7 @@ public List<MetricFamilySamples> collect() {
collectors.add(factory.createJenkinsCollector(CollectorType.JENKINS_VERSION_INFO_GAUGE, new String[]{}));
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[]{}));
collectors.add(factory.createJenkinsCollector(CollectorType.NODES_ONLINE_GAUGE, new String[]{"node"}));

collectors.forEach(c -> c.calculateMetric(Jenkins.get(), new String[]{}));

Expand Down
52 changes: 25 additions & 27 deletions src/main/java/org/jenkinsci/plugins/prometheus/JobCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import org.jenkinsci.plugins.prometheus.collectors.CollectorFactory;
import org.jenkinsci.plugins.prometheus.collectors.CollectorType;
import org.jenkinsci.plugins.prometheus.collectors.MetricCollector;
import org.jenkinsci.plugins.prometheus.collectors.builds.BuildCollectorFactory;
import org.jenkinsci.plugins.prometheus.collectors.jobs.JobCollectorFactory;
import org.jenkinsci.plugins.prometheus.config.PrometheusConfiguration;
import org.jenkinsci.plugins.prometheus.util.Jobs;
import org.jenkinsci.plugins.prometheus.util.Runs;
Expand All @@ -27,24 +25,24 @@
private static final String NOT_AVAILABLE = "NA";
private static final String UNDEFINED = "UNDEFINED";

private MetricCollector<Run, ? extends Collector> summary;
private MetricCollector<Run, ? extends Collector> jobSuccessCount;
private MetricCollector<Run, ? extends Collector> jobFailedCount;
private MetricCollector<Job, ? extends Collector> jobHealthScoreGauge;
private MetricCollector<Job, ? extends Collector> nbBuildsGauge;
private MetricCollector<Job, ? extends Collector> buildDiscardGauge;
private MetricCollector<Job, ? extends Collector> currentRunDurationGauge;
private MetricCollector<Run<?, ?>, ? extends Collector> summary;
private MetricCollector<Run<?, ?>, ? extends Collector> jobSuccessCount;
private MetricCollector<Run<?, ?>, ? extends Collector> jobFailedCount;
private MetricCollector<Job<?, ?>, ? extends Collector> jobHealthScoreGauge;
private MetricCollector<Job<?, ?>, ? extends Collector> nbBuildsGauge;
private MetricCollector<Job<?, ?>, ? extends Collector> buildDiscardGauge;
private MetricCollector<Job<?, ?>, ? extends Collector> currentRunDurationGauge;

private static class BuildMetrics {

public MetricCollector<Run, ? extends Collector> jobBuildResultOrdinal;
public MetricCollector<Run, ? extends Collector> jobBuildResult;
public MetricCollector<Run, ? extends Collector> jobBuildStartMillis;
public MetricCollector<Run, ? extends Collector> jobBuildDuration;
public MetricCollector<Run, ? extends Collector> stageSummary;
public MetricCollector<Run, ? extends Collector> jobBuildTestsTotal;
public MetricCollector<Run, ? extends Collector> jobBuildTestsSkipped;
public MetricCollector<Run, ? extends Collector> jobBuildTestsFailing;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildResultOrdinal;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildResult;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildStartMillis;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildDuration;
public MetricCollector<Run<?, ?>, ? extends Collector> stageSummary;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildTestsTotal;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildTestsSkipped;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildTestsFailing;

private final String buildPrefix;

Expand Down Expand Up @@ -176,12 +174,12 @@

private void addSamples(List<MetricFamilySamples> allSamples, List<MetricFamilySamples> newSamples, String logMessage) {
for (MetricFamilySamples metricFamilySample : newSamples) {
int sampleCount = metricFamilySample.samples.size();
if (sampleCount > 0) {
logger.debug(logMessage, sampleCount, metricFamilySample.name);
allSamples.addAll(newSamples);
}
int sampleCount = metricFamilySample.samples.size();
if (sampleCount > 0) {
logger.debug(logMessage, sampleCount, metricFamilySample.name);
allSamples.addAll(newSamples);
}
}
}

private void addSamples(List<MetricFamilySamples> allSamples, BuildMetrics buildMetrics) {
Expand All @@ -195,7 +193,7 @@
addSamples(allSamples, buildMetrics.stageSummary.collect(), "Adding [{}] samples from summary ({})");
}

protected void appendJobMetrics(Job job) {
protected void appendJobMetrics(Job<?, ?> job) {
Dismissed Show dismissed Hide dismissed
boolean isAppendParamLabel = PrometheusConfiguration.get().isAppendParamLabel();
boolean isAppendStatusLabel = PrometheusConfiguration.get().isAppendStatusLabel();
boolean isPerBuildMetrics = PrometheusConfiguration.get().isPerBuildMetrics();
Expand All @@ -208,7 +206,7 @@
}
String[] baseLabelValueArray = {job.getFullName(), repoName, String.valueOf(job.isBuildable())};

Run lastBuild = job.getLastBuild();
Run<?, ?> lastBuild = job.getLastBuild();

Check warning on line 209 in src/main/java/org/jenkinsci/plugins/prometheus/JobCollector.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 209 is not covered by tests
// Never built
if (null == lastBuild) {
logger.debug("job [{}] never built", job.getFullName());
Expand All @@ -221,7 +219,7 @@
currentRunDurationGauge.calculateMetric(job, baseLabelValueArray);
processRun(job, lastBuild, baseLabelValueArray, lastBuildMetrics);

Run run = lastBuild;
Run<?, ?> run = lastBuild;

Check warning on line 222 in src/main/java/org/jenkinsci/plugins/prometheus/JobCollector.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 222 is not covered by tests
while (run != null) {
logger.debug("getting metrics for run [{}] from job [{}], include per run metrics [{}]", run.getNumber(), job.getName(), isPerBuildMetrics);
if (Runs.includeBuildInMetrics(run)) {
Expand All @@ -231,7 +229,7 @@
String[] labelValueArray = baseLabelValueArray;

if (isAppendParamLabel) {
String params = Runs.getBuildParameters(run).entrySet().stream().map(e -> "" + e.getKey() + "=" + e.getValue()).collect(Collectors.joining(";"));
String params = Runs.getBuildParameters(run).entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(";"));

Check warning on line 232 in src/main/java/org/jenkinsci/plugins/prometheus/JobCollector.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 232 is not covered by tests
labelValueArray = Arrays.copyOf(labelValueArray, labelValueArray.length + 1);
labelValueArray[labelValueArray.length - 1] = params;
}
Expand Down Expand Up @@ -269,7 +267,7 @@
}
}

private void processRun(Job job, Run run, String[] buildLabelValueArray, BuildMetrics buildMetrics) {
private void processRun(Job<?, ?> job, Run<?, ?> run, String[] buildLabelValueArray, BuildMetrics buildMetrics) {
logger.debug("Processing run [{}] from job [{}]", run.getNumber(), job.getName());
buildMetrics.jobBuildResultOrdinal.calculateMetric(run, buildLabelValueArray);
buildMetrics.jobBuildResult.calculateMetric(run, buildLabelValueArray);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jenkinsci.plugins.prometheus.collectors;

import org.jenkinsci.plugins.prometheus.config.disabledmetrics.MetricStatusChecker;
import org.jenkinsci.plugins.prometheus.util.ConfigurationUtils;

public abstract class BaseCollectorFactory {
Expand All @@ -12,8 +13,12 @@
subsystem = ConfigurationUtils.getSubSystem();
}

protected boolean isEnabledViaConfig(CollectorType type) {
// prepare for disable via config
return true;

protected MetricCollector saveBuildCollector(MetricCollector collector) {
String fullName = namespace + "_" + subsystem + "_" + collector.calculateName();
if (MetricStatusChecker.isEnabled(fullName)) {

Check warning on line 19 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/BaseCollectorFactory.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 19 is only partially covered, one branch is missing
return collector;
}
return new NoOpMetricCollector<>();

Check warning on line 22 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/BaseCollectorFactory.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 22 is not covered by tests
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package org.jenkinsci.plugins.prometheus.collectors;

import io.prometheus.client.Collector;
import io.prometheus.client.SimpleCollector;

import java.util.List;

public abstract class BaseMetricCollector<T, I extends Collector> implements MetricCollector<T, I> {
public abstract class BaseMetricCollector<T, I extends SimpleCollector<?>> implements MetricCollector<T, I> {

protected final static String SEPARATOR = "_";

protected final String[] labelNames;
protected final String namespace;
protected final String subsystem;
protected final String namePrefix;

protected I collector;

protected BaseMetricCollector(String[] labelNames, String namespace, String subsystem, String namePrefix) {
Expand All @@ -31,14 +31,38 @@ protected BaseMetricCollector(String[] labelNames, String namespace, String subs
collector = initCollector();
}

protected abstract I initCollector();
/**
* @return - the name of the collector without subsystem, namespace, prefix
*/
protected abstract CollectorType getCollectorType();

/**
* @return - the help text which should be displayed
*/
protected abstract String getHelpText();

/**
* @return - builder object of the type of collector
*/
protected abstract SimpleCollector.Builder<?, I> getCollectorBuilder();

protected I initCollector() {
return getCollectorBuilder()
.name(calculateName())
.subsystem(subsystem)
.namespace(namespace)
.labelNames(labelNames)
.help(getHelpText())
.create();
}

@Override
public List<Collector.MetricFamilySamples> collect() {
return collector.collect();
}

protected String calculateName(String name) {
public String calculateName() {
String name = getCollectorType().getName();
StringBuilder sb = new StringBuilder();
if (isBaseNameSet()) {
sb.append(getBaseName()).append(SEPARATOR);
Expand All @@ -62,4 +86,5 @@ protected String getBaseName() {
return "";
}

public abstract void calculateMetric(T jenkinsObject, String[] labelValues);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ public CollectorFactory() {
diskCollectorFactory = new DiskCollectorFactory();
}

public MetricCollector<Run, ? extends Collector> createRunCollector(CollectorType type, String[] labelNames, String prefix) {
public MetricCollector<Run<?, ?>, ? extends Collector> createRunCollector(CollectorType type, String[] labelNames, String prefix) {
return buildCollectorFactory.createCollector(type, labelNames, prefix);
}

public MetricCollector<Job, ? extends Collector> createJobCollector(CollectorType type, String[] labelNames) {
public MetricCollector<Job<?, ?>, ? extends Collector> createJobCollector(CollectorType type, String[] labelNames) {
return jobCollectorFactory.createCollector(type, labelNames);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,27 @@
/**
* Implementations of this interface shall be able to construct and calculate any subclass of
* {@link io.prometheus.client.SimpleCollector}
*
* @param <T> - any subclass of {@link io.prometheus.client.SimpleCollector}
*/
public interface MetricCollector<T, I extends Collector> {

/**
* This method contains the logic to calculate a metric value based on the given Jenkins object (e.g. Job, Run,...)
*
* @param jenkinsObject - Examples: {@link hudson.model.Job}, {@link hudson.model.Run}
* @param labelValues - The label values for the calculation
* @param labelValues - The label values for the calculation
*/
void calculateMetric(T jenkinsObject, String[] labelValues);

/**
* Calling this method basically calls I.collect()
*/
List<I.MetricFamilySamples> collect();

/**
* Calling this method will return the resulting name of the metric with base name and prefix
* @return the full name of the collector
*/
String calculateName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public class NoOpMetricCollector<T, I extends Collector> implements MetricCollector<T, I> {
@Override
public void calculateMetric(Object jenkinsObject, String[] labelValues) {
public void calculateMetric(T jenkinsObject, String[] labelValues) {
// do nothing
}

Expand All @@ -16,4 +16,9 @@
// do nothing
return new ArrayList<>();
}

@Override
public String calculateName() {
return "";

Check warning on line 22 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/NoOpMetricCollector.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 22 is not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import hudson.model.Run;
import hudson.tasks.test.AbstractTestResultAction;
import io.prometheus.client.Collector;
import io.prometheus.client.SimpleCollector;
import org.jenkinsci.plugins.prometheus.collectors.builds.BuildsMetricCollector;
import org.jenkinsci.plugins.prometheus.config.PrometheusConfiguration;

public abstract class TestBasedMetricCollector<T, I extends Collector> extends BuildsMetricCollector<T, I> {
public abstract class TestBasedMetricCollector<T, I extends SimpleCollector<?>> extends BuildsMetricCollector<T, I> {

public TestBasedMetricCollector(String[] labelNames, String namespace, String subsystem, String namePrefix) {
super(labelNames, namespace, subsystem, namePrefix);
Expand Down
Loading
Loading