diff --git a/custom/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java b/custom/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java index 515d7e705..527892087 100644 --- a/custom/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java +++ b/custom/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java @@ -20,18 +20,9 @@ import static io.opentelemetry.opamp.client.internal.request.service.HttpRequestService.DEFAULT_DELAY_BETWEEN_RETRIES; import static io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil.getConfig; import static io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil.getResource; -import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_INSTANCE_ID; -import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; -import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAMESPACE; -import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_VERSION; -import static io.opentelemetry.semconv.incubating.DeploymentIncubatingAttributes.DEPLOYMENT_ENVIRONMENT_NAME; -import static io.opentelemetry.semconv.incubating.OsIncubatingAttributes.OS_NAME; -import static io.opentelemetry.semconv.incubating.OsIncubatingAttributes.OS_TYPE; -import static io.opentelemetry.semconv.incubating.OsIncubatingAttributes.OS_VERSION; import static java.util.logging.Level.WARNING; import com.google.auto.service.AutoService; -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.OpampClientBuilder; @@ -43,6 +34,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.resources.Resource; import java.time.Duration; +import java.util.List; import java.util.logging.Logger; import opamp.proto.ServerErrorResponse; import org.jetbrains.annotations.Nullable; @@ -109,32 +101,69 @@ static OpampClient startOpampClient( HttpRequestService.create(okhttp, pollingDelay, DEFAULT_DELAY_BETWEEN_RETRIES); builder.setRequestService(httpSender); } - addIdentifying(builder, resource, DEPLOYMENT_ENVIRONMENT_NAME); - addIdentifying(builder, resource, SERVICE_NAME); - addIdentifying(builder, resource, SERVICE_VERSION); - addIdentifying(builder, resource, SERVICE_NAMESPACE); - addIdentifying(builder, resource, SERVICE_INSTANCE_ID); - - addNonIdentifying(builder, resource, OS_NAME); - addNonIdentifying(builder, resource, OS_TYPE); - addNonIdentifying(builder, resource, OS_VERSION); + addIdentifyingAttributes(builder, resource); return builder.build(callbacks); } - static void addIdentifying( - OpampClientBuilder builder, Resource res, AttributeKey resourceAttr) { - String attr = res.getAttribute(resourceAttr); - if (attr != null) { - builder.putIdentifyingAttribute(resourceAttr.getKey(), attr); - } - } - - static void addNonIdentifying( - OpampClientBuilder builder, Resource res, AttributeKey resourceAttr) { - String attr = res.getAttribute(resourceAttr); - if (attr != null) { - builder.putNonIdentifyingAttribute(resourceAttr.getKey(), attr); - } + static void addIdentifyingAttributes(OpampClientBuilder builder, Resource res) { + res.getAttributes() + .forEach( + (key, value) -> { + switch (key.getType()) { + case STRING: + builder.putIdentifyingAttribute(key.getKey(), (String) value); + break; + case LONG: + builder.putIdentifyingAttribute(key.getKey(), (long) value); + break; + case DOUBLE: + builder.putIdentifyingAttribute(key.getKey(), (double) value); + break; + case BOOLEAN: + builder.putIdentifyingAttribute(key.getKey(), (boolean) value); + break; + case VALUE: + builder.putIdentifyingAttribute(key.getKey(), value.toString()); + break; + case STRING_ARRAY: + { + List typedValueList = (List) value; + String[] array = typedValueList.toArray(new String[] {}); + builder.putIdentifyingAttribute(key.getKey(), array); + break; + } + case LONG_ARRAY: + { + List typedValueList = (List) value; + long[] primitiveArray = new long[typedValueList.size()]; + for (int i = 0; i < typedValueList.size(); i++) { + primitiveArray[i] = typedValueList.get(i); + } + builder.putIdentifyingAttribute(key.getKey(), primitiveArray); + break; + } + case DOUBLE_ARRAY: + { + List typedValueList = (List) value; + double[] primitiveArray = new double[typedValueList.size()]; + for (int i = 0; i < typedValueList.size(); i++) { + primitiveArray[i] = typedValueList.get(i); + } + builder.putIdentifyingAttribute(key.getKey(), primitiveArray); + break; + } + case BOOLEAN_ARRAY: + { + List typedValueList = (List) value; + boolean[] primitiveArray = new boolean[typedValueList.size()]; + for (int i = 0; i < typedValueList.size(); i++) { + primitiveArray[i] = typedValueList.get(i); + } + builder.putIdentifyingAttribute(key.getKey(), primitiveArray); + break; + } + } + }); } } diff --git a/custom/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java b/custom/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java index 40340eee0..503dae573 100644 --- a/custom/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java +++ b/custom/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java @@ -16,6 +16,10 @@ package com.splunk.opentelemetry.opamp; +import static io.opentelemetry.api.common.AttributeKey.booleanKey; +import static io.opentelemetry.api.common.AttributeKey.doubleKey; +import static io.opentelemetry.api.common.AttributeKey.longKey; +import static io.opentelemetry.api.common.AttributeKey.valueKey; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAMESPACE; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_VERSION; @@ -27,6 +31,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.Value; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.response.MessageData; @@ -36,16 +41,20 @@ import io.opentelemetry.testing.internal.armeria.common.MediaType; import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension; import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.RecordedRequest; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import okio.ByteString; import opamp.proto.AgentConfigFile; import opamp.proto.AgentConfigMap; import opamp.proto.AgentRemoteConfig; import opamp.proto.AgentToServer; import opamp.proto.AnyValue; +import opamp.proto.ArrayValue; import opamp.proto.KeyValue; import opamp.proto.ServerErrorResponse; import opamp.proto.ServerToAgent; @@ -93,6 +102,18 @@ void testOpamp() throws Exception { .put(OS_NAME, "test-os-name") .put(OS_TYPE, "test-os-type") .put(OS_VERSION, "test-os-ver") + .put(longKey("long"), 12L) + .put(doubleKey("double"), 99.0) + .put(booleanKey("bool"), true) + .put(valueKey("val"), Value.of("vvv")) + .put("longarr", new long[] {2L, 3L, 5L}) + .put(AttributeKey.longArrayKey("longobjarr"), Arrays.asList(2L, 3L, 5L)) + .put("doublearr", new double[] {2.0, 3.0}) + .put(AttributeKey.doubleArrayKey("doubleobjarr"), Arrays.asList(5.0, 6.0)) + .put("stringarr", new String[] {"foo", "flimflam"}) + .put(AttributeKey.stringArrayKey("stringobjarr"), Arrays.asList("flim", "jibberjo")) + .put("boolarr", new boolean[] {true, false}) + .put(AttributeKey.booleanArrayKey("boolobjarr"), Arrays.asList(true, true, false, true)) .build(); Resource resource = Resource.create(attributes); Map configMap = @@ -148,26 +169,86 @@ public void onMessage(OpampClient opampClient, MessageData messageData) { RecordedRequest recordedRequest = server.takeRequest(); byte[] body = recordedRequest.request().content().array(); AgentToServer agentToServer = AgentToServer.ADAPTER.decode(body); - assertIdentifying(agentToServer, DEPLOYMENT_ENVIRONMENT_NAME, "test-deployment-env"); - assertIdentifying(agentToServer, SERVICE_NAME, "test-service"); - assertIdentifying(agentToServer, SERVICE_VERSION, "test-ver"); - assertIdentifying(agentToServer, SERVICE_NAMESPACE, "test-ns"); - assertNonIdentifying(agentToServer, OS_NAME, "test-os-name"); - assertNonIdentifying(agentToServer, OS_TYPE, "test-os-type"); - assertNonIdentifying(agentToServer, OS_VERSION, "test-os-ver"); + + assertIdentifyingString(agentToServer, DEPLOYMENT_ENVIRONMENT_NAME, "test-deployment-env"); + assertIdentifyingString(agentToServer, SERVICE_NAME, "test-service"); + assertIdentifyingString(agentToServer, SERVICE_VERSION, "test-ver"); + assertIdentifyingString(agentToServer, SERVICE_NAMESPACE, "test-ns"); + + List identifyingAttributes = agentToServer.agent_description.identifying_attributes; + assertThat(identifyingAttributes) + .anyMatch(kv -> kv.key.equals("long") && kv.value.int_value.equals(12L)); + assertThat(identifyingAttributes) + .anyMatch(kv -> kv.key.equals("double") && kv.value.double_value.equals(99.0)); + assertThat(identifyingAttributes) + .anyMatch(kv -> kv.key.equals("bool") && kv.value.bool_value.equals(true)); + assertThat(identifyingAttributes) + .anyMatch(kv -> kv.key.equals("val") && kv.value.string_value.equals("vvv")); + AnyValue longsArray = + createArrayAttribute( + new AnyValue.Builder().int_value(2L).build(), + new AnyValue.Builder().int_value(3L).build(), + new AnyValue.Builder().int_value(5L).build()); + assertThat(identifyingAttributes) + .anyMatch(kv -> kv.key.equals("longarr") && kv.value.equals(longsArray)); + assertThat(identifyingAttributes) + .anyMatch(kv -> kv.key.equals("longobjarr") && kv.value.equals(longsArray)); + assertThat(identifyingAttributes) + .anyMatch( + matching( + "doublearr", + new AnyValue.Builder().double_value(2.0).build(), + new AnyValue.Builder().double_value(3.0).build())); + assertThat(identifyingAttributes) + .anyMatch( + matching( + "doubleobjarr", + new AnyValue.Builder().double_value(5.0).build(), + new AnyValue.Builder().double_value(6.0).build())); + + assertThat(identifyingAttributes) + .anyMatch( + matching( + "stringarr", + new AnyValue.Builder().string_value("foo").build(), + new AnyValue.Builder().string_value("flimflam").build())); + assertThat(identifyingAttributes) + .anyMatch( + matching( + "stringobjarr", + new AnyValue.Builder().string_value("flim").build(), + new AnyValue.Builder().string_value("jibberjo").build())); + assertThat(identifyingAttributes) + .anyMatch( + matching( + "boolarr", + new AnyValue.Builder().bool_value(true).build(), + new AnyValue.Builder().bool_value(false).build())); + assertThat(identifyingAttributes) + .anyMatch( + matching( + "boolobjarr", + new AnyValue.Builder().bool_value(true).build(), + new AnyValue.Builder().bool_value(true).build(), + new AnyValue.Builder().bool_value(false).build(), + new AnyValue.Builder().bool_value(true).build())); + + assertThat(agentToServer.agent_description.non_identifying_attributes).isEmpty(); } - private void assertIdentifying( - AgentToServer agentToServer, AttributeKey attr, String expected) { - KeyValue kv = - new KeyValue(attr.getKey(), new AnyValue.Builder().string_value(expected).build()); - assertThat(agentToServer.agent_description.identifying_attributes).contains(kv); + private static Predicate matching(String key, AnyValue... values) { + return kv -> kv.key.equals(key) && kv.value.equals(createArrayAttribute(values)); + } + + private static AnyValue createArrayAttribute(AnyValue... values) { + return new AnyValue.Builder() + .array_value(new ArrayValue.Builder().values(Arrays.asList(values)).build()) + .build(); } - private void assertNonIdentifying( + private void assertIdentifyingString( AgentToServer agentToServer, AttributeKey attr, String expected) { - KeyValue kv = - new KeyValue(attr.getKey(), new AnyValue.Builder().string_value(expected).build()); - assertThat(agentToServer.agent_description.non_identifying_attributes).contains(kv); + assertThat(agentToServer.agent_description.identifying_attributes) + .anyMatch(kv -> kv.key.equals(attr.getKey()) && kv.value.string_value.equals(expected)); } }