Skip to content

Commit c8c10ff

Browse files
authored
Merge pull request #2558 from newrelic/json-fix
JSON load fix
2 parents 24125d9 + 6190d9d commit c8c10ff

File tree

3 files changed

+62
-40
lines changed

3 files changed

+62
-40
lines changed

instrumentation/opentelemetry-sdk-extension-autoconfigure-1.28.0/src/main/java/com/nr/agent/instrumentation/utils/span/AttributeMapper.java

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,29 @@
77
package com.nr.agent.instrumentation.utils.span;
88

99
import com.newrelic.api.agent.NewRelic;
10+
import com.newrelic.bootstrap.EmbeddedJarFilesImpl;
1011
import io.opentelemetry.api.trace.SpanKind;
1112
import org.json.simple.JSONArray;
1213
import org.json.simple.JSONObject;
1314
import org.json.simple.parser.JSONParser;
15+
import org.json.simple.parser.ParseException;
1416

17+
import java.io.IOException;
1518
import java.io.InputStream;
1619
import java.io.InputStreamReader;
20+
import java.nio.charset.StandardCharsets;
1721
import java.util.ArrayList;
1822
import java.util.HashMap;
1923
import java.util.List;
2024
import java.util.Map;
2125
import java.util.Set;
26+
import java.util.jar.JarEntry;
27+
import java.util.jar.JarFile;
2228
import java.util.logging.Level;
2329

2430
public class AttributeMapper {
2531
private static final String MAPPING_RESOURCE = "attribute-mappings.json";
32+
private static final String INSTRUMENTATION_JAR_LOCATION = "instrumentation/opentelemetry-sdk-extension-autoconfigure-1.28.0-1.0";
2633

2734
private static volatile AttributeMapper instance;
2835
private final Map<SpanKind, Map<AttributeType, List<AttributeKey>>> mappings = new HashMap<>();
@@ -42,35 +49,34 @@ public static AttributeMapper getInstance() {
4249
if (instance == null) {
4350
synchronized (AttributeMapper.class) {
4451
if (instance == null) {
45-
try (InputStream inputStream = AttributeMapper.class.getClassLoader().getResourceAsStream(MAPPING_RESOURCE);
46-
InputStreamReader reader = new InputStreamReader(inputStream)) {
47-
48-
instance = new AttributeMapper();
49-
50-
JSONParser parser = new JSONParser();
51-
JSONArray rootArray = (JSONArray) parser.parse(reader);
52-
53-
for (Object spanKindObj : rootArray) {
54-
// Span kind and a list of attribute types
55-
JSONObject spanKindObject = (JSONObject) spanKindObj;
56-
SpanKind spanKind = SpanKind.valueOf((String) spanKindObject.get("spanKind"));
57-
JSONArray jsonAttributeTypes = (JSONArray) spanKindObject.get("attributeTypes");
58-
59-
for (Object typeObj : jsonAttributeTypes) {
60-
JSONObject categoryObject = (JSONObject) typeObj;
61-
62-
// Grab the attribute type (Port, Host, etc) and then iterate over the actual attribute keys
63-
AttributeType attributeType = AttributeType.valueOf((String) categoryObject.get("attributeType"));
64-
JSONArray jsonAttributes = (JSONArray) categoryObject.get("attributes");
65-
for (Object jsonAttribute : jsonAttributes) {
66-
JSONObject attribute = (JSONObject) jsonAttribute;
67-
instance.addAttributeMapping(spanKind, attributeType, new AttributeKey((String) attribute.get("name"), (String) attribute.get("version")));
52+
try {
53+
JSONArray rootArray = parseJsonResourceFromAgentJar(INSTRUMENTATION_JAR_LOCATION, MAPPING_RESOURCE);
54+
55+
if (rootArray != null) {
56+
instance = new AttributeMapper();
57+
58+
for (Object spanKindObj : rootArray) {
59+
// Span kind and a list of attribute types
60+
JSONObject spanKindObject = (JSONObject) spanKindObj;
61+
SpanKind spanKind = SpanKind.valueOf((String) spanKindObject.get("spanKind"));
62+
JSONArray jsonAttributeTypes = (JSONArray) spanKindObject.get("attributeTypes");
63+
64+
for (Object typeObj : jsonAttributeTypes) {
65+
JSONObject categoryObject = (JSONObject) typeObj;
66+
67+
// Grab the attribute type (Port, Host, etc) and then iterate over the actual attribute keys
68+
AttributeType attributeType = AttributeType.valueOf((String) categoryObject.get("attributeType"));
69+
JSONArray jsonAttributes = (JSONArray) categoryObject.get("attributes");
70+
for (Object jsonAttribute : jsonAttributes) {
71+
JSONObject attribute = (JSONObject) jsonAttribute;
72+
instance.addAttributeMapping(spanKind, attributeType, new AttributeKey((String) attribute.get("name"), (String) attribute.get("version")));
73+
}
6874
}
6975
}
7076
}
7177
} catch (Exception e) {
72-
// Should never happen...
73-
NewRelic.getAgent().getLogger().log(Level.SEVERE, "Unable to read OTel attribute mappings", e);
78+
// Should never happen...Maybe
79+
NewRelic.getAgent().getLogger().log(Level.SEVERE, "OTel AttributeMapper: Unable to read OTel attribute mappings: {0}", e.getMessage());
7480
}
7581
}
7682
}
@@ -120,4 +126,32 @@ Map<SpanKind, Map<AttributeType, List<AttributeKey>>> getMappings() {
120126
private void addAttributeMapping(SpanKind spanKind, AttributeType attributeType, AttributeKey attributeKey) {
121127
this.mappings.get(spanKind).get(attributeType).add(attributeKey);
122128
}
129+
130+
private static JSONArray parseJsonResourceFromAgentJar(String instrumentationJarLocation, String jsonResourceName) {
131+
try (JarFile instrumentationJarFile = new JarFile(EmbeddedJarFilesImpl.INSTANCE.getJarFileInAgent(instrumentationJarLocation))) {
132+
JarEntry jsonFileJarEntry = instrumentationJarFile.getJarEntry(jsonResourceName);
133+
134+
if (jsonFileJarEntry != null) {
135+
StringBuilder jsonStringBuilder = new StringBuilder();
136+
try (InputStream inputStream = instrumentationJarFile.getInputStream(jsonFileJarEntry)) {
137+
byte[] buffer = new byte[1024];
138+
int bytesRead;
139+
while ((bytesRead = inputStream.read(buffer)) != -1) {
140+
jsonStringBuilder.append(new String(buffer, 0, bytesRead, StandardCharsets.UTF_8));
141+
}
142+
}
143+
String jsonString = jsonStringBuilder.toString();
144+
145+
JSONParser parser = new JSONParser();
146+
return (JSONArray) parser.parse(jsonString);
147+
} else {
148+
NewRelic.getAgent().getLogger().log(Level.SEVERE, "OTel AttributeMapper: JarEntry `{0}` not found in the {1} jar file", jsonResourceName, instrumentationJarLocation);
149+
}
150+
} catch (IOException e) {
151+
NewRelic.getAgent().getLogger().log(Level.SEVERE, "OTel AttributeMapper: IOException constructing JarFile: {0}", e.getMessage());
152+
} catch (ParseException e) {
153+
NewRelic.getAgent().getLogger().log(Level.SEVERE, "OTel AttributeMapper: ParseException parsing attribute mapping JSON: {0}", e.getMessage());
154+
}
155+
return null;
156+
}
123157
}

instrumentation/opentelemetry-sdk-extension-autoconfigure-1.28.0/src/main/java/io/opentelemetry/sdk/trace/ExitTracerSpan.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,12 @@ private void reportClientSpan() {
285285

286286
private AttributeKey<String> generateStringAttributeKey(SpanKind spanKind, com.nr.agent.instrumentation.utils.span.AttributeType attributeType) {
287287
return AttributeKey.stringKey(
288-
attributeMapper.findProperOtelKey(SpanKind.CLIENT, attributeType, attributes.keySet()));
288+
attributeMapper.findProperOtelKey(spanKind, attributeType, attributes.keySet()));
289289
}
290290

291291
private AttributeKey<Long> generateLongAttributeKey(SpanKind spanKind, com.nr.agent.instrumentation.utils.span.AttributeType attributeType) {
292292
return AttributeKey.longKey(
293-
attributeMapper.findProperOtelKey(SpanKind.CLIENT, attributeType, attributes.keySet()));
293+
attributeMapper.findProperOtelKey(spanKind, attributeType, attributes.keySet()));
294294
}
295295

296296

instrumentation/opentelemetry-sdk-extension-autoconfigure-1.28.0/src/test/java/com/nr/agent/instrumentation/utils/span/AttributeMapperTest.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ public void getInstance_withValidJson_createsValidMapper() {
2828
for (SpanKind spanKind : SpanKind.values()) {
2929
Map<AttributeType, List<AttributeKey>> attributeTypesBySpan = mappings.get(spanKind);
3030
assertEquals(14, attributeTypesBySpan.size());
31-
32-
assertEquals(2, attributeTypesBySpan.get(AttributeType.Port).size());
33-
assertEquals(2, attributeTypesBySpan.get(AttributeType.Host).size());
3431
}
3532
}
3633

@@ -61,22 +58,13 @@ public void findProperOtelKey_returnsEmptyString_whenRequestedKeyNotFound() {
6158
public void attributeKeyClass_properlyParsesSemanticConventionField() {
6259
AttributeMapper attributeMapper = AttributeMapper.getInstance();
6360

64-
// Comma delimited list of semantic conventions exist in the SERVER -> Port
6561
Map<SpanKind, Map<AttributeType, List<AttributeKey>>> attributes = attributeMapper.getMappings();
6662
AttributeKey attribute = attributes.get(SpanKind.SERVER).get(AttributeType.Port).get(0);
67-
assertEquals(3, attribute.getSemanticConventions().length);
63+
assertEquals(1, attribute.getSemanticConventions().length);
6864
assertEquals("HTTP-Server:1.23", attribute.getSemanticConventions()[0]);
69-
assertEquals("HTTP-Server:1.24", attribute.getSemanticConventions()[1]);
70-
assertEquals("HTTP-Server:1.25", attribute.getSemanticConventions()[2]);
7165

72-
// Only one in SERVER -> Host
7366
attribute = attributes.get(SpanKind.SERVER).get(AttributeType.Host).get(0);
7467
assertEquals(1, attribute.getSemanticConventions().length);
7568
assertEquals("HTTP-Server:1.23", attribute.getSemanticConventions()[0]);
76-
77-
// Handle empty semantic convention field. INTERNAL -> Port
78-
attribute = attributes.get(SpanKind.INTERNAL).get(AttributeType.Port).get(0);
79-
assertEquals(1, attribute.getSemanticConventions().length);
80-
assertEquals("", attribute.getSemanticConventions()[0]);
8169
}
8270
}

0 commit comments

Comments
 (0)