-
Notifications
You must be signed in to change notification settings - Fork 54
/
AbstractGitStepHandler.java
154 lines (136 loc) · 6.96 KB
/
AbstractGitStepHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Copyright The Original Author or Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.jenkins.plugins.opentelemetry.job;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import io.jenkins.plugins.opentelemetry.semconv.JenkinsOtelSemanticAttributes;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import org.eclipse.jgit.transport.URIish;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.net.URISyntaxException;
import java.util.logging.Logger;
public abstract class AbstractGitStepHandler implements StepHandler {
private final static Logger LOGGER = Logger.getLogger(AbstractGitStepHandler.class.getName());
public String searchGitUserName(@Nullable String credentialsId, @Nonnull WorkflowRun run) {
if (credentialsId == null) {
return null;
}
String gitUserName = credentialsId;
StandardUsernameCredentials credentials = CredentialsProvider.findCredentialById(credentialsId,
StandardUsernameCredentials.class,
run);
if (credentials != null && credentials.getUsername() != null) {
gitUserName = credentials.getUsername();
}
return gitUserName;
}
/**
* See:
* https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md
* https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols
*/
@VisibleForTesting
@Nonnull
public SpanBuilder createSpanBuilder(@Nonnull String gitUrl, @Nullable String gitBranch, @Nullable String credentialsId, @Nonnull String stepFunctionName, @Nonnull Tracer tracer, @Nonnull WorkflowRun run) throws URISyntaxException {
String gitUserName = searchGitUserName(credentialsId, run);
return createSpanBuilderFromGitDetails(gitUrl, gitBranch, gitUserName, stepFunctionName, tracer);
}
/**
* Visible for testing. User {@link #createSpanBuilder(String, String, String, String, Tracer, WorkflowRun)} instead of this method
*/
@VisibleForTesting
protected SpanBuilder createSpanBuilderFromGitDetails(@Nullable String gitUrl, @Nullable String gitBranch, @Nullable String gitUserName, @Nonnull String stepFunctionName, @Nonnull Tracer tracer) throws URISyntaxException {
URIish gitUri = new URIish(gitUrl);
String host = gitUri.getHost();
String gitRepositoryPath = normalizeGitRepositoryPath(gitUri);
final SpanBuilder spanBuilder;
if ("https".equals(gitUri.getScheme())) {
// HTTPS URL e.g. https://github.com/open-telemetry/opentelemetry-java
String spanName = stepFunctionName + ": " + host + "/" + gitRepositoryPath;
spanBuilder = tracer.spanBuilder(spanName);
spanBuilder
.setAttribute(SemanticAttributes.RPC_SYSTEM, gitUri.getScheme())
.setAttribute(SemanticAttributes.RPC_SERVICE, "git")
.setAttribute(SemanticAttributes.RPC_METHOD, "checkout")
.setAttribute(SemanticAttributes.NET_PEER_NAME, host)
.setAttribute(SemanticAttributes.PEER_SERVICE, "git")
.setAttribute(SemanticAttributes.HTTP_URL, sanitizeUrl(gitUri))
.setAttribute(SemanticAttributes.HTTP_METHOD, "POST")
.setSpanKind(SpanKind.CLIENT)
;
} else if ("ssh".equals(gitUri.getScheme())
|| (gitUri.getScheme() == null && gitUri.getHost() != null)) {
// SSH URL e.g. ssh://[email protected]/open-telemetry/opentelemetry-java.git
// SCP URL e.g. [email protected]:open-telemetry/opentelemetry-java.git
String spanName = stepFunctionName + ": " + host + "/" + gitRepositoryPath;
spanBuilder = tracer.spanBuilder(spanName);
spanBuilder
.setAttribute(SemanticAttributes.RPC_SYSTEM, "ssh")
.setAttribute(SemanticAttributes.RPC_SERVICE, "git")
.setAttribute(SemanticAttributes.RPC_METHOD, "checkout")
.setAttribute(SemanticAttributes.NET_PEER_NAME, host)
.setAttribute(SemanticAttributes.PEER_SERVICE, "git")
.setAttribute(SemanticAttributes.NET_TRANSPORT, SemanticAttributes.NetTransportValues.IP_TCP)
.setSpanKind(SpanKind.CLIENT)
;
} else if (("file".equals(gitUri.getScheme())
|| (gitUri.getScheme() == null && gitUri.getHost() == null))) {
// FILE URL e.g. file:///srv/git/project.git
// IMPLICIT FILE URL e.g. /srv/git/project.git
String spanName = stepFunctionName + ": " + gitRepositoryPath;
spanBuilder = tracer.spanBuilder(spanName);
} else {
// TODO document which case it is?
String spanName = stepFunctionName + ": " + host + "/" + gitRepositoryPath;
spanBuilder = tracer.spanBuilder(spanName);
}
spanBuilder.setAttribute(JenkinsOtelSemanticAttributes.GIT_REPOSITORY, gitRepositoryPath);
if (!Strings.isNullOrEmpty(gitBranch)) {
spanBuilder.setAttribute(JenkinsOtelSemanticAttributes.GIT_BRANCH, gitBranch);
}
if (!Strings.isNullOrEmpty(gitUserName)) {
spanBuilder.setAttribute(JenkinsOtelSemanticAttributes.GIT_USERNAME, gitUserName);
}
return spanBuilder;
}
private String normalizeGitRepositoryPath(URIish gitUri) {
String githubOrgAndRepository = gitUri.getPath();
if (githubOrgAndRepository.startsWith("/")) {
githubOrgAndRepository = githubOrgAndRepository.substring("/".length());
}
if (githubOrgAndRepository.endsWith(".git")) {
githubOrgAndRepository = githubOrgAndRepository.substring(0, githubOrgAndRepository.length() - ".git".length());
}
return githubOrgAndRepository;
}
/**
* Remove the `username` and the `password` params of the URL.
* <p>
* Example: "https://my_username:[email protected]/open-telemetry/opentelemetry-java.git" is sanitized as
* "https://github.com/open-telemetry/opentelemetry-java.git"
*
* @param gitUri to sanitize
* @return sanitized url
*/
@Nonnull
protected String sanitizeUrl(@Nonnull URIish gitUri) {
String normalizedUrl = gitUri.getScheme() + "://";
if (gitUri.getHost() != null) {
normalizedUrl += gitUri.getHost();
}
if (gitUri.getPort() != -1) {
normalizedUrl += ":" + gitUri.getPort();
}
normalizedUrl += gitUri.getPath();
return normalizedUrl;
}
}