Skip to content

Commit d151527

Browse files
authored
Fix APM Server version parsing (#2313)
1 parent a3ef2a7 commit d151527

File tree

5 files changed

+91
-18
lines changed

5 files changed

+91
-18
lines changed

CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ endif::[]
3333
3434
[float]
3535
===== Bug fixes
36+
* Fix error with parsing APM Server version for 7.16+ - {pull}2313[#2313]
3637
3738
[[release-notes-1.x]]
3839
=== Java Agent version 1.x

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

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@
2222
import co.elastic.apm.agent.util.Version;
2323
import com.dslplatform.json.DslJson;
2424
import com.dslplatform.json.JsonReader;
25-
import com.dslplatform.json.MapConverter;
2625
import com.dslplatform.json.Nullable;
2726
import com.dslplatform.json.ObjectConverter;
2827
import org.slf4j.Logger;
2928
import org.slf4j.LoggerFactory;
3029

3130
import java.net.HttpURLConnection;
3231
import java.util.Collections;
32+
import java.util.LinkedHashMap;
3333
import java.util.List;
3434
import java.util.Map;
35+
import java.util.Objects;
3536
import java.util.concurrent.Callable;
3637
import java.util.concurrent.Future;
3738
import java.util.concurrent.ThreadPoolExecutor;
@@ -41,8 +42,9 @@
4142
public class ApmServerHealthChecker implements Callable<Version> {
4243
private static final Logger logger = LoggerFactory.getLogger(ApmServerHealthChecker.class);
4344

45+
private static final DslJson<Object> dslJson = new DslJson<>(new DslJson.Settings<>());
46+
4447
private final ApmServerClient apmServerClient;
45-
private final DslJson<Object> dslJson = new DslJson<>(new DslJson.Settings<>());
4648

4749
public ApmServerHealthChecker(ApmServerClient apmServerClient) {
4850
this.apmServerClient = apmServerClient;
@@ -81,24 +83,11 @@ public Version withConnection(HttpURLConnection connection) {
8183
// prints out the version info of the APM Server
8284
String body = HttpUtils.readToString(connection.getInputStream());
8385
logger.info("Elastic APM server is available: {}", body);
84-
JsonReader<Object> reader = dslJson.newReader(body.getBytes(UTF_8));
85-
reader.startObject();
86-
String versionString;
87-
try {
88-
// newer APM server versions contain a flat map at the JSON root
89-
versionString = MapConverter.deserialize(reader).get("version");
90-
} catch (Exception e) {
91-
// 6.x APM server versions' JSON has a root object of which value is the same map
92-
reader = dslJson.newReader(body.getBytes(UTF_8));
93-
reader.startObject();
94-
Map<String, Object> root = ObjectConverter.deserializeMap(reader);
95-
//noinspection unchecked
96-
versionString = ((Map<String, String>) root.get("ok")).get("version");
97-
}
86+
Version version = parseVersion(body);
9887
if (logger.isDebugEnabled()) {
99-
logger.debug("APM server {} version is: {}", connection.getURL(), versionString);
88+
logger.debug("APM server {} version is: {}", connection.getURL(), version);
10089
}
101-
return Version.of(versionString);
90+
return version;
10291
} catch (Exception e) {
10392
logger.warn("Failed to parse version of APM server {}: {}", connection.getURL(), e.getMessage());
10493
}
@@ -115,4 +104,23 @@ public Version withConnection(HttpURLConnection connection) {
115104
}
116105
return Version.UNKNOWN_VERSION;
117106
}
107+
108+
static Version parseVersion(String body) throws java.io.IOException {
109+
JsonReader<Object> reader = dslJson.newReader(body.getBytes(UTF_8));
110+
reader.startObject();
111+
String versionString;
112+
try {
113+
// APM server 7.0+ contain a flat map at the JSON root
114+
LinkedHashMap<String, Object> responseJsonMap = ObjectConverter.deserializeMap(reader);
115+
versionString = (String) Objects.requireNonNull(responseJsonMap.get("version"));
116+
} catch (Exception e) {
117+
// 6.x APM server versions' JSON has a root object of which value is the same map
118+
reader = dslJson.newReader(body.getBytes(UTF_8));
119+
reader.startObject();
120+
Map<String, Object> root = ObjectConverter.deserializeMap(reader);
121+
//noinspection unchecked
122+
versionString = ((Map<String, String>) root.get("ok")).get("version");
123+
}
124+
return Version.of(versionString);
125+
}
118126
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,16 @@ public int compareTo(Version another) {
7272
}
7373
return 0;
7474
}
75+
76+
@Override
77+
public String toString() {
78+
StringBuilder sb = new StringBuilder();
79+
for (int i = 0; i < numbers.length; i++) {
80+
sb.append(numbers[i]);
81+
if (i < numbers.length - 1) {
82+
sb.append('.');
83+
}
84+
}
85+
return sb.toString();
86+
}
7587
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package co.elastic.apm.agent.report;
20+
21+
import co.elastic.apm.agent.util.Version;
22+
import org.junit.jupiter.api.Test;
23+
24+
import java.io.IOException;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
28+
class ApmServerHealthCheckerTest {
29+
30+
@Test
31+
void testParseVersion() throws IOException {
32+
// 7.16+
33+
String body = "{ \"build_date\": \"2021-11-04T12:50:39Z\", \"build_sha\": \"74a2ccb4be966ebab82b9727caef355fe9097340\", \"publish_ready\": true, \"version\": \"8.0.0\"}";
34+
assertThat(ApmServerHealthChecker.parseVersion(body).compareTo(Version.of("8.0.0"))).isEqualTo(0);
35+
// 7.0 -> 7.15
36+
body = "{ \"build_date\": \"2021-03-06T04:41:35Z\", \"build_sha\": \"b706a93fac838d7ca44622d8d9686d2c3b3c8bde\", \"version\": \"7.11.2\"}";
37+
assertThat(ApmServerHealthChecker.parseVersion(body).compareTo(Version.of("7.11.2"))).isEqualTo(0);
38+
// 6.x
39+
body = "{\"ok\":{\"build_date\":\"2021-10-13T17:29:41Z\",\"build_sha\":\"04a84d8d3d0358af5e73b3581c4ba37fbdbc979e\",\"version\":\"6.8.20\"}}";
40+
assertThat(ApmServerHealthChecker.parseVersion(body).compareTo(Version.of("6.8.20"))).isEqualTo(0);
41+
}
42+
}

apm-agent-core/src/test/java/co/elastic/apm/agent/util/VersionTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,14 @@ void testVersion() {
3636
assertThat(Version.of("httpclient.4.5.13.redhat")).isEqualByComparingTo(Version.of("4.5.13"));
3737
assertThat(Version.of("httpclient.4.5.13-redhat")).isEqualByComparingTo(Version.of("4.5.13"));
3838
}
39+
40+
@Test
41+
void testToString() {
42+
System.out.println(Version.of(""));
43+
System.out.println(Version.of("1"));
44+
System.out.println(Version.of("1.2"));
45+
System.out.println(Version.of("1.2.3"));
46+
System.out.println(Version.of("1.2.3.4"));
47+
System.out.println(Version.of("1.2.3.ignore"));
48+
}
3949
}

0 commit comments

Comments
 (0)