Skip to content

Commit d943484

Browse files
authored
Implement user-agent spec (#2177)
* implement spec + test * annotate some nullable configuration items * prevent NPE:wq * fix other NPEs + cleanup * fix copyright * update changelog * post review changes
1 parent 9f36a55 commit d943484

File tree

20 files changed

+282
-95
lines changed

20 files changed

+282
-95
lines changed

CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ exclude known static files in all applications might be changed to `/app/static/
6060
* Switching last instrumentations (`trace_methods`, sparkjava, JDK `HttpServer` and Struts 2) to
6161
`TracerAwareInstrumentation` - {pull}#2170[#2170]
6262
* Replace concurrency plugin maps to `SpanConcurrentHashMap` ones - {pull}#2173[#2173]
63+
* Align User-Agent HTTP header with other APM agents - {pull}#2177[#2177]
6364
6465
[[release-notes-1.x]]
6566
=== Java Agent version 1.x

apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,14 +656,17 @@ public long getDelayTracerStartMs() {
656656
return delayTracerStart.get().getMillis();
657657
}
658658

659+
@Nullable
659660
public String getServiceVersion() {
660661
return serviceVersion.get();
661662
}
662663

664+
@Nullable
663665
public String getHostname() {
664666
return hostname.get();
665667
}
666668

669+
@Nullable
667670
public String getEnvironment() {
668671
return environment.get();
669672
}

apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/StartupInfo.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ public class StartupInfo extends AbstractLifecycleListener {
4444
private final String elasticApmVersion;
4545

4646
public StartupInfo() {
47-
final String version = VersionUtils.getAgentVersion();
48-
if (version != null) {
49-
elasticApmVersion = version;
50-
} else {
51-
elasticApmVersion = "(unknown version)";
52-
}
47+
elasticApmVersion = VersionUtils.getAgentVersion();
5348
}
5449

5550
private static String getJvmAndOsVersionString() {

apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracerBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ private ElasticApmTracer build(boolean startTracer) {
142142
lifecycleListeners.add(scheduleReloadAtRate(configurationRegistry, 30, TimeUnit.SECONDS));
143143
}
144144

145-
ApmServerClient apmServerClient = new ApmServerClient(configurationRegistry.getConfig(ReporterConfiguration.class));
145+
ApmServerClient apmServerClient = new ApmServerClient(configurationRegistry.getConfig(ReporterConfiguration.class), configurationRegistry.getConfig(CoreConfiguration.class));
146146
Future<MetaData> metaData = MetaData.create(configurationRegistry, ephemeralId);
147147
if (addApmServerConfigSource) {
148148
// adding remote configuration source last will make it highest priority

apm-agent-core/src/main/java/co/elastic/apm/agent/impl/payload/Service.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public String getEnvironment() {
149149
/**
150150
* Environment name of the service, e.g. "production" or "staging"
151151
*/
152-
public Service withEnvironment(String environment) {
152+
public Service withEnvironment(@Nullable String environment) {
153153
this.environment = environment;
154154
return this;
155155
}
@@ -181,7 +181,7 @@ public String getVersion() {
181181
/**
182182
* Version of the service emitting this event
183183
*/
184-
public Service withVersion(String version) {
184+
public Service withVersion(@Nullable String version) {
185185
this.version = version;
186186
return this;
187187
}

apm-agent-core/src/main/java/co/elastic/apm/agent/impl/payload/ServiceFactory.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,10 @@ public Service createService(CoreConfiguration coreConfiguration, String ephemer
2828
.withName(coreConfiguration.getServiceName())
2929
.withVersion(coreConfiguration.getServiceVersion())
3030
.withEnvironment(coreConfiguration.getEnvironment())
31-
.withAgent(new Agent("java", getAgentVersion(), ephemeralId))
31+
.withAgent(new Agent("java", VersionUtils.getAgentVersion(), ephemeralId))
3232
.withRuntime(new RuntimeInfo("Java", System.getProperty("java.version")))
3333
.withLanguage(new Language("Java", System.getProperty("java.version")))
3434
.withNode(new Node(coreConfiguration.getServiceNodeName()));
3535
}
3636

37-
private String getAgentVersion() {
38-
String version = VersionUtils.getAgentVersion();
39-
if (version == null) {
40-
return "unknown";
41-
}
42-
return version;
43-
}
4437
}

apm-agent-core/src/main/java/co/elastic/apm/agent/report/ApmServerClient.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package co.elastic.apm.agent.report;
2020

21+
import co.elastic.apm.agent.configuration.CoreConfiguration;
2122
import co.elastic.apm.agent.report.ssl.SslUtils;
2223
import co.elastic.apm.agent.util.UrlConnectionUtils;
2324
import co.elastic.apm.agent.util.Version;
@@ -65,7 +66,6 @@
6566
public class ApmServerClient {
6667

6768
private static final Logger logger = LoggerFactory.getLogger(ApmServerClient.class);
68-
private static final String USER_AGENT = "elasticapm-java/" + VersionUtils.getAgentVersion();
6969
private static final Version VERSION_6_7 = Version.of("6.7.0");
7070
private static final Version VERSION_7_9 = Version.of("7.9.0");
7171
private static final Version VERSION_7_0 = Version.of("7.0.0");
@@ -77,9 +77,12 @@ public class ApmServerClient {
7777
private final AtomicInteger errorCount = new AtomicInteger();
7878
private final ApmServerHealthChecker healthChecker;
7979

80-
public ApmServerClient(ReporterConfiguration reporterConfiguration) {
80+
private final String userAgent;
81+
82+
public ApmServerClient(ReporterConfiguration reporterConfiguration, CoreConfiguration coreConfiguration) {
8183
this.reporterConfiguration = reporterConfiguration;
8284
this.healthChecker = new ApmServerHealthChecker(this);
85+
this.userAgent = getUserAgent(coreConfiguration);
8386
}
8487

8588
public void start() {
@@ -159,7 +162,7 @@ private HttpURLConnection startRequestToUrl(URL url) throws IOException {
159162
connection.setRequestProperty("Authorization", authHeaderValue);
160163
}
161164

162-
connection.setRequestProperty("User-Agent", USER_AGENT);
165+
connection.setRequestProperty("User-Agent", userAgent);
163166
connection.setConnectTimeout((int) reporterConfiguration.getServerTimeout().getMillis());
164167
connection.setReadTimeout((int) reporterConfiguration.getServerTimeout().getMillis());
165168
return (HttpURLConnection) connection;
@@ -320,7 +323,7 @@ public boolean supportsLogsEndpoint() {
320323
return isAtLeast(VERSION_7_9);
321324
}
322325

323-
public boolean supportsNumericUrlPort(){
326+
public boolean supportsNumericUrlPort() {
324327
return isAtLeast(VERSION_7_0);
325328
}
326329

@@ -357,7 +360,7 @@ public interface ConnectionHandler<T> {
357360
/**
358361
* Gets the {@link HttpURLConnection} after the connection has been established and returns a result,
359362
* for example the status code or the response body.
360-
*
363+
* <p>
361364
* NOTE: do not call {@link InputStream#close()} as that is handled by {@link ApmServerClient}
362365
*
363366
* @param connection the connection
@@ -368,4 +371,18 @@ public interface ConnectionHandler<T> {
368371
T withConnection(HttpURLConnection connection) throws IOException;
369372
}
370373

374+
private static String getUserAgent(CoreConfiguration coreConfiguration) {
375+
StringBuilder userAgent = new StringBuilder();
376+
userAgent.append("apm-agent-java/").append(VersionUtils.getAgentVersion());
377+
String serviceName = coreConfiguration.getServiceName();
378+
String serviceVersion = coreConfiguration.getServiceVersion();
379+
if (!serviceName.isEmpty()) {
380+
userAgent.append(" (").append(serviceName);
381+
if (serviceVersion != null && !serviceVersion.isEmpty()) {
382+
userAgent.append(" ").append(serviceVersion);
383+
}
384+
userAgent.append(")");
385+
}
386+
return userAgent.toString();
387+
}
371388
}

apm-agent-core/src/main/java/co/elastic/apm/agent/util/VersionUtils.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ public final class VersionUtils {
5151
private VersionUtils() {
5252
}
5353

54-
@Nullable
5554
public static String getAgentVersion() {
56-
return AGENT_VERSION;
55+
return AGENT_VERSION != null ? AGENT_VERSION : "unknown";
5756
}
5857

5958
@Nullable

apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/ApmServerConfigurationSourceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void setUp() throws Exception {
7474
mockApmServer.stubFor(get(urlEqualTo("/")).willReturn(okForJson(Map.of("version", "7.0.0"))));
7575
mockApmServer.stubFor(post(urlEqualTo("/config/v1/agents")).willReturn(okForJson(Map.of("foo", "bar")).withHeader("ETag", "foo")));
7676
mockApmServer.stubFor(post(urlEqualTo("/config/v1/agents")).withHeader("If-None-Match", equalTo("foo")).willReturn(status(304)));
77-
apmServerClient = new ApmServerClient(config.getConfig(ReporterConfiguration.class));
77+
apmServerClient = new ApmServerClient(config.getConfig(ReporterConfiguration.class), config.getConfig(CoreConfiguration.class));
7878
apmServerClient.start(List.of(new URL("http", "localhost", mockApmServer.port(), "/")));
7979
mockLogger = mock(Logger.class);
8080
configurationSource = new ApmServerConfigurationSource(

apm-agent-core/src/test/java/co/elastic/apm/agent/report/ApmServerClientProxySupportTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package co.elastic.apm.agent.report;
2020

21+
import co.elastic.apm.agent.configuration.CoreConfiguration;
2122
import co.elastic.apm.agent.configuration.SpyConfiguration;
2223
import io.undertow.Undertow;
2324
import io.undertow.io.Sender;
@@ -27,6 +28,7 @@
2728
import org.junit.jupiter.api.Test;
2829
import org.slf4j.Logger;
2930
import org.slf4j.LoggerFactory;
31+
import org.stagemonitor.configuration.ConfigurationRegistry;
3032
import org.testcontainers.Testcontainers;
3133
import org.testcontainers.containers.BindMode;
3234
import org.testcontainers.containers.GenericContainer;
@@ -212,10 +214,11 @@ private void setSystemProxyCredentialProperties() {
212214
}
213215

214216
private static ApmServerClient createAndStartClient(boolean useProxy) {
215-
ReporterConfiguration config = SpyConfiguration.createSpyConfig().getConfig(ReporterConfiguration.class);
217+
ConfigurationRegistry spyConfig = SpyConfiguration.createSpyConfig();
218+
ReporterConfiguration config = spyConfig.getConfig(ReporterConfiguration.class);
216219

217220
doReturn(Collections.singletonList(useProxy ? proxyUrl : directUrl)).when(config).getServerUrls();
218-
ApmServerClient client = new ApmServerClient(config);
221+
ApmServerClient client = new ApmServerClient(config, spyConfig.getConfig(CoreConfiguration.class));
219222
client.start();
220223
return client;
221224
}

0 commit comments

Comments
 (0)