Skip to content

Commit f9a5bf6

Browse files
committed
[DSM] Support schema expansion of maps with record values
1 parent 40eea52 commit f9a5bf6

File tree

2 files changed

+22
-18
lines changed

2 files changed

+22
-18
lines changed

dd-java-agent/instrumentation/avro/src/main/java/datadog/trace/instrumentation/avro/SchemaExtractor.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,18 @@ public static boolean extractProperty(
5050
return false;
5151
};
5252
}
53-
5453
break;
5554
case MAP:
5655
type = "object";
57-
description = "Map type";
56+
String keys = "string";
57+
String values = getType(field.schema().getValueType().getType().getName());
58+
if (values == "record") {
59+
values = "#/components/schemas/" + field.schema().getValueType().getFullName();
60+
if (!extractSchema(field.schema().getValueType(), builder, depth)) {
61+
return false;
62+
};
63+
}
64+
description = "Map type with " + keys + " keys and " + values + " values";
5865
break;
5966
case STRING:
6067
type = "string";

dd-java-agent/instrumentation/avro/src/test/groovy/AvroDatumReaderTest.groovy

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class AvroDatumReaderTest extends AgentTestRunner {
2323

2424
return true
2525
}
26-
String schemaID = "1235632270399345373"
27-
String openApiSchemaDef = "{\"components\":{\"schemas\":{\"TestRecord\":{\"properties\":{\"stringField\":{\"type\":\"string\"},\"intField\":{\"format\":\"int32\",\"type\":\"integer\"},\"longField\":{\"format\":\"int64\",\"type\":\"integer\"},\"floatField\":{\"format\":\"float\",\"type\":\"number\"},\"doubleField\":{\"format\":\"double\",\"type\":\"number\"},\"booleanField\":{\"type\":\"boolean\"},\"bytesField\":{\"format\":\"byte\",\"type\":\"string\"},\"nullField\":{\"type\":\"null\"},\"enumField\":{\"enum\":[\"A\",\"B\",\"C\"],\"type\":\"string\"},\"fixedField\":{\"type\":\"string\"},\"recordField\":{\"type\":\"#/components/schemas/NestedRecord\"},\"arrayField\":{\"items\":{\"type\":\"integer\"},\"type\":\"array\"},\"mapField\":{\"description\":\"Map type\",\"type\":\"object\"},\"arrayNestedField\":{\"items\":{\"type\":\"#/components/schemas/OtherNestedRecord\"},\"type\":\"array\"}},\"type\":\"object\"},\"NestedRecord\":{\"properties\":{\"nestedString\":{\"type\":\"string\"}},\"type\":\"object\"},\"OtherNestedRecord\":{\"properties\":{\"nestedString\":{\"type\":\"string\"}},\"type\":\"object\"}}},\"openapi\":\"3.0.0\"}"
26+
String schemaID = "8924443781494069161"
27+
String openApiSchemaDef = "{\"components\":{\"schemas\":{\"TestRecord\":{\"properties\":{\"stringField\":{\"type\":\"string\"},\"intField\":{\"format\":\"int32\",\"type\":\"integer\"},\"longField\":{\"format\":\"int64\",\"type\":\"integer\"},\"floatField\":{\"format\":\"float\",\"type\":\"number\"},\"doubleField\":{\"format\":\"double\",\"type\":\"number\"},\"booleanField\":{\"type\":\"boolean\"},\"bytesField\":{\"format\":\"byte\",\"type\":\"string\"},\"nullField\":{\"type\":\"null\"},\"enumField\":{\"enum\":[\"A\",\"B\",\"C\"],\"type\":\"string\"},\"fixedField\":{\"type\":\"string\"},\"recordField\":{\"type\":\"#/components/schemas/NestedRecord\"},\"arrayField\":{\"items\":{\"type\":\"integer\"},\"type\":\"array\"},\"mapField\":{\"description\":\"Map type with string keys and string values\",\"type\":\"object\"},\"arrayNestedField\":{\"items\":{\"type\":\"#/components/schemas/OtherNestedRecord\"},\"type\":\"array\"},\"mapNestedField\":{\"description\":\"Map type with string keys and #/components/schemas/ThirdTypeOfNestedRecord values\",\"type\":\"object\"}},\"type\":\"object\"},\"NestedRecord\":{\"properties\":{\"nestedString\":{\"type\":\"string\"}},\"type\":\"object\"},\"OtherNestedRecord\":{\"properties\":{\"nestedString\":{\"type\":\"string\"}},\"type\":\"object\"},\"ThirdTypeOfNestedRecord\":{\"properties\":{\"nestedString\":{\"type\":\"string\"}},\"type\":\"object\"}}},\"openapi\":\"3.0.0\"}"
2828
String schemaStr = '''
2929
{
3030
"type": "record",
@@ -43,22 +43,12 @@ class AvroDatumReaderTest extends AgentTestRunner {
4343
{"name": "recordField", "type": {"type": "record", "name": "NestedRecord", "fields": [{"name": "nestedString", "type": "string"}]}},
4444
{"name": "arrayField", "type": {"type": "array", "items": "int"}},
4545
{"name": "mapField", "type": {"type": "map", "values": "string"}},
46-
{"name": "arrayNestedField", "type": { "type": "array", "items": {"type": "record", "name": "OtherNestedRecord", "fields": [{"name": "nestedString", "type": "string"}]}}}
46+
{"name": "arrayNestedField", "type": { "type": "array", "items": {"type": "record", "name": "OtherNestedRecord", "fields": [{"name": "nestedString", "type": "string"}]}}},
47+
{"name": "mapNestedField", "type": {"type": "map", "values": {"type": "record", "name": "ThirdTypeOfNestedRecord", "fields": [{"name": "nestedString", "type": "string"}]}}}
4748
]
4849
}
4950
'''
5051
Schema schemaDef = new Schema.Parser().parse(schemaStr)
51-
// here for convience but must be kept in sync with the array nested field
52-
String nestedSchemaStr = '''
53-
{
54-
"type": "record",
55-
"name": "OtherNestedRecord",
56-
"fields": [
57-
{"name": "nestedString", "type": "string"}
58-
]
59-
}
60-
'''
61-
Schema nestedSchemaDef = new Schema.Parser().parse(nestedSchemaStr)
6252

6353
void 'test extract avro schema on deserialize'() {
6454

@@ -91,12 +81,19 @@ class AvroDatumReaderTest extends AgentTestRunner {
9181
datum.put("mapField", map)
9282

9383
// array of nested fields
94-
GenericRecord nestedRecordA = new GenericData.Record(nestedSchemaDef)
84+
GenericRecord nestedRecordA = new GenericData.Record(schemaDef.getField("arrayNestedField").schema().getElementType())
9585
nestedRecordA.put("nestedString", "a")
96-
GenericRecord nestedRecordB = new GenericData.Record(nestedSchemaDef)
86+
GenericRecord nestedRecordB = new GenericData.Record(schemaDef.getField("arrayNestedField").schema().getElementType())
9787
nestedRecordB.put("nestedString", "b")
9888
datum.put("arrayNestedField", Arrays.asList(nestedRecordA, nestedRecordB))
9989

90+
// map of nested fields
91+
Map<String, GenericRecord> nestedMap = new HashMap<>()
92+
GenericRecord nestedRecordC = new GenericData.Record(schemaDef.getField("mapNestedField").schema().getValueType())
93+
nestedRecordC.put("nestedString", "a")
94+
nestedMap.put("key1", nestedRecordC)
95+
datum.put("mapNestedField", nestedMap)
96+
10097
when:
10198
def bytes
10299
ByteArrayOutputStream out = new ByteArrayOutputStream()

0 commit comments

Comments
 (0)