diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/build.gradle.kts b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/build.gradle.kts index 23b06a7bf2..7988d58908 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/build.gradle.kts +++ b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { testImplementation("org.apache.logging.log4j:log4j-core:2.11.0") testImplementation("org.apache.logging.log4j:log4j-api:2.11.0") + testImplementation("com.fasterxml.jackson.core:jackson-databind") testImplementation("org.testcontainers:elasticsearch") testLibrary("org.elasticsearch.client:rest:5.0.0") diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/ElasticsearchRest5Test.groovy b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/ElasticsearchRest5Test.groovy deleted file mode 100644 index a8c76d3f3e..0000000000 --- a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/groovy/ElasticsearchRest5Test.groovy +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import groovy.json.JsonSlurper -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes -import org.apache.http.HttpHost -import org.apache.http.client.config.RequestConfig -import org.apache.http.util.EntityUtils -import org.elasticsearch.client.Response -import org.elasticsearch.client.ResponseListener -import org.elasticsearch.client.RestClient -import org.elasticsearch.client.RestClientBuilder -import org.testcontainers.elasticsearch.ElasticsearchContainer -import spock.lang.Shared - -import java.util.concurrent.CountDownLatch - -import static io.opentelemetry.api.trace.SpanKind.CLIENT -import static io.opentelemetry.api.trace.SpanKind.INTERNAL - -class ElasticsearchRest5Test extends AgentInstrumentationSpecification { - @Shared - ElasticsearchContainer elasticsearch - - @Shared - HttpHost httpHost - - @Shared - static RestClient client - - def setupSpec() { - if (!Boolean.getBoolean("testLatestDeps")) { - elasticsearch = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:5.6.16") - .withEnv("xpack.ml.enabled", "false") - .withEnv("xpack.security.enabled", "false") - } else { - elasticsearch = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.16") - } - // limit memory usage - elasticsearch.withEnv("ES_JAVA_OPTS", "-Xmx256m -Xms256m") - elasticsearch.start() - - httpHost = HttpHost.create(elasticsearch.getHttpHostAddress()) - client = RestClient.builder(httpHost) - .setMaxRetryTimeoutMillis(Integer.MAX_VALUE) - .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { - @Override - RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) { - return builder.setConnectTimeout(Integer.MAX_VALUE).setSocketTimeout(Integer.MAX_VALUE) - } - }) - .build() - } - - def cleanupSpec() { - elasticsearch.stop() - } - - def "test elasticsearch status"() { - setup: - Response response = client.performRequest("GET", "_cluster/health") - - Map result = new JsonSlurper().parseText(EntityUtils.toString(response.entity)) - - expect: - // usually this test reports green status, but sometimes it is yellow - result.status == "green" || result.status == "yellow" - - assertTraces(1) { - trace(0, 2) { - span(0) { - name "GET" - kind CLIENT - hasNoParent() - attributes { - "$SemanticAttributes.DB_SYSTEM" "elasticsearch" - "$SemanticAttributes.DB_OPERATION" "GET" - "$SemanticAttributes.DB_STATEMENT" "GET _cluster/health" - } - } - span(1) { - name "GET" - kind CLIENT - childOf span(0) - attributes { - "$SemanticAttributes.NET_PEER_NAME" httpHost.hostName - "$SemanticAttributes.NET_PEER_PORT" httpHost.port - "$SemanticAttributes.HTTP_METHOD" "GET" - "net.protocol.name" "http" - "net.protocol.version" "1.1" - "$SemanticAttributes.HTTP_URL" "${httpHost.toURI()}/_cluster/health" - "$SemanticAttributes.HTTP_STATUS_CODE" 200 - "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long - } - } - } - } - } - - def "test elasticsearch status async"() { - setup: - Response requestResponse = null - Exception exception = null - CountDownLatch countDownLatch = new CountDownLatch(1) - ResponseListener responseListener = new ResponseListener() { - @Override - void onSuccess(Response response) { - runWithSpan("callback") { - requestResponse = response - countDownLatch.countDown() - } - } - - @Override - void onFailure(Exception e) { - runWithSpan("callback") { - exception = e - countDownLatch.countDown() - } - } - } - runWithSpan("parent") { - client.performRequestAsync("GET", "_cluster/health", responseListener) - } - countDownLatch.await() - - if (exception != null) { - throw exception - } - Map result = new JsonSlurper().parseText(EntityUtils.toString(requestResponse.entity)) - - expect: - // usually this test reports green status, but sometimes it is yellow - result.status == "green" || result.status == "yellow" - - assertTraces(1) { - trace(0, 4) { - span(0) { - name "parent" - kind INTERNAL - hasNoParent() - } - span(1) { - name "GET" - kind CLIENT - childOf(span(0)) - attributes { - "$SemanticAttributes.DB_SYSTEM" "elasticsearch" - "$SemanticAttributes.DB_OPERATION" "GET" - "$SemanticAttributes.DB_STATEMENT" "GET _cluster/health" - } - } - span(2) { - name "GET" - kind CLIENT - childOf span(1) - attributes { - "$SemanticAttributes.NET_PEER_NAME" httpHost.hostName - "$SemanticAttributes.NET_PEER_PORT" httpHost.port - "$SemanticAttributes.HTTP_METHOD" "GET" - "net.protocol.name" "http" - "net.protocol.version" "1.1" - "$SemanticAttributes.HTTP_URL" "${httpHost.toURI()}/_cluster/health" - "$SemanticAttributes.HTTP_STATUS_CODE" 200 - "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long - } - } - span(3) { - name "callback" - kind INTERNAL - childOf(span(0)) - } - } - } - } -} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/java/ElasticsearchRest5Test.java b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/java/ElasticsearchRest5Test.java new file mode 100644 index 0000000000..138ed7260b --- /dev/null +++ b/instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/test/java/ElasticsearchRest5Test.java @@ -0,0 +1,197 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import org.apache.http.HttpHost; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseListener; +import org.elasticsearch.client.RestClient; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.testcontainers.elasticsearch.ElasticsearchContainer; + +public class ElasticsearchRest5Test { + + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + static ElasticsearchContainer elasticsearch; + + static HttpHost httpHost; + + static RestClient client; + + static ObjectMapper objectMapper; + + @BeforeAll + static void setup() { + if (!Boolean.getBoolean("testLatestDeps")) { + elasticsearch = + new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:5.6.16") + .withEnv("xpack.ml.enabled", "false") + .withEnv("xpack.security.enabled", "false"); + } else { + elasticsearch = + new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.16"); + } + // limit memory usage + elasticsearch.withEnv("ES_JAVA_OPTS", "-Xmx256m -Xms256m"); + elasticsearch.start(); + + httpHost = HttpHost.create(elasticsearch.getHttpHostAddress()); + client = + RestClient.builder(httpHost) + .setMaxRetryTimeoutMillis(Integer.MAX_VALUE) + .setRequestConfigCallback( + builder -> + builder + .setConnectTimeout(Integer.MAX_VALUE) + .setSocketTimeout(Integer.MAX_VALUE)) + .build(); + + objectMapper = new ObjectMapper(); + } + + @AfterAll + static void cleanUp() { + elasticsearch.stop(); + } + + @Test + @SuppressWarnings("rawtypes") + void elasticsearchStatus() throws IOException { + Response response = client.performRequest("GET", "_cluster/health"); + + Map result = objectMapper.readValue(response.getEntity().getContent(), Map.class); + + // usually this test reports green status, but sometimes it is yellow + Assertions.assertTrue( + "green".equals(result.get("status")) || "yellow".equals(result.get("status"))); + + testing.waitAndAssertTraces( + trace -> { + trace.hasSpansSatisfyingExactly( + span -> { + span.hasName("GET") + .hasKind(SpanKind.CLIENT) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(SemanticAttributes.DB_SYSTEM, "elasticsearch"), + equalTo(SemanticAttributes.DB_OPERATION, "GET"), + equalTo(SemanticAttributes.DB_STATEMENT, "GET _cluster/health")); + }, + span -> { + span.hasName("GET") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(SemanticAttributes.NET_PEER_NAME, httpHost.getHostName()), + equalTo(SemanticAttributes.NET_PEER_PORT, httpHost.getPort()), + equalTo(SemanticAttributes.HTTP_METHOD, "GET"), + equalTo(AttributeKey.stringKey("net.protocol.name"), "http"), + equalTo(AttributeKey.stringKey("net.protocol.version"), "1.1"), + equalTo(SemanticAttributes.HTTP_URL, httpHost.toURI() + "/_cluster/health"), + equalTo(SemanticAttributes.HTTP_STATUS_CODE, 200), + equalTo( + SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, + response.getEntity().getContentLength())); + }); + }); + } + + @Test + @SuppressWarnings("rawtypes") + void elasticsearchStatusAsync() throws Exception { + Response[] requestResponse = {null}; + Exception[] exception = {null}; + CountDownLatch countDownLatch = new CountDownLatch(1); + ResponseListener responseListener = + new ResponseListener() { + @Override + public void onSuccess(Response response) { + testing.runWithSpan( + "callback", + () -> { + requestResponse[0] = response; + countDownLatch.countDown(); + }); + } + + @Override + public void onFailure(Exception e) { + testing.runWithSpan( + "callback", + () -> { + exception[0] = e; + countDownLatch.countDown(); + }); + } + }; + + testing.runWithSpan( + "parent", + () -> { + client.performRequestAsync("GET", "_cluster/health", responseListener); + }); + countDownLatch.await(); + if (exception[0] != null) { + throw exception[0]; + } + Map result = objectMapper.readValue(requestResponse[0].getEntity().getContent(), Map.class); + + // usually this test reports green status, but sometimes it is yellow + Assertions.assertTrue( + "green".equals(result.get("status")) || "yellow".equals(result.get("status"))); + + testing.waitAndAssertTraces( + trace -> { + trace.hasSpansSatisfyingExactly( + span -> { + span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(); + }, + span -> { + span.hasName("GET") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(SemanticAttributes.DB_SYSTEM, "elasticsearch"), + equalTo(SemanticAttributes.DB_OPERATION, "GET"), + equalTo(SemanticAttributes.DB_STATEMENT, "GET _cluster/health")); + }, + span -> { + span.hasName("GET") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(1)) + .hasAttributesSatisfyingExactly( + equalTo(SemanticAttributes.NET_PEER_NAME, httpHost.getHostName()), + equalTo(SemanticAttributes.NET_PEER_PORT, httpHost.getPort()), + equalTo(SemanticAttributes.HTTP_METHOD, "GET"), + equalTo(AttributeKey.stringKey("net.protocol.name"), "http"), + equalTo(AttributeKey.stringKey("net.protocol.version"), "1.1"), + equalTo(SemanticAttributes.HTTP_URL, httpHost.toURI() + "/_cluster/health"), + equalTo(SemanticAttributes.HTTP_STATUS_CODE, 200), + equalTo( + SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, + requestResponse[0].getEntity().getContentLength())); + }, + span -> { + span.hasName("callback").hasKind(SpanKind.INTERNAL).hasParent(trace.getSpan(0)); + }); + }); + } +} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/build.gradle.kts b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/build.gradle.kts index 8b589b1df3..79e573af55 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/build.gradle.kts +++ b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { testImplementation("org.apache.logging.log4j:log4j-core:2.11.0") testImplementation("org.apache.logging.log4j:log4j-api:2.11.0") + testImplementation("com.fasterxml.jackson.core:jackson-databind") testImplementation("org.testcontainers:elasticsearch") testLibrary("org.elasticsearch.client:elasticsearch-rest-client:6.4.0") diff --git a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/java/ElasticsearchRest6Test.java b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/java/ElasticsearchRest6Test.java index 435c19b54f..178a235123 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/java/ElasticsearchRest6Test.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/test/java/ElasticsearchRest6Test.java @@ -5,6 +5,7 @@ import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import com.fasterxml.jackson.databind.ObjectMapper; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; @@ -23,7 +24,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.testcontainers.elasticsearch.ElasticsearchContainer; -import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; public class ElasticsearchRest6Test { @RegisterExtension