From 318d9b9ef82bea4f7b6aae5842d700b6dda5e378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vandon?= Date: Mon, 17 Feb 2025 15:26:52 +0100 Subject: [PATCH 1/4] fix bug on proto schema extraction --- .../protobuf_java/SchemaExtractor.java | 29 ++-- .../AbstractMessageInstrumentationTest.groovy | 152 +++++++++++++++++- .../protobuf/src/test/proto/message.proto | 7 + .../DefaultDataStreamsMonitoring.java | 1 + 4 files changed, 171 insertions(+), 18 deletions(-) diff --git a/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java b/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java index 03593389199..9e0d47ae596 100644 --- a/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java +++ b/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java @@ -44,6 +44,9 @@ public SchemaExtractor(Descriptor descriptor) { this.descriptor = descriptor; } + /** + * @return false if no more properties should be extracted + */ public static boolean extractProperty( FieldDescriptor field, String schemaName, @@ -107,9 +110,7 @@ public static boolean extractProperty( case TYPE_MESSAGE: ref = "#/components/schemas/" + field.getMessageType().getFullName(); // Recursively add nested message schemas - if (!extractSchema(field.getMessageType(), builder, depth)) { - return false; - } + extractSchema(field.getMessageType(), builder, depth); builder.addToHash(field.getMessageType().getFullName()); break; case TYPE_BYTES: @@ -154,22 +155,20 @@ public static boolean extractProperty( schemaName, fieldName, array, type, description, ref, format, enumValues, extensions); } - public static boolean extractSchema(Descriptor descriptor, SchemaBuilder builder, int depth) { + public static void extractSchema(Descriptor descriptor, SchemaBuilder builder, int depth) { depth++; String schemaName = descriptor.getFullName(); - if (!builder.shouldExtractSchema(schemaName, depth)) { - return false; - } - // iterate fields in number order to ensure hash stability - for (FieldDescriptor field : - descriptor.getFields().stream() - .sorted(Comparator.comparingInt(FieldDescriptor::getNumber)) - .collect(Collectors.toList())) { - if (!extractProperty(field, schemaName, field.getName(), builder, depth)) { - return false; + if (builder.shouldExtractSchema(schemaName, depth)) { + for (FieldDescriptor field : + descriptor.getFields().stream() + // iterate fields in number order to ensure hash stability + .sorted(Comparator.comparingInt(FieldDescriptor::getNumber)) + .collect(Collectors.toList())) { + if (!extractProperty(field, schemaName, field.getName(), builder, depth)) { + break; // we have reached the max nb of properties to extract + } } } - return true; } public static Schema extractSchemas(Descriptor descriptor) { diff --git a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy index 381c24ff3d4..c4e50d8184e 100644 --- a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy @@ -2,6 +2,7 @@ package com.datadog.instrumentation.protobuf import com.datadog.instrumentation.protobuf.generated.Message.MyMessage import com.datadog.instrumentation.protobuf.generated.Message.OtherMessage +import com.datadog.instrumentation.protobuf.generated.Message.RecursiveMessage import com.google.protobuf.InvalidProtocolBufferException import datadog.trace.agent.test.AgentTestRunner import datadog.trace.api.DDTags @@ -16,11 +17,68 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { return true } - String expectedSchema = "{\"components\":{\"schemas\":{\"com.datadog.instrumentation.protobuf.generated.MyMessage\":{\"properties\":{\"id\":{\"extensions\":{\"x-protobuf-number\":\"1\"},\"type\":\"string\"},\"value\":{\"extensions\":{\"x-protobuf-number\":\"2\"},\"type\":\"string\"},\"other_message\":{\"extensions\":{\"x-protobuf-number\":\"3\"},\"items\":{\"\$ref\":\"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage\"},\"type\":\"array\"}},\"type\":\"object\"},\"com.datadog.instrumentation.protobuf.generated.OtherMessage\":{\"properties\":{\"name\":{\"extensions\":{\"x-protobuf-number\":\"1\"},\"type\":\"string\"},\"age\":{\"extensions\":{\"x-protobuf-number\":\"2\"},\"format\":\"int32\",\"type\":\"integer\"}},\"type\":\"object\"}}},\"openapi\":\"3.0.0\"}" - String expectedSchemaID = "4690647329509494987" + void 'test extract protobuf schema on serialize & deserialize'() { + String expectedSchema = "{" + + ' "components":{' + + ' "schemas":{' + + ' "com.datadog.instrumentation.protobuf.generated.MyMessage":{' + + ' "properties":{' + + ' "id":{' + + ' "extensions":{' + + ' "x-protobuf-number":"1"' + + ' },' + + ' "type":"string"' + + ' },' + + ' "value":{' + + ' "extensions":{' + + ' "x-protobuf-number":"2"' + + ' },' + + ' "type":"string"' + + ' },' + + ' "other_message":{' + + ' "extensions":{' + + ' "x-protobuf-number":"3"' + + ' },' + + ' "items":{' + + ' "$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage"' + + ' },' + + ' "type":"array"' + + ' },' + + ' "nested":{' + + ' "$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage",' + + ' "extensions":{' + + ' "x-protobuf-number":"4"' + + ' }' + + ' }' + + ' },' + + ' "type":"object"' + + ' },' + + ' "com.datadog.instrumentation.protobuf.generated.OtherMessage":{' + + ' "properties":{' + + ' "name":{' + + ' "extensions":{' + + ' "x-protobuf-number":"1"' + + ' },' + + ' "type":"string"' + + ' },' + + ' "age":{' + + ' "extensions":{' + + ' "x-protobuf-number":"2"' + + ' },' + + ' "format":"int32",' + + ' "type":"integer"' + + ' }' + + ' },' + + ' "type":"object"' + + ' }' + + ' }' + + ' },' + + ' "openapi":"3.0.0"' + + '}' + expectedSchema = expectedSchema.replaceAll(" ", "") // the spaces are just here to make it readable + String expectedSchemaID = "2792908287829424040" - void 'test extract protobuf schema on serialize & deserialize'() { setup: MyMessage message = MyMessage.newBuilder() .setId("1") @@ -81,6 +139,94 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { } } + void 'test extract protobuf schema with recursive message'() { + String expectedSchema = '{' + + ' "components":{' + + ' "schemas":{' + + ' "com.datadog.instrumentation.protobuf.generated.RecursiveMessage":{' + + ' "properties":{' + + ' "value":{' + + ' "extensions":{' + + ' "x-protobuf-number":"1"' + + ' },' + + ' "format":"int32",' + + ' "type":"integer"' + + ' },' + + ' "next":{' + + ' "$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.RecursiveMessage",' + + ' "extensions":{' + + ' "x-protobuf-number":"2"' + + ' }' + + ' }' + + ' },' + + ' "type":"object"' + + ' }' + + ' }' + + ' },' + + ' "openapi":"3.0.0"' + + '}' + expectedSchema = expectedSchema.replaceAll(" ", "") // the spaces are just here to make it readable + String expectedSchemaID = "8377547842972884891" + + setup: + getTEST_DATA_STREAMS_MONITORING() + RecursiveMessage message = RecursiveMessage.newBuilder() + .setValue(12) + .build() + when: + byte[] bytes + runUnderTrace("parent_serialize") { + AgentSpan span = activeSpan() + span.setTag(DDTags.MANUAL_KEEP, true) + bytes = message.toByteArray() + } + runUnderTrace("parent_deserialize") { + AgentSpan span = activeSpan() + span.setTag(DDTags.MANUAL_KEEP, true) + MyMessage.parseFrom(bytes) + } + TEST_WRITER.waitForTraces(2) + then: + assertTraces(2, SORT_TRACES_BY_ID) { + trace(1) { + span { + hasServiceName() + operationName "parent_serialize" + resourceName "parent_serialize" + errored false + measured false + tags { + "$DDTags.SCHEMA_DEFINITION" expectedSchema + "$DDTags.SCHEMA_WEIGHT" 1 + "$DDTags.SCHEMA_TYPE" "protobuf" + "$DDTags.SCHEMA_NAME" "com.datadog.instrumentation.protobuf.generated.RecursiveMessage" + "$DDTags.SCHEMA_OPERATION" "serialization" + "$DDTags.SCHEMA_ID" expectedSchemaID + defaultTags(false) + } + } + } + trace(1) { + span { + hasServiceName() + operationName "parent_deserialize" + resourceName "parent_deserialize" + errored false + measured false + tags { + "$DDTags.SCHEMA_DEFINITION" expectedSchema + "$DDTags.SCHEMA_WEIGHT" 1 + "$DDTags.SCHEMA_TYPE" "protobuf" + "$DDTags.SCHEMA_NAME" "com.datadog.instrumentation.protobuf.generated.RecursiveMessage" + "$DDTags.SCHEMA_OPERATION" "deserialization" + "$DDTags.SCHEMA_ID" expectedSchemaID + defaultTags(false) + } + } + } + } + } + void 'test error when de-serializing'() { setup: MyMessage message = MyMessage.newBuilder() diff --git a/dd-java-agent/instrumentation/protobuf/src/test/proto/message.proto b/dd-java-agent/instrumentation/protobuf/src/test/proto/message.proto index d78165d2da7..4dc248a4332 100644 --- a/dd-java-agent/instrumentation/protobuf/src/test/proto/message.proto +++ b/dd-java-agent/instrumentation/protobuf/src/test/proto/message.proto @@ -1,3 +1,5 @@ +// run gradle target generateTestProto when you modify this + syntax = "proto3"; package com.datadog.instrumentation.protobuf.generated; @@ -13,3 +15,8 @@ message MyMessage { repeated OtherMessage other_message = 3; OtherMessage nested = 4; } + +message RecursiveMessage { + int32 value = 1; + RecursiveMessage next = 2; +} diff --git a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java index 2c8a897e762..f37d84695b6 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java @@ -432,6 +432,7 @@ private void flush(long timestampNanos) { @Override public void clear() { timeToBucket.clear(); + schemaSamplers.clear(); } void report() { From d5836c050758ae3020090c04bd272f25e124874e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vandon?= Date: Mon, 17 Feb 2025 17:22:06 +0100 Subject: [PATCH 2/4] formatting in test --- .../protobuf_java/SchemaExtractor.java | 4 +--- .../AbstractMessageInstrumentationTest.groovy | 14 +++++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java b/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java index 9e0d47ae596..a4f9d56c64d 100644 --- a/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java +++ b/dd-java-agent/instrumentation/protobuf/src/main/java/datadog/trace/instrumentation/protobuf_java/SchemaExtractor.java @@ -44,9 +44,7 @@ public SchemaExtractor(Descriptor descriptor) { this.descriptor = descriptor; } - /** - * @return false if no more properties should be extracted - */ + /** @return false if no more properties should be extracted */ public static boolean extractProperty( FieldDescriptor field, String schemaName, diff --git a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy index c4e50d8184e..9695fc5e8f6 100644 --- a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy @@ -81,10 +81,10 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { setup: MyMessage message = MyMessage.newBuilder() - .setId("1") - .setValue("Hello from Protobuf!") - .setNested(OtherMessage.newBuilder().setName("hello").setAge(10).build()) - .build() + .setId("1") + .setValue("Hello from Protobuf!") + .setNested(OtherMessage.newBuilder().setName("hello").setAge(10).build()) + .build() when: var bytes runUnderTrace("parent_serialize") { @@ -230,9 +230,9 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { void 'test error when de-serializing'() { setup: MyMessage message = MyMessage.newBuilder() - .setId("1") - .setValue("Hello from Protobuf!") - .build() + .setId("1") + .setValue("Hello from Protobuf!") + .build() when: runUnderTrace("parent_deserialize") { AgentSpan span = activeSpan() From 26ec5856dd102cc92f719868eae4f790c05d9124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vandon?= Date: Tue, 18 Feb 2025 10:47:16 +0100 Subject: [PATCH 3/4] use triple quoted strings --- .../AbstractMessageInstrumentationTest.groovy | 174 +++++++++--------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy index 9695fc5e8f6..b993f428e75 100644 --- a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy @@ -17,66 +17,66 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { return true } - void 'test extract protobuf schema on serialize & deserialize'() { + void "test extract protobuf schema on serialize & deserialize"() { - String expectedSchema = "{" + - ' "components":{' + - ' "schemas":{' + - ' "com.datadog.instrumentation.protobuf.generated.MyMessage":{' + - ' "properties":{' + - ' "id":{' + - ' "extensions":{' + - ' "x-protobuf-number":"1"' + - ' },' + - ' "type":"string"' + - ' },' + - ' "value":{' + - ' "extensions":{' + - ' "x-protobuf-number":"2"' + - ' },' + - ' "type":"string"' + - ' },' + - ' "other_message":{' + - ' "extensions":{' + - ' "x-protobuf-number":"3"' + - ' },' + - ' "items":{' + - ' "$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage"' + - ' },' + - ' "type":"array"' + - ' },' + - ' "nested":{' + - ' "$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage",' + - ' "extensions":{' + - ' "x-protobuf-number":"4"' + - ' }' + - ' }' + - ' },' + - ' "type":"object"' + - ' },' + - ' "com.datadog.instrumentation.protobuf.generated.OtherMessage":{' + - ' "properties":{' + - ' "name":{' + - ' "extensions":{' + - ' "x-protobuf-number":"1"' + - ' },' + - ' "type":"string"' + - ' },' + - ' "age":{' + - ' "extensions":{' + - ' "x-protobuf-number":"2"' + - ' },' + - ' "format":"int32",' + - ' "type":"integer"' + - ' }' + - ' },' + - ' "type":"object"' + - ' }' + - ' }' + - ' },' + - ' "openapi":"3.0.0"' + - '}' - expectedSchema = expectedSchema.replaceAll(" ", "") // the spaces are just here to make it readable + String expectedSchema = """{ + "components":{ + "schemas":{ + "com.datadog.instrumentation.protobuf.generated.MyMessage":{ + "properties":{ + "id":{ + "extensions":{ + "x-protobuf-number":"1" + }, + "type":"string" + }, + "value":{ + "extensions":{ + "x-protobuf-number":"2" + }, + "type":"string" + }, + "other_message":{ + "extensions":{ + "x-protobuf-number":"3" + }, + "items":{ + "\$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage" + }, + "type":"array" + }, + "nested":{ + "\$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage", + "extensions":{ + "x-protobuf-number":"4" + } + } + }, + "type":"object" + }, + "com.datadog.instrumentation.protobuf.generated.OtherMessage":{ + "properties":{ + "name":{ + "extensions":{ + "x-protobuf-number":"1" + }, + "type":"string" + }, + "age":{ + "extensions":{ + "x-protobuf-number":"2" + }, + "format":"int32", + "type":"integer" + } + }, + "type":"object" + } + } + }, + "openapi":"3.0.0" + }""" + expectedSchema = expectedSchema.replaceAll("[ \n]", "") // the spaces are just here to make it readable String expectedSchemaID = "2792908287829424040" setup: @@ -139,33 +139,33 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { } } - void 'test extract protobuf schema with recursive message'() { - String expectedSchema = '{' + - ' "components":{' + - ' "schemas":{' + - ' "com.datadog.instrumentation.protobuf.generated.RecursiveMessage":{' + - ' "properties":{' + - ' "value":{' + - ' "extensions":{' + - ' "x-protobuf-number":"1"' + - ' },' + - ' "format":"int32",' + - ' "type":"integer"' + - ' },' + - ' "next":{' + - ' "$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.RecursiveMessage",' + - ' "extensions":{' + - ' "x-protobuf-number":"2"' + - ' }' + - ' }' + - ' },' + - ' "type":"object"' + - ' }' + - ' }' + - ' },' + - ' "openapi":"3.0.0"' + - '}' - expectedSchema = expectedSchema.replaceAll(" ", "") // the spaces are just here to make it readable + void "test extract protobuf schema with recursive message"() { + String expectedSchema = """{ + "components":{ + "schemas":{ + "com.datadog.instrumentation.protobuf.generated.RecursiveMessage":{ + "properties":{ + "value":{ + "extensions":{ + "x-protobuf-number":"1" + }, + "format":"int32", + "type":"integer" + }, + "next":{ + "\$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.RecursiveMessage", + "extensions":{ + "x-protobuf-number":"2" + } + } + }, + "type":"object" + } + } + }, + "openapi":"3.0.0" + }""" + expectedSchema = expectedSchema.replaceAll("[ \n]", "") // the spaces are just here to make it readable String expectedSchemaID = "8377547842972884891" setup: @@ -227,7 +227,7 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { } } - void 'test error when de-serializing'() { + void "test error when de-serializing"() { setup: MyMessage message = MyMessage.newBuilder() .setId("1") From 0765d26d23a0c95aeaf58fafa869c306843d174a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vandon?= Date: Tue, 18 Feb 2025 18:31:48 +0100 Subject: [PATCH 4/4] fix tests --- .../AbstractMessageInstrumentationTest.groovy | 2 +- .../DynamicMessageInstrumentationTest.groovy | 62 ++++++++++++++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy index b993f428e75..551a0329ad1 100644 --- a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/AbstractMessageInstrumentationTest.groovy @@ -183,7 +183,7 @@ class AbstractMessageInstrumentationTest extends AgentTestRunner { runUnderTrace("parent_deserialize") { AgentSpan span = activeSpan() span.setTag(DDTags.MANUAL_KEEP, true) - MyMessage.parseFrom(bytes) + RecursiveMessage.parseFrom(bytes) } TEST_WRITER.waitForTraces(2) then: diff --git a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/DynamicMessageInstrumentationTest.groovy b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/DynamicMessageInstrumentationTest.groovy index 7393dc369ce..d4b26ec0c34 100644 --- a/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/DynamicMessageInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/protobuf/src/test/groovy/com/datadog/instrumentation/protobuf/DynamicMessageInstrumentationTest.groovy @@ -22,8 +22,66 @@ class DynamicMessageInstrumentationTest extends AgentTestRunner { .setValue("Hello from Protobuf!") .build() when: - String expectedSchema = "{\"components\":{\"schemas\":{\"com.datadog.instrumentation.protobuf.generated.MyMessage\":{\"properties\":{\"id\":{\"extensions\":{\"x-protobuf-number\":\"1\"},\"type\":\"string\"},\"value\":{\"extensions\":{\"x-protobuf-number\":\"2\"},\"type\":\"string\"},\"other_message\":{\"extensions\":{\"x-protobuf-number\":\"3\"},\"items\":{\"\$ref\":\"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage\"},\"type\":\"array\"}},\"type\":\"object\"},\"com.datadog.instrumentation.protobuf.generated.OtherMessage\":{\"properties\":{\"name\":{\"extensions\":{\"x-protobuf-number\":\"1\"},\"type\":\"string\"},\"age\":{\"extensions\":{\"x-protobuf-number\":\"2\"},\"format\":\"int32\",\"type\":\"integer\"}},\"type\":\"object\"}}},\"openapi\":\"3.0.0\"}" - String expectedSchemaID = "4690647329509494987" + String expectedSchema = """{ + "components":{ + "schemas":{ + "com.datadog.instrumentation.protobuf.generated.MyMessage":{ + "properties":{ + "id":{ + "extensions":{ + "x-protobuf-number":"1" + }, + "type":"string" + }, + "value":{ + "extensions":{ + "x-protobuf-number":"2" + }, + "type":"string" + }, + "other_message":{ + "extensions":{ + "x-protobuf-number":"3" + }, + "items":{ + "\$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage" + }, + "type":"array" + }, + "nested":{ + "\$ref":"#/components/schemas/com.datadog.instrumentation.protobuf.generated.OtherMessage", + "extensions":{ + "x-protobuf-number":"4" + } + } + }, + "type":"object" + }, + "com.datadog.instrumentation.protobuf.generated.OtherMessage":{ + "properties":{ + "name":{ + "extensions":{ + "x-protobuf-number":"1" + }, + "type":"string" + }, + "age":{ + "extensions":{ + "x-protobuf-number":"2" + }, + "format":"int32", + "type":"integer" + } + }, + "type":"object" + } + } + }, + "openapi":"3.0.0" + }""" + expectedSchema = expectedSchema.replaceAll("[ \n]", "") // the spaces are just here to make it readable + String expectedSchemaID = "2792908287829424040" + var bytes runUnderTrace("parent_serialize") { AgentSpan span = activeSpan()