Skip to content

Commit

Permalink
Merge pull request #141 from jamesrobson-secondmind/metrics-plugin-in…
Browse files Browse the repository at this point in the history
…tegration

Integration with the Metrics plugin
  • Loading branch information
rsandell committed Sep 24, 2021
2 parents 93e4067 + e2c71c5 commit 88a513f
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ recognition of why the build failed.
## Guides

* [Azure Cosmos DB](docs/azure.md)
* [Metrics Integration](docs/metrics.md)

## Community Resources
* [Changelog](https://github.com/jenkinsci/build-failure-analyzer-plugin/releases)
Expand Down
31 changes: 31 additions & 0 deletions docs/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Metrics Integration

This is a guide for the integration with the [Metrics plugin](https://plugins.jenkins.io/metrics/).

## Metrics

The integration provides counters for each individual cause and category that you create. These counters will reset to zero when jenkins is restarted. The format for the metrics created is `jenkins_bfa_category_<category name>` for each category and `jenkins_bfa_cause_<cause name>` for each cause. The category and cause names will be escaped by the metrics api to replace any spaces with underscores.

## Exporting

To export the BFA metrics you can use any plugin that integrates with the Metrics plugin.

### Prometheus
The [prometheus plugin](https://plugins.jenkins.io/prometheus/)
To restructure the metrics into the form that prometheus expects you can add the following into your scrape config:

```yaml
metric_relabel_configs:
- source_labels: [__name__]
regex: 'jenkins_bfa_category_(.*)'
target_label: 'category'
- source_labels: [__name__]
regex: 'jenkins_bfa_cause_(.*)'
target_label: 'cause'
- source_labels: [__name__]
regex: 'jenkins_bfa_(.*)_(.*)'
replacement: 'jenkins_bfa'
target_label: __name__
```

This will provide a metric called `jenkins_bfa` with labels for the category and specific cause.
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.8</version>
<version>2.15</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -376,6 +376,11 @@
<version>2.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>metrics</artifactId>
<version>4.0.2.6</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

package com.sonyericsson.jenkins.plugins.bfa;

import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.incCounters;

import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseDisplayData;
Expand Down Expand Up @@ -188,6 +190,10 @@ public static void scan(Run build, PrintStream scanLog) {
foundCauseList = foundCauseListToLog;
}

for (FoundFailureCause cause : foundCauseList) {
incCounters(cause);
}

List<String> fallbackCategories = PluginImpl.getInstance().getFallbackCategories();

if (!fallbackCategories.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.sonyericsson.jenkins.plugins.bfa;

import com.codahale.metrics.MetricRegistry;
import com.sonyericsson.jenkins.plugins.bfa.model.IFailureCauseMetricData;
import jenkins.metrics.api.Metrics;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;

public final class MetricsManager {
static final String CAUSEPREFIX = "jenkins_bfa.cause.";
static final String CATEGORYPREFIX = "jenkins_bfa.category.";

private MetricsManager() {
}

private static Set<String> getMetricNames(IFailureCauseMetricData cause) {
Set<String> metrics = new HashSet<String>();
metrics.add(CAUSEPREFIX + cause.getName());
List<String> categoriesForCause = cause.getCategories();
if (categoriesForCause != null) {
for (String string : categoriesForCause) {
metrics.add(CATEGORYPREFIX + string);
}
}
return metrics;
}

/**
* Add metrics into the MetricRegistry from the Metrics plugin.
*
* @param cause The Cause to add metrics for
*/
public static void addMetric(IFailureCauseMetricData cause) {
MetricRegistry metricRegistry = Metrics.metricRegistry();
SortedSet<String> existingMetrics = metricRegistry.getNames();
Set<String> metrics = getMetricNames(cause);
for (String metric : metrics) {
if (!existingMetrics.contains(metric)) {
metricRegistry.counter(metric);
}
}
}

/**
* Increment caounters for the metric and its categories.
* @param cause The cause to increment counters for
*/
public static void incCounters(IFailureCauseMetricData cause) {
MetricRegistry metricRegistry = Metrics.metricRegistry();
Set<String> metrics = getMetricNames(cause);
for (String metric : metrics) {
metricRegistry.counter(metric).inc();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package com.sonyericsson.jenkins.plugins.bfa.db;

import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.addMetric;
import static hudson.Util.fixEmpty;

import java.io.IOException;
Expand Down Expand Up @@ -56,6 +57,9 @@ public class LocalFileKnowledgeBase extends KnowledgeBase {

private Map<String, FailureCause> causes;




/**
* Standard constructor. Used for legacy conversion.
*
Expand Down Expand Up @@ -125,6 +129,7 @@ public FailureCause removeCause(String id) throws Exception {

@Override
public FailureCause saveCause(FailureCause cause) throws IOException {
addMetric(cause);
if (fixEmpty(cause.getId()) == null) {
return addCause(cause);
} else {
Expand Down Expand Up @@ -183,7 +188,9 @@ public boolean equals(KnowledgeBase oldKnowledgeBase) {

@Override
public void start() {
//TODO should something be done here?
for (Map.Entry<String, FailureCause> entry : causes.entrySet()) {
addMetric(entry.getValue());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import static com.mongodb.client.model.Filters.not;
import static com.mongodb.client.model.Filters.exists;
import static com.mongodb.client.model.Filters.eq;
import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.addMetric;

import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCursor;
Expand All @@ -58,6 +59,7 @@
import hudson.util.Secret;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
Expand All @@ -82,8 +84,6 @@
import org.mongojack.JacksonMongoCollection;
import org.mongojack.internal.MongoJackModule;

import java.util.Collection;


/**
* Handling of the MongoDB way of saving the knowledge base.
Expand Down Expand Up @@ -211,6 +211,10 @@ public MongoDBKnowledgeBase(String host, int port, String dbName, String userNam
@Override
public synchronized void start() {
initCache();
cache.updateCache();
for (FailureCause entry : getCauseNames()) {
addMetric(entry);
}
}

@Override
Expand Down Expand Up @@ -328,6 +332,7 @@ public FailureCause addCause(FailureCause cause, boolean doUpdate) {

@Override
public FailureCause saveCause(FailureCause cause) {
addMetric(cause);
return saveCause(cause, true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
* @author Tomas Westling &lt;thomas.westling@sonyericsson.com&gt;
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class FailureCause implements Serializable, Action, Describable<FailureCause> {
public class FailureCause implements Serializable, Action, Describable<FailureCause>, IFailureCauseMetricData {
private static final Logger logger = Logger.getLogger(FailureCause.class.getName());
private String id;
private String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
* @author Tomas Westling &lt;tomas.westling@sonymobile.com&gt;
*/
@ExportedBean
public class FoundFailureCause {
public class FoundFailureCause implements IFailureCauseMetricData {
private static final Logger logger = Logger.getLogger(FoundFailureCause.class.getName());

private final String id;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sonyericsson.jenkins.plugins.bfa.model;

import java.util.List;

public interface IFailureCauseMetricData {
/**
* Getter for the name.
* @return the name
*/
String getName();

/**
* Getter for the categories.
* @return the categories
*/
List<String> getCategories();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.sonyericsson.jenkins.plugins.bfa;

import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;

import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication;
import jenkins.metrics.api.Metrics;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.addMetric;
import static com.sonyericsson.jenkins.plugins.bfa.MetricsManager.incCounters;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;


/**
* Tests for {@link MetricsManager}.
*/

@RunWith(PowerMockRunner.class)
@PrepareForTest({MetricRegistry.class})
public class MetricsManagerTest {
@Mock
private MetricRegistry metricRegistry;
@Mock
private Counter counter;

private List<Indication> indications;
private Indication indication;
private FailureCause mockedCause;


/**
* Common stuff to set up for the tests.
*/
@Before
public void setUp() {
indications = new LinkedList<Indication>();
indication = new BuildLogIndication("something");
indications.add(indication);
mockedCause = new FailureCause("id", "myFailureCause", "description", "comment", new Date(),
"category", indications, null);

PowerMockito.mockStatic(Metrics.class);
PowerMockito.when(Metrics.metricRegistry()).thenReturn(metricRegistry);
PowerMockito.when(metricRegistry.counter(Mockito.anyString())).thenReturn(counter);
}

/**
* Test that the case and category counters are created from a FailureCause.
*/
public void testAddMetric() {
addMetric(mockedCause);

verify(metricRegistry, times(1)).counter("jenkins_bfa.cause.myFailureCause");
verify(metricRegistry, times(1)).counter("jenkins_bfa.category.category");
}

/**
* Test that the cause and category counters are incremented for a Failurecasue.
*/
public void testIncCounters() {
incCounters(mockedCause);

verify(metricRegistry, times(1)).counter("jenkins_bfa.cause.myFailureCause").inc();
verify(metricRegistry, times(1)).counter("jenkins_bfa.category.category").inc();
}

}

0 comments on commit 88a513f

Please sign in to comment.