From a0abcdec0ed9b534e4555c55ee444e42c7982982 Mon Sep 17 00:00:00 2001 From: Alexander Reitz Date: Mon, 20 Apr 2020 15:53:09 +0200 Subject: [PATCH 01/13] adds pause duration, build time --- pom.xml | 28 +++++++++++++-- .../listeners/DatadogBuildListener.java | 36 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f5e9d1365..da52d745d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.plugins plugin - 3.56 + 3.57 @@ -15,7 +15,7 @@ https://github.com/jenkinsci/datadog-plugin org.datadog.jenkins.plugins datadog - 1.1.1-SNAPSHOT + 1.2.0-SNAPSHOT hpi @@ -72,6 +72,30 @@ 3.2.4 test + + + org.jenkins-ci.plugins.workflow + workflow-job + 2.12 + + + + org.jenkins-ci.plugins.workflow + workflow-step-api + 2.20 + + + + org.jenkins-ci.plugins.workflow + workflow-api + 2.37 + + + + org.jenkins-ci.plugins.pipeline-stage-view + pipeline-stage-view + 2.12 + diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index 4d205f7b5..8579002b9 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -25,6 +25,8 @@ of this software and associated documentation files (the "Software"), to deal package org.datadog.jenkins.plugins.datadog.listeners; +import com.cloudbees.workflow.rest.external.RunExt; +import com.cloudbees.workflow.rest.external.StageNodeExt; import hudson.Extension; import hudson.model.*; import hudson.model.listeners.RunListener; @@ -36,11 +38,13 @@ of this software and associated documentation files (the "Software"), to deal import org.datadog.jenkins.plugins.datadog.events.BuildFinishedEventImpl; import org.datadog.jenkins.plugins.datadog.events.BuildStartedEventImpl; import org.datadog.jenkins.plugins.datadog.model.BuildData; +import org.jenkinsci.plugins.workflow.job.WorkflowRun; import javax.annotation.Nonnull; import java.io.IOException; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.logging.Logger; @@ -154,6 +158,26 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { Map> tags = buildData.getTags(); String hostname = buildData.getHostname("unknown"); client.gauge("jenkins.job.duration", buildData.getDuration(0L) / 1000, hostname, tags); + logger.fine(String.format("[%s]: Duration: %s", buildData.getJobName(null), toTimeString(buildData.getDuration(0L)))); + + if (run instanceof WorkflowRun) { + RunExt extRun = RunExt.create((WorkflowRun) run); + long pauseduration = 0; + for (StageNodeExt stage : extRun.getStages()) { + pauseduration += stage.getPauseDurationMillis(); + } + client.gauge("jenkins.job.pauseduration", + pauseduration / 1000, + buildData.getHostname("null"), + tags); + logger.fine(String.format("[%s]: Pause Duration: %s", buildData.getJobName(null), toTimeString(pauseduration))); + long buildduration = run.getDuration() - pauseduration; + client.gauge("jenkins.job.buildduration", + buildduration / 1000, + buildData.getHostname("null"), + tags); + logger.fine(String.format("[%s]: Build Duration (without pause): %s", buildData.getJobName(null), toTimeString(buildduration))); + } // Submit counter client.incrementCounter("jenkins.job.completed", hostname, tags); @@ -178,19 +202,24 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { long leadTime = run.getDuration() + mttr; client.gauge("jenkins.job.leadtime", leadTime / 1000, hostname, tags); + logger.fine(String.format("[%s]: Lead time: %s", buildData.getJobName(null), toTimeString(leadTime))); if (cycleTime > 0) { client.gauge("jenkins.job.cycletime", cycleTime / 1000, hostname, tags); + logger.fine(String.format("[%s]: Cycle Time: %s", buildData.getJobName(null), toTimeString(cycleTime))); } if (mttr > 0) { client.gauge("jenkins.job.mttr", mttr / 1000, hostname, tags); + logger.fine(String.format("[%s]: MTTR: %s", buildData.getJobName(null), toTimeString(mttr))); } } else { long feedbackTime = run.getDuration(); long mtbf = getMeanTimeBetweenFailure(run); client.gauge("jenkins.job.feedbacktime", feedbackTime / 1000, hostname, tags); + logger.fine(String.format("[%s]: Feedback Time: %s", buildData.getJobName(null), toTimeString(feedbackTime))); if (mtbf > 0) { client.gauge("jenkins.job.mtbf", mtbf / 1000, hostname, tags); + logger.fine(String.format("[%s]: MTBF: %s", buildData.getJobName(null), toTimeString(mtbf))); } } @@ -241,6 +270,13 @@ public void onDeleted(Run run) { } } + private String toTimeString(long millis) { + return String.format("%d min, %d sec", + TimeUnit.MILLISECONDS.toMinutes(millis), + TimeUnit.MILLISECONDS.toSeconds(millis) - + TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))); + } + private long getMeanTimeBetweenFailure(Run run) { Run lastGreenRun = run.getPreviousNotFailedBuild(); if (lastGreenRun != null) { From 5790e21f12a41c7805417c43de4be415d0380b82 Mon Sep 17 00:00:00 2001 From: Alexander Reitz Date: Tue, 21 Apr 2020 10:12:44 +0200 Subject: [PATCH 02/13] Use hostname var --- pom.xml | 2 +- .../plugins/datadog/listeners/DatadogBuildListener.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index da52d745d..ce06d54ad 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ https://github.com/jenkinsci/datadog-plugin org.datadog.jenkins.plugins datadog - 1.2.0-SNAPSHOT + 1.1.1-SNAPSHOT hpi diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index 8579002b9..2a0fe2377 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -168,13 +168,13 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { } client.gauge("jenkins.job.pauseduration", pauseduration / 1000, - buildData.getHostname("null"), + hostname, tags); logger.fine(String.format("[%s]: Pause Duration: %s", buildData.getJobName(null), toTimeString(pauseduration))); long buildduration = run.getDuration() - pauseduration; client.gauge("jenkins.job.buildduration", buildduration / 1000, - buildData.getHostname("null"), + hostname, tags); logger.fine(String.format("[%s]: Build Duration (without pause): %s", buildData.getJobName(null), toTimeString(buildduration))); } From 4690d1c52c4eb6ad5bead9dd408d36d3296995f6 Mon Sep 17 00:00:00 2001 From: Alexander Reitz Date: Tue, 21 Apr 2020 10:39:20 +0200 Subject: [PATCH 03/13] Add build and pauseduration to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9a9d1f230..d5cee4abb 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,7 @@ NOTE: `event_type` is always set to `security` for above events and metrics. | `jenkins.item.location_changed` | Rate of items being moved. | `jenkins_url`, `user_id` | | `jenkins.item.updated` | Rate of items being updated. | `jenkins_url`, `user_id` | | `jenkins.job.aborted` | Rate of aborted jobs. | `branch`, `jenkins_url`, `job`, `node`, `user_id` | +| `jenkins.job.buildduration` | Build duration without pause (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.completed` | Rate of completed jobs. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.cycletime` | Build Cycle Time. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.duration` | Build duration (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | @@ -210,6 +211,7 @@ NOTE: `event_type` is always set to `security` for above events and metrics. | `jenkins.job.leadtime` | Build Lead Time. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.mtbf` | MTBF, time between last successful job and current failed job. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.mttr` | MTTR: time between last failed job and current successful job. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | +| `jenkins.job.pauseduration` | Pause duration of build job (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.started` | Rate of started jobs. | `branch`, `jenkins_url`, `job`, `node`, `user_id` | | `jenkins.job.waiting` | Time spent waiting for job to run (in milliseconds). | `branch`, `jenkins_url`, `job`, `node`, `user_id` | | `jenkins.node.count` | Total number of node. | `jenkins_url` | From 3a3792023c0cc4bfc635e78e9857140b8a8b0cb6 Mon Sep 17 00:00:00 2001 From: Alexander Reitz Date: Tue, 21 Apr 2020 15:31:35 +0200 Subject: [PATCH 04/13] Add SCM checkout duration --- README.md | 1 + .../datadog/listeners/DatadogBuildListener.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/README.md b/README.md index d5cee4abb..5e7e544a3 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,7 @@ NOTE: `event_type` is always set to `security` for above events and metrics. | `jenkins.item.updated` | Rate of items being updated. | `jenkins_url`, `user_id` | | `jenkins.job.aborted` | Rate of aborted jobs. | `branch`, `jenkins_url`, `job`, `node`, `user_id` | | `jenkins.job.buildduration` | Build duration without pause (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | +| `jenkins.job.checkoutduration` | SCM Checkout duration (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.completed` | Rate of completed jobs. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.cycletime` | Build Cycle Time. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.duration` | Build duration (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index 2a0fe2377..7a034db6b 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -163,9 +163,19 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { if (run instanceof WorkflowRun) { RunExt extRun = RunExt.create((WorkflowRun) run); long pauseduration = 0; + long checkoutduration = 0; for (StageNodeExt stage : extRun.getStages()) { pauseduration += stage.getPauseDurationMillis(); + if (stage.getName().contains("Checkout SCM")) { + checkoutduration += stage.getDurationMillis(); + } } + client.gauge("jenkins.job.checkoutduration", + checkoutduration / 1000, + hostname, + tags); + logger.fine(String.format("[%s]: Checkout Duration: %s", buildData.getJobName(null), toTimeString(checkoutduration))); + client.gauge("jenkins.job.pauseduration", pauseduration / 1000, hostname, From 59f0ebb0934d90134e23e2cda29b89107267f93d Mon Sep 17 00:00:00 2001 From: "florian.veaux" Date: Wed, 29 Apr 2020 11:19:21 +0200 Subject: [PATCH 05/13] Add tests --- .../listeners/DatadogBuildListener.java | 6 +- .../listeners/DatadogBuildListenerTest.java | 175 ++++++++++-------- .../DatadogBuildListenerTestWrapper.java | 12 ++ .../plugins/datadog/stubs/RunExtStub.java | 24 +++ 4 files changed, 143 insertions(+), 74 deletions(-) create mode 100644 src/test/java/org/datadog/jenkins/plugins/datadog/stubs/RunExtStub.java diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index 7a034db6b..0f170771c 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -161,7 +161,7 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { logger.fine(String.format("[%s]: Duration: %s", buildData.getJobName(null), toTimeString(buildData.getDuration(0L)))); if (run instanceof WorkflowRun) { - RunExt extRun = RunExt.create((WorkflowRun) run); + RunExt extRun = getRunExtForRun((WorkflowRun) run); long pauseduration = 0; long checkoutduration = 0; for (StageNodeExt stage : extRun.getStages()) { @@ -326,6 +326,10 @@ private boolean isFailedBuild(Run run) { return run != null && run.getResult() != Result.SUCCESS; } + public RunExt getRunExtForRun(WorkflowRun run) { + return RunExt.create(run); + } + public Queue getQueue(){ return Queue.getInstance(); } diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java index f897d9def..2fc1b57c8 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java @@ -25,6 +25,7 @@ of this software and associated documentation files (the "Software"), to deal package org.datadog.jenkins.plugins.datadog.listeners; +import com.cloudbees.workflow.rest.external.StageNodeExt; import hudson.EnvVars; import hudson.model.*; import jenkins.model.Jenkins; @@ -33,7 +34,11 @@ of this software and associated documentation files (the "Software"), to deal import org.datadog.jenkins.plugins.datadog.clients.DatadogClientStub; import org.datadog.jenkins.plugins.datadog.clients.DatadogMetric; import org.datadog.jenkins.plugins.datadog.stubs.QueueStub; +import org.datadog.jenkins.plugins.datadog.stubs.RunExtStub; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import java.util.Arrays; @@ -43,57 +48,68 @@ of this software and associated documentation files (the "Software"), to deal public class DatadogBuildListenerTest { - @Test - public void testOnCompletedWithNothing() throws Exception { - DatadogClientStub client = new DatadogClientStub(); - DatadogBuildListener datadogBuildListener = new DatadogBuildListenerTestWrapper(); - ((DatadogBuildListenerTestWrapper)datadogBuildListener).setDatadogClient(client); + private DatadogClientStub client; + private DatadogBuildListener datadogBuildListener; + private ProjectStub job; + private Queue queue; + private WorkflowRun workflowRun; + EnvVars envVars; - Jenkins jenkins = mock(Jenkins.class); - when(jenkins.getFullName()).thenReturn(null); + @Before + public void setUpMocks() { + this.client = new DatadogClientStub(); - ProjectStub job = new ProjectStub(jenkins,null); + this.datadogBuildListener = new DatadogBuildListenerTestWrapper(); + ((DatadogBuildListenerTestWrapper)datadogBuildListener).setDatadogClient(client); - EnvVars envVars = new EnvVars(); + this.queue = new QueueStub(mock(LoadBalancer.class)); + Queue.Item item = mock(Queue.Item.class); + when(item.getId()).thenReturn(1L); + when(item.getInQueueSince()).thenReturn(2000000L); + ((QueueStub)queue).setItem(item); + ((DatadogBuildListenerTestWrapper)datadogBuildListener).setQueue(queue); - Run run = mock(Run.class); - when(run.getResult()).thenReturn(null); - when(run.getEnvironment(any(TaskListener.class))).thenReturn(envVars); - when(run.getParent()).thenReturn(job); + Jenkins jenkins = mock(Jenkins.class); + when(jenkins.getFullName()).thenReturn("ParentFullName"); + this.job = new ProjectStub(jenkins,"JobName"); - datadogBuildListener.onCompleted(run, mock(TaskListener.class)); + this.envVars = new EnvVars(); + envVars.put("HOSTNAME", "test-hostname-2"); + envVars.put("NODE_NAME", "test-node"); + envVars.put("BUILD_URL", "http://build_url.com"); + envVars.put("GIT_BRANCH", "test-branch"); - client.assertedAllMetricsAndServiceChecks(); + workflowRun = mock(WorkflowRun.class); } @Test - public void testOnCompletedOnSuccessfulRun() throws Exception { - DatadogClientStub client = new DatadogClientStub(); - DatadogBuildListener datadogBuildListener = new DatadogBuildListenerTestWrapper(); - ((DatadogBuildListenerTestWrapper)datadogBuildListener).setDatadogClient(client); - + public void testOnCompletedWithNothing() throws Exception { Jenkins jenkins = mock(Jenkins.class); - when(jenkins.getFullName()).thenReturn("ParentFullName"); + when(jenkins.getFullName()).thenReturn(null); + this.job = new ProjectStub(jenkins,null); - ProjectStub project = new ProjectStub(jenkins,"JobName"); + Run run = mock(Run.class); + when(run.getResult()).thenReturn(null); + when(run.getEnvironment(any(TaskListener.class))).thenReturn(this.envVars); + when(run.getParent()).thenReturn(this.job); - EnvVars envVars = new EnvVars(); - envVars.put("HOSTNAME", "test-hostname-2"); - envVars.put("NODE_NAME", "test-node"); - envVars.put("BUILD_URL", "http://build_url.com"); - envVars.put("GIT_BRANCH", "test-branch"); + this.datadogBuildListener.onCompleted(run, mock(TaskListener.class)); + this.client.assertedAllMetricsAndServiceChecks(); + } - BuildStub previousSuccessfulRun = new BuildStub(project, Result.SUCCESS, envVars, null, + @Test + public void testOnCompletedOnSuccessfulRun() throws Exception { + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, envVars, null, 121000L, 1, null, 1000000L, null); - BuildStub previousFailedRun1 = new BuildStub(project, Result.FAILURE, envVars, previousSuccessfulRun, + BuildStub previousFailedRun1 = new BuildStub(this.job, Result.FAILURE, envVars, previousSuccessfulRun, 122000L, 2, previousSuccessfulRun, 2000000L, null); - BuildStub previousFailedRun2 = new BuildStub(project, Result.FAILURE, envVars, previousSuccessfulRun, + BuildStub previousFailedRun2 = new BuildStub(this.job, Result.FAILURE, envVars, previousSuccessfulRun, 123000L, 3, previousFailedRun1, 3000000L, null); - BuildStub successRun = new BuildStub(project, Result.SUCCESS, envVars, previousSuccessfulRun, + BuildStub successRun = new BuildStub(this.job, Result.SUCCESS, envVars, previousSuccessfulRun, 124000L, 4, previousFailedRun2, 4000000L, null); datadogBuildListener.onCompleted(previousSuccessfulRun, mock(TaskListener.class)); @@ -137,27 +153,62 @@ public void testOnCompletedOnSuccessfulRun() throws Exception { } @Test - public void testOnCompletedOnFailedRun() throws Exception { - DatadogClientStub client = new DatadogClientStub(); - DatadogBuildListener datadogBuildListener = new DatadogBuildListenerTestWrapper(); - ((DatadogBuildListenerTestWrapper)datadogBuildListener).setDatadogClient(client); - - Jenkins jenkins = mock(Jenkins.class); - when(jenkins.getFullName()).thenReturn("ParentFullName"); - - ProjectStub project = new ProjectStub(jenkins,"JobName"); - - EnvVars envVars = new EnvVars(); - envVars.put("HOSTNAME", "test-hostname-2"); - envVars.put("NODE_NAME", "test-node"); - envVars.put("BUILD_URL", "http://build_url.com"); - envVars.put("GIT_BRANCH", "test-branch"); + public void testOnCompletedWorkflowRun() throws Exception { + final int stageCount = 5; + final long stageDuration = 12000; + final long pauseDurationPerStage = 400; + final long buildDuration = stageDuration * stageCount; + final long pauseDuration = pauseDurationPerStage * stageCount; + final long totalDuration = buildDuration + pauseDuration; + final String[] stageNames = {"Stage 1: Checkout SCM", "Stage 2", "Stage 3", "Stage 4", "Stage 5"}; + + WorkflowJob job = mock(WorkflowJob.class); + when(job.getFullName()).thenReturn("Pipeline job"); + when(workflowRun.getParent()).thenReturn(job); + + TaskListener listener = mock(TaskListener.class); + when(workflowRun.getEnvironment(listener)).thenReturn(this.envVars); + when(workflowRun.getStartTimeInMillis()).thenReturn((long)0); + when(workflowRun.getDuration()).thenReturn(totalDuration); + when(workflowRun.getResult()).thenReturn(null); + when(workflowRun.getNumber()).thenReturn(0); + when(workflowRun.getResult()).thenReturn(Result.SUCCESS); + + RunExtStub runExt = new RunExtStub(); + for(int i = 0; i < stageCount; i++){ + StageNodeExt stage = mock(StageNodeExt.class); + when(stage.getName()).thenReturn(stageNames[i]); + when(stage.getPauseDurationMillis()).thenReturn(pauseDurationPerStage); + when(stage.getDurationMillis()).thenReturn(stageDuration); + runExt.addStage(stage); + } + ((DatadogBuildListenerTestWrapper)datadogBuildListener).setStubbedRunExt(runExt); + + datadogBuildListener.onCompleted(workflowRun, listener); + + String[] expectedTags = { + "result:SUCCESS", + "node:test-node", + "jenkins_url:unknown", + "user_id:anonymous", + "job:Pipelinejob", + "branch:test-branch" + }; + client.assertMetric("jenkins.job.duration", totalDuration / 1000, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.checkoutduration", stageDuration / 1000, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.pauseduration", pauseDuration / 1000, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.buildduration", buildDuration / 1000, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.completed", 1, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.leadtime", totalDuration / 1000, "test-hostname-2", expectedTags); + } - BuildStub previousSuccessfulRun = new BuildStub(project, Result.SUCCESS, envVars, null, + @Test + public void testOnCompletedOnFailedRun() throws Exception { + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, envVars, null, 123000L, 1, null, 1000000L, null); - BuildStub failedRun = new BuildStub(project, Result.FAILURE, envVars, null, - 124000L, 2, null, 2000000L, previousSuccessfulRun);; + BuildStub failedRun = new BuildStub(this.job, Result.FAILURE, envVars, null, + 124000L, 2, null, 2000000L, previousSuccessfulRun); datadogBuildListener.onCompleted(previousSuccessfulRun, mock(TaskListener.class)); String[] expectedTags1 = new String[6]; @@ -191,30 +242,7 @@ public void testOnCompletedOnFailedRun() throws Exception { @Test public void testOnStarted() throws Exception { - DatadogClientStub client = new DatadogClientStub(); - DatadogBuildListener datadogBuildListener = new DatadogBuildListenerTestWrapper(); - ((DatadogBuildListenerTestWrapper)datadogBuildListener).setDatadogClient(client); - Queue queue = new QueueStub(mock(LoadBalancer.class)); - ((DatadogBuildListenerTestWrapper)datadogBuildListener).setQueue(queue); - - Jenkins jenkins = mock(Jenkins.class); - when(jenkins.getFullName()).thenReturn("ParentFullName"); - - ProjectStub project = new ProjectStub(jenkins,"JobName"); - - Queue.Item item = mock(Queue.Item.class); - when(item.getId()).thenReturn(1L); - when(item.getInQueueSince()).thenReturn(2000000L); - - ((QueueStub)queue).setItem(item); - - EnvVars envVars = new EnvVars(); - envVars.put("HOSTNAME", "test-hostname-2"); - envVars.put("NODE_NAME", "test-node"); - envVars.put("BUILD_URL", "http://build_url.com"); - envVars.put("GIT_BRANCH", "test-branch"); - - BuildStub run = new BuildStub(project, Result.SUCCESS, envVars, null, + BuildStub run = new BuildStub(this.job, Result.SUCCESS, envVars, null, 123000L, 1, null, 1000000L, null); datadogBuildListener.onStarted(run, mock(TaskListener.class)); @@ -235,4 +263,5 @@ public void testOnStarted() throws Exception { client.metrics.clear(); client.assertedAllMetricsAndServiceChecks(); } + } diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTestWrapper.java b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTestWrapper.java index bd1d16470..63148e577 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTestWrapper.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTestWrapper.java @@ -1,11 +1,14 @@ package org.datadog.jenkins.plugins.datadog.listeners; +import com.cloudbees.workflow.rest.external.RunExt; import hudson.model.Queue; import org.datadog.jenkins.plugins.datadog.DatadogClient; +import org.jenkinsci.plugins.workflow.job.WorkflowRun; public class DatadogBuildListenerTestWrapper extends DatadogBuildListener { Queue queue; DatadogClient client; + RunExt runExt; public void setQueue(Queue queue) { this.queue = queue; @@ -22,4 +25,13 @@ public Queue getQueue(){ public DatadogClient getDatadogClient(){ return this.client; } + + public void setStubbedRunExt(RunExt r){ + this.runExt = r; + } + + @Override + public RunExt getRunExtForRun(WorkflowRun r){ + return this.runExt; + } } diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/stubs/RunExtStub.java b/src/test/java/org/datadog/jenkins/plugins/datadog/stubs/RunExtStub.java new file mode 100644 index 000000000..b065a0dc6 --- /dev/null +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/stubs/RunExtStub.java @@ -0,0 +1,24 @@ +package org.datadog.jenkins.plugins.datadog.stubs; + +import com.cloudbees.workflow.rest.external.RunExt; +import com.cloudbees.workflow.rest.external.StageNodeExt; +import java.util.ArrayList; +import java.util.List; + +public class RunExtStub extends RunExt { + + private List stages; + + public RunExtStub(){ + this.stages = new ArrayList<>(); + } + public void addStage(StageNodeExt stage){ + this.stages.add(stage); + } + + @Override + public List getStages() { + return this.stages; + } + +} From 10242f6ce35c1a877eeff8ae0b46662fcfc84ff7 Mon Sep 17 00:00:00 2001 From: "florian.veaux" Date: Wed, 29 Apr 2020 11:24:33 +0200 Subject: [PATCH 06/13] Add mockito file to mock final --- .../resources/mockito-extensions/org.mockito.plugins.MockMaker | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 000000000..1f0955d45 --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline From accdbb3a808580c29a6970c81e5a1d7d0ebbb850 Mon Sep 17 00:00:00 2001 From: "florian.veaux" Date: Wed, 29 Apr 2020 11:42:57 +0200 Subject: [PATCH 07/13] Update jenkins parent pom version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ce06d54ad..60977f095 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.plugins plugin - 3.57 + 4.1 From 53287e6caec94726f798a081c522e4e02e66a011 Mon Sep 17 00:00:00 2001 From: Alexander Reitz Date: Mon, 11 May 2020 09:09:45 +0200 Subject: [PATCH 08/13] Remove checkout duration --- README.md | 1 - .../datadog/listeners/DatadogBuildListener.java | 10 ---------- .../datadog/listeners/DatadogBuildListenerTest.java | 1 - 3 files changed, 12 deletions(-) diff --git a/README.md b/README.md index 5e7e544a3..d5cee4abb 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,6 @@ NOTE: `event_type` is always set to `security` for above events and metrics. | `jenkins.item.updated` | Rate of items being updated. | `jenkins_url`, `user_id` | | `jenkins.job.aborted` | Rate of aborted jobs. | `branch`, `jenkins_url`, `job`, `node`, `user_id` | | `jenkins.job.buildduration` | Build duration without pause (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | -| `jenkins.job.checkoutduration` | SCM Checkout duration (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.completed` | Rate of completed jobs. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.cycletime` | Build Cycle Time. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.duration` | Build duration (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index 0f170771c..a6bf3eaaf 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -163,19 +163,9 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { if (run instanceof WorkflowRun) { RunExt extRun = getRunExtForRun((WorkflowRun) run); long pauseduration = 0; - long checkoutduration = 0; for (StageNodeExt stage : extRun.getStages()) { pauseduration += stage.getPauseDurationMillis(); - if (stage.getName().contains("Checkout SCM")) { - checkoutduration += stage.getDurationMillis(); - } } - client.gauge("jenkins.job.checkoutduration", - checkoutduration / 1000, - hostname, - tags); - logger.fine(String.format("[%s]: Checkout Duration: %s", buildData.getJobName(null), toTimeString(checkoutduration))); - client.gauge("jenkins.job.pauseduration", pauseduration / 1000, hostname, diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java index 2fc1b57c8..9bb4993f5 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java @@ -195,7 +195,6 @@ public void testOnCompletedWorkflowRun() throws Exception { "branch:test-branch" }; client.assertMetric("jenkins.job.duration", totalDuration / 1000, "test-hostname-2", expectedTags); - client.assertMetric("jenkins.job.checkoutduration", stageDuration / 1000, "test-hostname-2", expectedTags); client.assertMetric("jenkins.job.pauseduration", pauseDuration / 1000, "test-hostname-2", expectedTags); client.assertMetric("jenkins.job.buildduration", buildDuration / 1000, "test-hostname-2", expectedTags); client.assertMetric("jenkins.job.completed", 1, "test-hostname-2", expectedTags); From 8029aa29a7134d5e5cc40d97e3a785390005e28d Mon Sep 17 00:00:00 2001 From: "florian.veaux" Date: Mon, 22 Jun 2020 15:35:13 +0200 Subject: [PATCH 09/13] Address review --- .../plugins/datadog/listeners/DatadogBuildListener.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index e862e3236..325abdcc6 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -268,10 +268,10 @@ public void onDeleted(Run run) { } private String toTimeString(long millis) { - return String.format("%d min, %d sec", - TimeUnit.MILLISECONDS.toMinutes(millis), - TimeUnit.MILLISECONDS.toSeconds(millis) - - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))); + long minutes = TimeUnit.MILLISECONDS.toMinutes(millis); + long totalSeconds = TimeUnit.MILLISECONDS.toSeconds(millis); + long seconds = totalSeconds - TimeUnit.MINUTES.toSeconds(minutes); + return String.format("%d min, %d sec", minutes, seconds); } private long getMeanTimeBetweenFailure(Run run) { From c4d1f95562bf0ab5a4faf2086192ec9e77c254de Mon Sep 17 00:00:00 2001 From: "florian.veaux" Date: Tue, 23 Jun 2020 09:52:40 +0200 Subject: [PATCH 10/13] Update metric names --- .../plugins/datadog/listeners/DatadogBuildListener.java | 4 ++-- .../plugins/datadog/listeners/DatadogBuildListenerTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java index 325abdcc6..8ddfb7c58 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListener.java @@ -168,10 +168,10 @@ public void onCompleted(Run run, @Nonnull TaskListener listener) { for (StageNodeExt stage : extRun.getStages()) { pauseDuration += stage.getPauseDurationMillis(); } - client.gauge("jenkins.job.pauseduration", pauseDuration / 1000, hostname, tags); + client.gauge("jenkins.job.pause_duration", pauseDuration / 1000, hostname, tags); logger.fine(String.format("[%s]: Pause Duration: %s", buildData.getJobName(null), toTimeString(pauseDuration))); long buildDuration = run.getDuration() - pauseDuration; - client.gauge("jenkins.job.buildduration", buildDuration / 1000, hostname, tags); + client.gauge("jenkins.job.build_duration", buildDuration / 1000, hostname, tags); logger.fine( String.format("[%s]: Build Duration (without pause): %s", buildData.getJobName(null), toTimeString(buildDuration))); } diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java index 9bb4993f5..279426c23 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogBuildListenerTest.java @@ -195,8 +195,8 @@ public void testOnCompletedWorkflowRun() throws Exception { "branch:test-branch" }; client.assertMetric("jenkins.job.duration", totalDuration / 1000, "test-hostname-2", expectedTags); - client.assertMetric("jenkins.job.pauseduration", pauseDuration / 1000, "test-hostname-2", expectedTags); - client.assertMetric("jenkins.job.buildduration", buildDuration / 1000, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.pause_duration", pauseDuration / 1000, "test-hostname-2", expectedTags); + client.assertMetric("jenkins.job.build_duration", buildDuration / 1000, "test-hostname-2", expectedTags); client.assertMetric("jenkins.job.completed", 1, "test-hostname-2", expectedTags); client.assertMetric("jenkins.job.leadtime", totalDuration / 1000, "test-hostname-2", expectedTags); } From 51acc5061ebe3cef054ab81283a53a4b3f7d0c8b Mon Sep 17 00:00:00 2001 From: Florian Veaux Date: Tue, 23 Jun 2020 15:42:19 +0200 Subject: [PATCH 11/13] Update README.md Co-authored-by: Sarah Witt --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e3df731d..2286e7a95 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ NOTE: `event_type` is always set to `security` for above events and metrics. | `jenkins.item.location_changed` | Rate of items being moved. | `jenkins_url`, `user_id` | | `jenkins.item.updated` | Rate of items being updated. | `jenkins_url`, `user_id` | | `jenkins.job.aborted` | Rate of aborted jobs. | `branch`, `jenkins_url`, `job`, `node`, `user_id` | -| `jenkins.job.buildduration` | Build duration without pause (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | +| `jenkins.job.build_duration` | Build duration without pause (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.completed` | Rate of completed jobs. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.cycletime` | Build Cycle Time. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.duration` | Build duration (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | From 223ad5089d30e417731ad88ea2c813d2580e9137 Mon Sep 17 00:00:00 2001 From: Florian Veaux Date: Tue, 23 Jun 2020 15:42:26 +0200 Subject: [PATCH 12/13] Update README.md Co-authored-by: Sarah Witt --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2286e7a95..9c7658526 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ NOTE: `event_type` is always set to `security` for above events and metrics. | `jenkins.job.leadtime` | Build Lead Time. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.mtbf` | MTBF, time between last successful job and current failed job. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.mttr` | MTTR: time between last failed job and current successful job. | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | -| `jenkins.job.pauseduration` | Pause duration of build job (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | +| `jenkins.job.pause_duration` | Pause duration of build job (in seconds). | `branch`, `jenkins_url`, `job`, `node`, `result`, `user_id` | | `jenkins.job.started` | Rate of started jobs. | `branch`, `jenkins_url`, `job`, `node`, `user_id` | | `jenkins.job.waiting` | Time spent waiting for job to run (in milliseconds). | `branch`, `jenkins_url`, `job`, `node`, `user_id` | | `jenkins.node.count` | Total number of node. | `jenkins_url` | From 9c97fc728d41eb49f7de12fe880c3a7be2226b80 Mon Sep 17 00:00:00 2001 From: "florian.veaux" Date: Tue, 23 Jun 2020 16:57:44 +0200 Subject: [PATCH 13/13] Fix dependencies for tests --- pom.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pom.xml b/pom.xml index 716145e2b..eb7e10fdf 100644 --- a/pom.xml +++ b/pom.xml @@ -114,6 +114,26 @@ pipeline-model-definition 1.4.0 test + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + org.jenkins-ci.plugins + jackson2-api + + + + + org.jenkins-ci.plugins + jackson2-api + 2.9.8 + test