Skip to content

Commit

Permalink
New Metrics which shows the Stage ordinal (#704)
Browse files Browse the repository at this point in the history
* Stage ordinal

* Docs and help

---------

Co-authored-by: Waschndolos <[email protected]>
  • Loading branch information
Waschndolos and Waschndolos authored Oct 18, 2024
1 parent 8838bb2 commit 3d25609
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/metrics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ specific metrics over the configuration page:
| default_jenkins_builds_last_build_tests_total | Number of total tests during the last build | gauge |
| default_jenkins_builds_last_last_build_tests_skipped | Number of skipped tests during the last build | gauge |
| default_jenkins_builds_last_build_tests_failing | Number of failing tests during the last build | gauge |
| default_jenkins_builds_last_stage_result_ordinal | Status ordinal of a stage in a pipeline (0=NOT_EXECUTED,1=ABORTED,2=SUCCESS,3=IN_PROGRESS,4=PAUSED_PENDING_INPUT,5=FAILED,6=UNSTABLE) | gauge |
| default_jenkins_builds_last_stage_duration_milliseconds_summary | Summary of Jenkins build times by Job and Stage in the last build | summary |
| default_jenkins_builds_last_logfile_size_bytes | Gauge which shows the log file size in bytes. | gauge |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ private static class BuildMetrics {
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildStartMillis;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildDuration;
public MetricCollector<Run<?, ?>, ? extends Collector> stageSummary;
public MetricCollector<Run<?, ?>, ? extends Collector> stageBuildResultOrdinal;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildTestsTotal;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildTestsSkipped;
public MetricCollector<Run<?, ?>, ? extends Collector> jobBuildTestsFailing;
Expand All @@ -65,6 +66,7 @@ public void initCollectors(String[] labelNameArray) {
this.jobBuildTestsSkipped = factory.createRunCollector(CollectorType.SKIPPED_TESTS_GAUGE, labelNameArray, buildPrefix);
this.jobBuildTestsFailing = factory.createRunCollector(CollectorType.FAILED_TESTS_GAUGE, labelNameArray, buildPrefix);
this.stageSummary = factory.createRunCollector(CollectorType.STAGE_SUMMARY, ArrayUtils.add(labelNameArray, "stage"), buildPrefix);
this.stageBuildResultOrdinal = factory.createRunCollector(CollectorType.STAGE_BUILDRESULT_ORDINAL, ArrayUtils.add(labelNameArray, "stage"), buildPrefix);
this.jobBuildLikelyStuck = factory.createRunCollector(CollectorType.BUILD_LIKELY_STUCK_GAUGE, labelNameArray, buildPrefix);
this.buildLogFileSizeGauge = factory.createRunCollector(CollectorType.BUILD_LOGFILE_SIZE_GAUGE, labelNameArray, buildPrefix);
}
Expand Down Expand Up @@ -214,6 +216,7 @@ private void addSamples(List<MetricFamilySamples> allSamples, BuildMetrics build
addSamples(allSamples, buildMetrics.jobBuildTestsFailing.collect(), "Adding [{}] samples from gauge ({})");
addSamples(allSamples, buildMetrics.jobBuildLikelyStuck.collect(), "Adding [{}] samples from gauge ({})");
addSamples(allSamples, buildMetrics.stageSummary.collect(), "Adding [{}] samples from summary ({})");
addSamples(allSamples, buildMetrics.stageBuildResultOrdinal.collect(), "Adding [{}] samples from summary ({})");
addSamples(allSamples, buildMetrics.buildLogFileSizeGauge.collect(), "Adding [{}] samples from summary ({})");
}

Expand Down Expand Up @@ -264,6 +267,7 @@ private void processRun(Job<?, ?> job, Run<?, ?> run, String[] buildLabelValueAr
buildMetrics.jobBuildDuration.calculateMetric(run, buildLabelValueArray);
// Label values are calculated within stageSummary so we pass null here.
buildMetrics.stageSummary.calculateMetric(run, buildLabelValueArray);
buildMetrics.stageBuildResultOrdinal.calculateMetric(run, buildLabelValueArray);

Check warning on line 270 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 270 is not covered by tests
buildMetrics.jobBuildTestsTotal.calculateMetric(run, buildLabelValueArray);
buildMetrics.jobBuildTestsSkipped.calculateMetric(run, buildLabelValueArray);
buildMetrics.jobBuildTestsFailing.calculateMetric(run, buildLabelValueArray);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public enum CollectorType {
FAILED_TESTS_GAUGE("build_tests_failing"),
SKIPPED_TESTS_GAUGE("last_build_tests_skipped"),
STAGE_SUMMARY("stage_duration_milliseconds_summary"),
STAGE_BUILDRESULT_ORDINAL("stage_result_ordinal"),
TOTAL_TESTS_GAUGE("build_tests_total"),
HEALTH_SCORE_GAUGE("health_score"),
NB_BUILDS_GAUGE("available_builds_count"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class BuildCollectorFactory extends BaseCollectorFactory {
return saveBuildCollector(new SkippedTestsGauge(labelNames, namespace, subsystem, prefix));
case STAGE_SUMMARY:
return saveBuildCollector(new StageSummary(labelNames, namespace, subsystem, prefix));
case STAGE_BUILDRESULT_ORDINAL:
return saveBuildCollector(new StageBuildResultOrdinalGauge(labelNames, namespace, subsystem, prefix));
case TOTAL_TESTS_GAUGE:
return saveBuildCollector(new TotalTestsGauge(labelNames, namespace, subsystem, prefix));
case BUILD_LIKELY_STUCK_GAUGE:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.jenkinsci.plugins.prometheus.collectors.builds;

import com.cloudbees.workflow.rest.external.StageNodeExt;
import hudson.model.Job;
import hudson.model.Run;
import io.prometheus.client.Gauge;
import io.prometheus.client.SimpleCollector;
import org.apache.commons.lang3.ArrayUtils;
import org.jenkinsci.plugins.prometheus.collectors.CollectorType;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

import static org.jenkinsci.plugins.prometheus.util.FlowNodes.getSortedStageNodes;

public class StageBuildResultOrdinalGauge extends BuildsMetricCollector<Run<?, ?>, Gauge> {

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

protected StageBuildResultOrdinalGauge(String[] labelNames, String namespace, String subsystem, String prefix) {
super(labelNames, namespace, subsystem, prefix);
}

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

@Override
protected String getHelpText() {
return "Build status of a Stage. 0=NOT_EXECUTED,1=ABORTED,2=SUCCESS,3=IN_PROGRESS,4=PAUSED_PENDING_INPUT,5=FAILED,6=UNSTABLE";
}

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

@Override
public void calculateMetric(Run<?, ?> run, String[] labelValues) {
if (run.isBuilding()) {
return;
}

if (!(run instanceof WorkflowRun)) {
return;
}

var workflowRun = (WorkflowRun) run;
WorkflowJob job = workflowRun.getParent();
if (workflowRun.getExecution() != null) {
processPipelineRunStages(job, workflowRun, labelValues);
}
}

private void processPipelineRunStages(Job job, WorkflowRun workflowRun, String[] labelValues) {
List<StageNodeExt> stages = getSortedStageNodes(workflowRun);
for (StageNodeExt stage : stages) {
if (stage != null) {
observeStage(job, workflowRun, stage, labelValues);
}
}
}

private void observeStage(Job job, Run run, StageNodeExt stage, String[] labelValues) {

LOGGER.debug("Observing stage[{}] in run [{}] from job [{}]", stage.getName(), run.getNumber(), job.getName());
String stageName = stage.getName();

String[] values = ArrayUtils.add(labelValues, stageName);

collector.labels(values).set(stage.getStatus().ordinal());
}

Check warning on line 76 in src/main/java/org/jenkinsci/plugins/prometheus/collectors/builds/StageBuildResultOrdinalGauge.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 44-76 are not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;

import static org.jenkinsci.plugins.prometheus.util.FlowNodes.getSortedStageNodes;

public class StageSummary extends BuildsMetricCollector<Run<?, ?>, Summary> {

private static final String NOT_AVAILABLE = "NA";
private static final Logger LOGGER = LoggerFactory.getLogger(StageSummary.class);

protected StageSummary(String[] labelNames, String namespace, String subsystem, String namePrefix) {
Expand Down

0 comments on commit 3d25609

Please sign in to comment.