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

Add a link to Datadog to job details page #447

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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 @@ -25,10 +25,12 @@ of this software and associated documentation files (the "Software"), to deal

package org.datadog.jenkins.plugins.datadog;

import static org.datadog.jenkins.plugins.datadog.configuration.DatadogAgentConfiguration.DatadogAgentConfigurationDescriptor.*;
import static org.datadog.jenkins.plugins.datadog.configuration.DatadogAgentConfiguration.DatadogAgentConfigurationDescriptor.getDefaultAgentHost;
import static org.datadog.jenkins.plugins.datadog.configuration.DatadogAgentConfiguration.DatadogAgentConfigurationDescriptor.getDefaultAgentLogCollectionPort;
import static org.datadog.jenkins.plugins.datadog.configuration.DatadogAgentConfiguration.DatadogAgentConfigurationDescriptor.getDefaultAgentPort;
import static org.datadog.jenkins.plugins.datadog.configuration.DatadogAgentConfiguration.DatadogAgentConfigurationDescriptor.getDefaultAgentTraceCollectionPort;
import static org.datadog.jenkins.plugins.datadog.configuration.api.intake.DatadogIntakeSite.DatadogIntakeSiteDescriptor.getSite;
import static org.datadog.jenkins.plugins.datadog.configuration.api.key.DatadogTextApiKey.DatadogTextApiKeyDescriptor.getDefaultKey;

import com.thoughtworks.xstream.annotations.XStreamConverter;
Expand All @@ -44,6 +46,7 @@ of this software and associated documentation files (the "Software"), to deal
import hudson.util.XStream2;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -202,7 +205,7 @@ public void loadEnvVariables() {
String clientType = System.getenv(REPORT_WITH_PROPERTY);
if (DATADOG_AGENT_CLIENT_TYPE.equals(clientType)) {
this.datadogClientConfiguration = new DatadogAgentConfiguration(
getDefaultAgentHost(), getDefaultAgentPort(), getDefaultAgentLogCollectionPort(), getDefaultAgentTraceCollectionPort());
getDefaultAgentHost(), getDefaultAgentPort(), getDefaultAgentLogCollectionPort(), getDefaultAgentTraceCollectionPort(), getSite());
} else {
DatadogIntake intake = DatadogIntake.getDefaultIntake();
DatadogTextApiKey apiKey = new DatadogTextApiKey(getDefaultKey());
Expand Down Expand Up @@ -1167,7 +1170,7 @@ protected Object readResolve() {
this.included = this.whitelist;
}
if (DATADOG_AGENT_CLIENT_TYPE.equals(reportWith)) {
this.datadogClientConfiguration = new DatadogAgentConfiguration(this.targetHost, this.targetPort, this.targetLogCollectionPort, this.targetTraceCollectionPort);
this.datadogClientConfiguration = new DatadogAgentConfiguration(this.targetHost, this.targetPort, this.targetLogCollectionPort, this.targetTraceCollectionPort, getSite());
}
if (DATADOG_API_CLIENT_TYPE.equals(reportWith)) {
DatadogIntakeUrls intake = new DatadogIntakeUrls(this.targetApiURL, this.targetLogIntakeURL, this.targetWebhookIntakeURL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,27 @@
import hudson.RelativePath;
import hudson.model.Descriptor;
import hudson.util.FormValidation;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.datadog.jenkins.plugins.datadog.DatadogClient;
import org.datadog.jenkins.plugins.datadog.DatadogUtilities;
import org.datadog.jenkins.plugins.datadog.clients.DatadogAgentClient;
import org.datadog.jenkins.plugins.datadog.configuration.api.intake.DatadogSite;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;

import javax.annotation.Nonnull;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger;

@Symbol("datadogAgentConfiguration")
public class DatadogAgentConfiguration extends DatadogClientConfiguration {

Expand All @@ -45,13 +48,19 @@
private final Integer agentPort;
private final Integer agentLogCollectionPort;
private final Integer agentTraceCollectionPort;
private final DatadogSite site;

@DataBoundConstructor
public DatadogAgentConfiguration(String agentHost, Integer agentPort, Integer agentLogCollectionPort, Integer agentTraceCollectionPort) {
public DatadogAgentConfiguration(String agentHost, Integer agentPort, Integer agentLogCollectionPort, Integer agentTraceCollectionPort, String site) {
this(agentHost, agentPort, agentLogCollectionPort, agentTraceCollectionPort, StringUtils.isNotBlank(site) ? DatadogSite.valueOf(site) : null);
}

public DatadogAgentConfiguration(String agentHost, Integer agentPort, Integer agentLogCollectionPort, Integer agentTraceCollectionPort, DatadogSite site) {
this.agentHost = agentHost;
this.agentPort = agentPort;
this.agentLogCollectionPort = agentLogCollectionPort;
this.agentTraceCollectionPort = agentTraceCollectionPort;
this.site = site;
}

public String getAgentHost() {
Expand All @@ -70,6 +79,10 @@
return agentTraceCollectionPort;
}

public DatadogSite getSite() {
return site;
}

@Override
public DatadogClient createClient() {
return new DatadogAgentClient(agentHost, agentPort, agentLogCollectionPort, agentTraceCollectionPort);
Expand Down Expand Up @@ -127,6 +140,11 @@
return variables;
}

@Override
public String getSiteName() {
return site != null ? site.getSiteName() : null;
}

@Override
public Descriptor<DatadogClientConfiguration> getDescriptor() {
Jenkins jenkins = Jenkins.getInstanceOrNull();
Expand Down Expand Up @@ -218,6 +236,17 @@
return FormValidation.ok("Success!");
}

@RequirePOST
public ListBoxModel doFillSiteItems() {

Check warning

Code scanning / Jenkins Security Scan

Stapler: Missing permission check Warning

Potential missing permission check in DatadogAgentConfigurationDescriptor#doFillSiteItems
DatadogSite[] siteValues = DatadogSite.values();
ListBoxModel.Option[] values = new ListBoxModel.Option[siteValues.length + 1];
values[0] = new ListBoxModel.Option("");
for (int i = 0; i < siteValues.length; i++) {
values[i + 1] = new ListBoxModel.Option(siteValues[i].name());
}
return new ListBoxModel(values);
}

public static String getDefaultAgentHost() {
Map<String, String> envVars = System.getenv();

Expand Down Expand Up @@ -331,11 +360,12 @@
return Objects.equals(agentHost, that.agentHost)
&& Objects.equals(agentPort, that.agentPort)
&& Objects.equals(agentLogCollectionPort, that.agentLogCollectionPort)
&& Objects.equals(agentTraceCollectionPort, that.agentTraceCollectionPort);
&& Objects.equals(agentTraceCollectionPort, that.agentTraceCollectionPort)
&& Objects.equals(site, that.site);
}

@Override
public int hashCode() {
return Objects.hash(agentHost, agentPort, agentLogCollectionPort, agentTraceCollectionPort);
return Objects.hash(agentHost, agentPort, agentLogCollectionPort, agentTraceCollectionPort, site);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ public Map<String, String> toEnvironmentVariables() {
return variables;
}

@Override
public String getSiteName() {
return intake.getSiteName();
}

@Override
public Descriptor<DatadogClientConfiguration> getDescriptor() {
Jenkins jenkins = Jenkins.getInstanceOrNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import hudson.model.Describable;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import org.datadog.jenkins.plugins.datadog.DatadogClient;

import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import jenkins.model.Jenkins;
import org.datadog.jenkins.plugins.datadog.DatadogClient;

public abstract class DatadogClientConfiguration implements Describable<DatadogClientConfiguration>, Serializable {

Expand All @@ -20,6 +22,9 @@ public abstract class DatadogClientConfiguration implements Describable<DatadogC

public abstract Map<String, String> toEnvironmentVariables();

@Nullable
public abstract String getSiteName();

public static abstract class DatadogClientConfigurationDescriptor extends Descriptor<DatadogClientConfiguration> {
public static List<DatadogClientConfigurationDescriptor> all() {
Jenkins jenkins = Jenkins.getInstanceOrNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.kohsuke.stapler.DataBoundConstructor;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Objects;

Expand Down Expand Up @@ -74,7 +75,8 @@ public String getHelpFile() {
return getHelpFile("siteBlock");
}

public static DatadogSite getDefaultSite() {
@Nullable
public static DatadogSite getSite() {
String site = System.getenv().get(DATADOG_SITE_PROPERTY);
if (site != null) {
try {
Expand All @@ -84,6 +86,14 @@ public static DatadogSite getDefaultSite() {
"Illegal " + DATADOG_SITE_PROPERTY + " environment property value set: " + site +
". Allowed values are " + Arrays.toString(DatadogSite.values()), e);
}
}
return null;
}

public static DatadogSite getDefaultSite() {
DatadogSite site = getSite();
if (site != null) {
return site;
} else {
return DEFAULT_DATADOG_SITE_VALUE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,40 @@ of this software and associated documentation files (the "Software"), to deal

package org.datadog.jenkins.plugins.datadog.listeners;

import static org.datadog.jenkins.plugins.datadog.DatadogUtilities.cleanUpTraceActions;
import static org.datadog.jenkins.plugins.datadog.traces.TracerConstants.SPAN_ID_ENVVAR_KEY;
import static org.datadog.jenkins.plugins.datadog.traces.TracerConstants.TRACE_ID_ENVVAR_KEY;

import com.cloudbees.workflow.rest.external.RunExt;
import com.cloudbees.workflow.rest.external.StageNodeExt;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.*;
import hudson.model.listeners.RunListener;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import org.apache.commons.lang.StringUtils;
import org.datadog.jenkins.plugins.datadog.DatadogClient;
import org.datadog.jenkins.plugins.datadog.DatadogEvent;
import org.datadog.jenkins.plugins.datadog.DatadogGlobalConfiguration;
import org.datadog.jenkins.plugins.datadog.DatadogUtilities;
import org.datadog.jenkins.plugins.datadog.clients.ClientHolder;
import org.datadog.jenkins.plugins.datadog.configuration.DatadogClientConfiguration;
import org.datadog.jenkins.plugins.datadog.events.BuildAbortedEventImpl;
import org.datadog.jenkins.plugins.datadog.events.BuildFinishedEventImpl;
import org.datadog.jenkins.plugins.datadog.events.BuildStartedEventImpl;
import org.datadog.jenkins.plugins.datadog.metrics.Metrics;
import org.datadog.jenkins.plugins.datadog.metrics.MetricsClient;
import org.datadog.jenkins.plugins.datadog.model.*;
import org.datadog.jenkins.plugins.datadog.model.BuildData;
import org.datadog.jenkins.plugins.datadog.model.GitCommitAction;
import org.datadog.jenkins.plugins.datadog.model.GitRepositoryAction;
import org.datadog.jenkins.plugins.datadog.model.PipelineQueueInfoAction;
import org.datadog.jenkins.plugins.datadog.model.TraceInfoAction;
import org.datadog.jenkins.plugins.datadog.traces.BuildSpanAction;
import org.datadog.jenkins.plugins.datadog.traces.BuildSpanManager;
import org.datadog.jenkins.plugins.datadog.traces.message.TraceSpan;
Expand All @@ -50,18 +67,6 @@ of this software and associated documentation files (the "Software"), to deal
import org.datadog.jenkins.plugins.datadog.util.SuppressFBWarnings;
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;

import static org.datadog.jenkins.plugins.datadog.DatadogUtilities.cleanUpTraceActions;
import static org.datadog.jenkins.plugins.datadog.traces.TracerConstants.SPAN_ID_ENVVAR_KEY;
import static org.datadog.jenkins.plugins.datadog.traces.TracerConstants.TRACE_ID_ENVVAR_KEY;


/**
* This class registers an {@link RunListener} to trigger events and calculate metrics:
* - When a build initializes, the {@link #onInitialize(Run)} method will be invoked.
Expand Down Expand Up @@ -411,6 +416,15 @@ public void onFinalized(Run run) {
return;
}

DatadogGlobalConfiguration datadogConfiguration = DatadogUtilities.getDatadogGlobalDescriptor();
if (datadogConfiguration != null && datadogConfiguration.getEnableCiVisibility()) {
DatadogClientConfiguration clientConfiguration = datadogConfiguration.getDatadogClientConfiguration();
String siteName = clientConfiguration.getSiteName();
if (StringUtils.isNotBlank(siteName)) {
run.addAction(new DatadogLinkAction(buildData, siteName));
}
}

traceWriter.submitBuild(buildData, run);
logger.fine("End DatadogBuildListener#onFinalized");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.datadog.jenkins.plugins.datadog.model;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import hudson.model.Action;
import org.datadog.jenkins.plugins.datadog.util.conversion.DatadogConverter;
import org.datadog.jenkins.plugins.datadog.util.conversion.VersionedConverter;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import static org.datadog.jenkins.plugins.datadog.util.conversion.VersionedConverter.ignoreOldData;

public class DatadogLinkAction implements Action {

private final String url;

public DatadogLinkAction(BuildData buildData, String siteName) {
String query = String.format("ci_level:pipeline @ci.pipeline.name:\"%s\" @ci.pipeline.number:%s", buildData.getJobName(), buildData.getBuildNumber(""));
String urlEncodedQuery = URLEncoder.encode(query, StandardCharsets.UTF_8);
this.url = String.format("https://app.%s/ci/pipeline-executions?query=%s", siteName, urlEncodedQuery);
}

private DatadogLinkAction(String url) {
this.url = url;
}

@Override
public String getIconFileName() {
return "/plugin/datadog/icons/dd_icon_rgb.svg";
}

@Override
public String getDisplayName() {
return "View in Datadog";
}

@Override
public String getUrlName() {
return url;
}

public static final class ConverterImpl extends DatadogConverter<DatadogLinkAction> {
public ConverterImpl(XStream xs) {
super(ignoreOldData(), new ConverterV1());
}
}

public static final class ConverterV1 extends VersionedConverter<DatadogLinkAction> {
private static final int VERSION = 1;

public ConverterV1() {
super(VERSION);
}

@Override
public void marshal(DatadogLinkAction action, HierarchicalStreamWriter writer, MarshallingContext context) {
writeField("url", action.url, writer, context);
}

@Override
public DatadogLinkAction unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
String url = readField(reader, context, String.class);
return new DatadogLinkAction(url);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@
method="checkTraceConnectivity" with="agentHost,agentTraceCollectionPort"
/>

<f:entry title="Datadog Site" field="site">
<f:select/>
</f:entry>

</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
Select your Datadog site.
See <a target="_blank" href="https://docs.datadoghq.com/getting_started/site/">Datadog documentation</a> for more information about sites.
</div>
Binary file added src/main/webapp/icons/dd_icon_rgb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading