diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcContractTestBase.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcContractTestBase.java index fe228894ca..2704dec3c9 100644 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcContractTestBase.java +++ b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcContractTestBase.java @@ -15,19 +15,26 @@ package software.amazon.opentelemetry.appsignals.test.jdbc; +import static io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_CLIENT; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.proto.common.v1.KeyValue; +import io.opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint; +import java.util.List; import java.util.Set; import software.amazon.opentelemetry.appsignals.test.base.ContractTestBase; -import software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.DBOperation; -import software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.JdbcOperationTester; -import software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.JdbcOperationTesterProvider; import software.amazon.opentelemetry.appsignals.test.utils.AppSignalsConstants; +import software.amazon.opentelemetry.appsignals.test.utils.ResourceScopeMetric; +import software.amazon.opentelemetry.appsignals.test.utils.ResourceScopeSpan; +import software.amazon.opentelemetry.appsignals.test.utils.SemanticConventionsConstants; -public abstract class JdbcContractTestBase extends ContractTestBase { +public class JdbcContractTestBase extends ContractTestBase { protected static final String DB_NAME = "testdb"; + protected static final String CREATE_DB_NAME = "testdb2"; protected static final String DB_USER = "root"; protected static final String DB_PASSWORD = "password"; + protected static final String DB_SELECT_OPERATION = "SELECT"; + protected static final String DB_CREATE_DATABASE_OPERATION = "CREATE DATABASE"; protected static final String DB_RESOURCE_TYPE = "DB::Connection"; @Override @@ -40,29 +47,289 @@ protected String getApplicationWaitPattern() { return ".*Application Ready.*"; } + protected void assertAwsSpanAttributes( + List resourceScopeSpans, + String method, + String path, + String dbSystem, + String dbOperation, + String type, + String identifier) { + assertThat(resourceScopeSpans) + .satisfiesOnlyOnce( + rss -> { + assertThat(rss.getSpan().getKind()).isEqualTo(SPAN_KIND_CLIENT); + var attributesList = rss.getSpan().getAttributesList(); + assertAwsAttributes( + attributesList, method, path, dbSystem, dbOperation, type, identifier); + }); + } + + protected void assertAwsAttributes( + List attributesList, + String method, + String endpoint, + String dbSystem, + String dbOperation, + String type, + String identifier) { + var assertions = + assertThat(attributesList) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_LOCAL_OPERATION); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(String.format("%s /%s", method, endpoint)); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_LOCAL_SERVICE); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(getApplicationOtelServiceName()); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_REMOTE_SERVICE); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbSystem); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_REMOTE_OPERATION); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbOperation); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_SPAN_KIND); + assertThat(attribute.getValue().getStringValue()).isEqualTo("CLIENT"); + }); + if (type != null && identifier != null) { + assertions.satisfiesOnlyOnce( + (attribute) -> { + assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_TYPE); + assertThat(attribute.getValue().getStringValue()).isEqualTo(type); + }); + assertions.satisfiesOnlyOnce( + (attribute) -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_IDENTIFIER); + assertThat(attribute.getValue().getStringValue()).isEqualTo(identifier); + }); + } + } + + protected void assertSemanticConventionsSpanAttributes( + List resourceScopeSpans, + String otelStatusCode, + String dbSqlTable, + String dbSystem, + String dbOperation, + String dbUser, + String dbName, + String jdbcUrl) { + assertThat(resourceScopeSpans) + .satisfiesOnlyOnce( + rss -> { + assertThat(rss.getSpan().getKind()).isEqualTo(SPAN_KIND_CLIENT); + assertThat(rss.getSpan().getStatus().getCode().toString()).isEqualTo(otelStatusCode); + assertSemanticConventionForOperation(rss, dbOperation, dbName, dbSqlTable); + var attributesList = rss.getSpan().getAttributesList(); + assertSemanticConventionsAttributes( + attributesList, dbSystem, dbUser, dbName, jdbcUrl); + assertSemanticConventionsAttributesForOperation( + attributesList, dbOperation, dbSqlTable); + }); + } + + private void assertSemanticConventionForOperation( + ResourceScopeSpan rss, String dbOperation, String dbName, String dbSqlTable) { + if (dbOperation.equals(DB_CREATE_DATABASE_OPERATION)) { + assertThat(rss.getSpan().getName()).isEqualTo(String.format("%s", dbName)); + } else if (dbOperation.equals(DB_SELECT_OPERATION)) { + assertThat(rss.getSpan().getName()) + .isEqualTo(String.format("%s %s.%s", dbOperation, dbName, dbSqlTable)); + } + } + + protected void assertSemanticConventionsAttributes( + List attributesList, + String dbSystem, + String dbUser, + String dbName, + String jdbcUrl) { + assertThat(attributesList) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.THREAD_ID); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.THREAD_NAME); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(SemanticConventionsConstants.DB_CONNECTION_STRING); + assertThat(attribute.getValue().getStringValue()).isEqualTo(jdbcUrl); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_NAME); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbName); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_USER); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbUser); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_SYSTEM); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbSystem); + }); + } + + private void assertSemanticConventionsAttributesForOperation( + List attributesList, String dbOperation, String dbSqlTable) { + if (dbOperation.equals(DB_CREATE_DATABASE_OPERATION)) { + assertThat(attributesList) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_STATEMENT); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(String.format("%s %s", dbOperation.toLowerCase(), CREATE_DB_NAME)); + }); + } else if (dbOperation.equals(DB_SELECT_OPERATION)) { + assertThat(attributesList) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_SQL_TABLE); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbSqlTable); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_STATEMENT); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo( + String.format( + "%s count(*) from %s", dbOperation.toLowerCase(), dbSqlTable)); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_OPERATION); + assertThat(attribute.getValue().getStringValue()).isEqualTo(dbOperation); + }); + } + } + + protected void assertMetricAttributes( + List resourceScopeMetrics, + String method, + String path, + String metricName, + Double expectedSum, + String dbSystem, + String dbOperation, + String type, + String identifier) { + assertThat(resourceScopeMetrics) + .anySatisfy( + metric -> { + assertThat(metric.getMetric().getName()).isEqualTo(metricName); + List dpList = + metric.getMetric().getExponentialHistogram().getDataPointsList(); + assertThat(dpList) + .satisfiesOnlyOnce( + dp -> { + List attributesList = dp.getAttributesList(); + assertThat(attributesList).isNotNull(); + var assertions = + assertThat(attributesList) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_SPAN_KIND); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo("CLIENT"); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_LOCAL_OPERATION); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(String.format("%s /%s", method, path)); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_LOCAL_SERVICE); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(getApplicationOtelServiceName()); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_REMOTE_SERVICE); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(dbSystem); + }) + .satisfiesOnlyOnce( + attribute -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_REMOTE_OPERATION); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(dbOperation); + }); + if (type != null && identifier != null) { + assertions.satisfiesOnlyOnce( + (attribute) -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_TYPE); + assertThat(attribute.getValue().getStringValue()).isEqualTo(type); + }); + assertions.satisfiesOnlyOnce( + (attribute) -> { + assertThat(attribute.getKey()) + .isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_IDENTIFIER); + assertThat(attribute.getValue().getStringValue()) + .isEqualTo(identifier); + }); + } + + if (expectedSum != null) { + double actualSum = dp.getSum(); + switch (metricName) { + case AppSignalsConstants.LATENCY_METRIC: + assertThat(actualSum).isStrictlyBetween(0.0, expectedSum); + break; + default: + assertThat(actualSum).isEqualTo(expectedSum); + } + } + }); + }); + } + protected void assertSuccess( String dbSystem, - DBOperation dbOperation, + String dbOperation, String dbUser, String dbName, String jdbcUrl, String type, String identifier) { - var path = "success/" + dbOperation.name(); + var path = "success/" + dbOperation; var method = "GET"; var otelStatusCode = "STATUS_CODE_UNSET"; var dbSqlTable = "employee"; - var otelApplicationImageName = getApplicationOtelServiceName(); - JdbcOperationTester operationTester = - JdbcOperationTesterProvider.getOperationTester( - dbOperation, dbSystem, dbUser, jdbcUrl, dbName, dbSqlTable); + var response = appClient.get(path).aggregate().join(); assertThat(response.status().isSuccess()).isTrue(); var traces = mockCollectorClient.getTraces(); - operationTester.assertAwsSpanAttributes( - traces, method, path, type, identifier, otelApplicationImageName); - operationTester.assertSemanticConventionsSpanAttributes(traces, otelStatusCode); + assertAwsSpanAttributes(traces, method, path, dbSystem, dbOperation, type, identifier); + assertSemanticConventionsSpanAttributes( + traces, otelStatusCode, dbSqlTable, dbSystem, dbOperation, dbUser, dbName, jdbcUrl); var metrics = mockCollectorClient.getMetrics( @@ -70,38 +337,41 @@ protected void assertSuccess( AppSignalsConstants.LATENCY_METRIC, AppSignalsConstants.ERROR_METRIC, AppSignalsConstants.FAULT_METRIC)); - operationTester.assertMetricAttributes( + assertMetricAttributes( metrics, method, path, AppSignalsConstants.LATENCY_METRIC, 5000.0, + dbSystem, + dbOperation, type, - identifier, - otelApplicationImageName); - operationTester.assertMetricAttributes( + identifier); + assertMetricAttributes( metrics, method, path, AppSignalsConstants.ERROR_METRIC, 0.0, + dbSystem, + dbOperation, type, - identifier, - otelApplicationImageName); - operationTester.assertMetricAttributes( + identifier); + assertMetricAttributes( metrics, method, path, AppSignalsConstants.FAULT_METRIC, 0.0, + dbSystem, + dbOperation, type, - identifier, - otelApplicationImageName); + identifier); } protected void assertFault( String dbSystem, - DBOperation dbOperation, + String dbOperation, String dbUser, String dbName, String jdbcUrl, @@ -111,17 +381,13 @@ protected void assertFault( var method = "GET"; var otelStatusCode = "STATUS_CODE_ERROR"; var dbSqlTable = "userrr"; - var otelApplicationImageName = getApplicationOtelServiceName(); - JdbcOperationTester operationTester = - JdbcOperationTesterProvider.getOperationTester( - dbOperation, dbSystem, dbUser, jdbcUrl, dbName, dbSqlTable); var response = appClient.get(path).aggregate().join(); assertThat(response.status().isServerError()).isTrue(); var traces = mockCollectorClient.getTraces(); - operationTester.assertAwsSpanAttributes( - traces, method, path, type, identifier, otelApplicationImageName); - operationTester.assertSemanticConventionsSpanAttributes(traces, otelStatusCode); + assertAwsSpanAttributes(traces, method, path, dbSystem, dbOperation, type, identifier); + assertSemanticConventionsSpanAttributes( + traces, otelStatusCode, dbSqlTable, dbSystem, dbOperation, dbUser, dbName, jdbcUrl); var metrics = mockCollectorClient.getMetrics( @@ -129,32 +395,35 @@ protected void assertFault( AppSignalsConstants.LATENCY_METRIC, AppSignalsConstants.ERROR_METRIC, AppSignalsConstants.FAULT_METRIC)); - operationTester.assertMetricAttributes( + assertMetricAttributes( metrics, method, path, AppSignalsConstants.LATENCY_METRIC, 5000.0, + dbSystem, + dbOperation, type, - identifier, - otelApplicationImageName); - operationTester.assertMetricAttributes( + identifier); + assertMetricAttributes( metrics, method, path, AppSignalsConstants.ERROR_METRIC, 0.0, + dbSystem, + dbOperation, type, - identifier, - otelApplicationImageName); - operationTester.assertMetricAttributes( + identifier); + assertMetricAttributes( metrics, method, path, AppSignalsConstants.FAULT_METRIC, 1.0, + dbSystem, + dbOperation, type, - identifier, - otelApplicationImageName); + identifier); } } diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcH2Test.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcH2Test.java index e7ba625bff..487874b84c 100644 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcH2Test.java +++ b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcH2Test.java @@ -19,7 +19,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.testcontainers.junit.jupiter.Testcontainers; -import software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.DBOperation; @Testcontainers(disabledWithoutDocker = true) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -32,14 +31,14 @@ public class JdbcH2Test extends JdbcContractTestBase { private static final String DB_PLATFORM = "org.hibernate.dialect.H2Dialect"; @Test - public void testSuccess() { + public void testSuccessSelect() { assertSuccess( - DB_SYSTEM, DBOperation.SELECT, DB_USER, DB_NAME, DB_CONNECTION_STRING, null, null); + DB_SYSTEM, DB_SELECT_OPERATION, DB_USER, DB_NAME, DB_CONNECTION_STRING, null, null); } @Test - public void testFault() { - assertFault(DB_SYSTEM, DBOperation.SELECT, DB_USER, DB_NAME, DB_CONNECTION_STRING, null, null); + public void testFaultSelect() { + assertFault(DB_SYSTEM, DB_SELECT_OPERATION, DB_USER, DB_NAME, DB_CONNECTION_STRING, null, null); } @Override diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcMySQLTest.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcMySQLTest.java index 98ce0848a3..5fa126e344 100644 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcMySQLTest.java +++ b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcMySQLTest.java @@ -17,19 +17,15 @@ import java.util.List; import java.util.Map; -import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance.Lifecycle; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.PullPolicy; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.lifecycle.Startable; -import software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.DBOperation; @Testcontainers(disabledWithoutDocker = true) @TestInstance(Lifecycle.PER_CLASS) @@ -52,16 +48,23 @@ public void afterEach() { mySQLContainer.stop(); } - private static Stream dbOperations() { - return Stream.of(DBOperation.SELECT, DBOperation.CREATE_DATABASE); + @Test + public void testSuccessCreateDatabase() { + assertSuccess( + DB_SYSTEM, + DB_CREATE_DATABASE_OPERATION, + DB_USER, + DB_NAME, + DB_CONNECTION_STRING, + DB_RESOURCE_TYPE, + MYSQL_IDENTIFIER); } - @ParameterizedTest - @MethodSource("dbOperations") - public void testSuccess(DBOperation operation) { + @Test + public void testSuccessSelect() { assertSuccess( DB_SYSTEM, - operation, + DB_SELECT_OPERATION, DB_USER, DB_NAME, DB_CONNECTION_STRING, @@ -70,10 +73,10 @@ public void testSuccess(DBOperation operation) { } @Test - public void testFault() { + public void testFaultSelect() { assertFault( DB_SYSTEM, - DBOperation.SELECT, + DB_SELECT_OPERATION, DB_USER, DB_NAME, DB_CONNECTION_STRING, diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcPostgresTest.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcPostgresTest.java index 0d89a21811..be873d4590 100644 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcPostgresTest.java +++ b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/JdbcPostgresTest.java @@ -17,18 +17,14 @@ import java.util.List; import java.util.Map; -import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.PullPolicy; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.lifecycle.Startable; -import software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.DBOperation; @Testcontainers(disabledWithoutDocker = true) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -52,16 +48,23 @@ public void afterEach() { postgreSqlContainer.stop(); } - private static Stream dbOperations() { - return Stream.of(DBOperation.SELECT, DBOperation.CREATE_DATABASE); + @Test + public void testSuccessCreateDatabase() { + assertSuccess( + DB_SYSTEM, + DB_CREATE_DATABASE_OPERATION, + DB_USER, + DB_NAME, + DB_CONNECTION_STRING, + DB_RESOURCE_TYPE, + POSTGRES_IDENTIFIER); } - @ParameterizedTest - @MethodSource("dbOperations") - public void testSuccess(DBOperation operation) { + @Test + public void testSuccessSelect() { assertSuccess( DB_SYSTEM, - operation, + DB_SELECT_OPERATION, DB_USER, DB_NAME, DB_CONNECTION_STRING, @@ -70,10 +73,10 @@ public void testSuccess(DBOperation operation) { } @Test - public void testFault() { + public void testFaultSelect() { assertFault( DB_SYSTEM, - DBOperation.SELECT, + DB_SELECT_OPERATION, DB_USER, DB_NAME, DB_CONNECTION_STRING, diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/DBOperation.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/DBOperation.java deleted file mode 100644 index 164a4bd291..0000000000 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/DBOperation.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.opentelemetry.appsignals.test.jdbc.operationtests; - -public enum DBOperation { - CREATE_DATABASE("CREATE DATABASE", "testdb2"), - SELECT("SELECT", "testdb"); - - DBOperation(String value, String targetDB) { - this.value = value; - this.targetDB = targetDB; - } - - private final String value; - private final String targetDB; - - public String getTargetDB() { - return targetDB; - } - - @Override - public String toString() { - return value; - } -} diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcCreateDatabaseOperationTester.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcCreateDatabaseOperationTester.java deleted file mode 100644 index 2fdcd6a563..0000000000 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcCreateDatabaseOperationTester.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.opentelemetry.appsignals.test.jdbc.operationtests; - -import static org.assertj.core.api.Assertions.assertThat; -import static software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.DBOperation.CREATE_DATABASE; - -import software.amazon.opentelemetry.appsignals.test.utils.ResourceScopeSpan; -import software.amazon.opentelemetry.appsignals.test.utils.SemanticConventionsConstants; - -public class JdbcCreateDatabaseOperationTester extends JdbcOperationTester { - - public JdbcCreateDatabaseOperationTester( - String dbSystem, String dbUser, String jdbcUrl, String dbName, String dbTable) { - super(dbSystem, dbUser, jdbcUrl, dbName, CREATE_DATABASE.toString(), dbTable); - } - - @Override - protected void assertOperationSemanticConventions(ResourceScopeSpan resourceScopeSpan) { - assertThat(resourceScopeSpan.getSpan().getName()).isEqualTo(String.format("%s", this.dbName)); - - var attributesList = resourceScopeSpan.getSpan().getAttributesList(); - assertThat(attributesList) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_STATEMENT); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo( - String.format( - "%s %s", - CREATE_DATABASE.toString().toLowerCase(), CREATE_DATABASE.getTargetDB())); - }); - } -} diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcOperationTester.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcOperationTester.java deleted file mode 100644 index c9b4f7a9fb..0000000000 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcOperationTester.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.opentelemetry.appsignals.test.jdbc.operationtests; - -import static io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_CLIENT; -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.proto.common.v1.KeyValue; -import io.opentelemetry.proto.metrics.v1.ExponentialHistogramDataPoint; -import java.util.List; -import software.amazon.opentelemetry.appsignals.test.utils.AppSignalsConstants; -import software.amazon.opentelemetry.appsignals.test.utils.ResourceScopeMetric; -import software.amazon.opentelemetry.appsignals.test.utils.ResourceScopeSpan; -import software.amazon.opentelemetry.appsignals.test.utils.SemanticConventionsConstants; - -public abstract class JdbcOperationTester { - - protected final String dbSystem; - protected final String dbUser; - protected final String jdbcUrl; - protected final String dbName; - protected final String dbOperation; - protected final String dbTable; - - protected JdbcOperationTester( - String dbSystem, - String dbUser, - String jdbcUrl, - String dbName, - String dbOperation, - String dbTable) { - this.dbSystem = dbSystem; - this.dbUser = dbUser; - this.jdbcUrl = jdbcUrl; - this.dbName = dbName; - this.dbOperation = dbOperation; - this.dbTable = dbTable; - } - - public void assertAwsSpanAttributes( - List resourceScopeSpans, - String method, - String path, - String type, - String identifier, - String applicationOtelServiceName) { - assertThat(resourceScopeSpans) - .satisfiesOnlyOnce( - rss -> { - assertThat(rss.getSpan().getKind()).isEqualTo(SPAN_KIND_CLIENT); - var attributesList = rss.getSpan().getAttributesList(); - assertAwsAttributes( - attributesList, method, path, type, identifier, applicationOtelServiceName); - }); - } - - private void assertAwsAttributes( - List attributesList, - String method, - String endpoint, - String type, - String identifier, - String applicationOtelServiceName) { - var assertions = - assertThat(attributesList) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_LOCAL_OPERATION); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(String.format("%s /%s", method, endpoint)); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_LOCAL_SERVICE); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(applicationOtelServiceName); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_REMOTE_SERVICE); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.dbSystem); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_REMOTE_OPERATION); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.dbOperation); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_SPAN_KIND); - assertThat(attribute.getValue().getStringValue()).isEqualTo("CLIENT"); - }); - if (type != null && identifier != null) { - assertions.satisfiesOnlyOnce( - (attribute) -> { - assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_TYPE); - assertThat(attribute.getValue().getStringValue()).isEqualTo(type); - }); - assertions.satisfiesOnlyOnce( - (attribute) -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_IDENTIFIER); - assertThat(attribute.getValue().getStringValue()).isEqualTo(identifier); - }); - } - } - - public void assertSemanticConventionsSpanAttributes( - List resourceScopeSpans, String otelStatusCode) { - assertThat(resourceScopeSpans) - .satisfiesOnlyOnce( - rss -> { - assertOperationSemanticConventions(rss); - assertSemanticConventionsCommon(rss, otelStatusCode); - }); - } - - protected abstract void assertOperationSemanticConventions(ResourceScopeSpan resourceScopeSpan); - - private void assertSemanticConventionsCommon(ResourceScopeSpan rss, String otelStatusCode) { - assertThat(rss.getSpan().getKind()).isEqualTo(SPAN_KIND_CLIENT); - assertThat(rss.getSpan().getStatus().getCode().toString()).isEqualTo(otelStatusCode); - var attributesList = rss.getSpan().getAttributesList(); - assertSemanticConventionsAttributes(attributesList); - } - - protected void assertSemanticConventionsAttributes(List attributesList) { - assertThat(attributesList) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.THREAD_ID); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.THREAD_NAME); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(SemanticConventionsConstants.DB_CONNECTION_STRING); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.jdbcUrl); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_NAME); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.dbName); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_USER); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.dbUser); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_SYSTEM); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.dbSystem); - }); - } - - public void assertMetricAttributes( - List resourceScopeMetrics, - String method, - String path, - String metricName, - Double expectedSum, - String type, - String identifier, - String applicationOtelServiceName) { - assertThat(resourceScopeMetrics) - .anySatisfy( - metric -> { - assertThat(metric.getMetric().getName()).isEqualTo(metricName); - List dpList = - metric.getMetric().getExponentialHistogram().getDataPointsList(); - assertThat(dpList) - .satisfiesOnlyOnce( - dp -> { - List attributesList = dp.getAttributesList(); - assertThat(attributesList).isNotNull(); - var assertions = - assertThat(attributesList) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_SPAN_KIND); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo("CLIENT"); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_LOCAL_OPERATION); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(String.format("%s /%s", method, path)); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_LOCAL_SERVICE); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(applicationOtelServiceName); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_REMOTE_SERVICE); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(this.dbSystem); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_REMOTE_OPERATION); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(this.dbOperation); - }); - if (type != null && identifier != null) { - assertions.satisfiesOnlyOnce( - (attribute) -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_TYPE); - assertThat(attribute.getValue().getStringValue()).isEqualTo(type); - }); - assertions.satisfiesOnlyOnce( - (attribute) -> { - assertThat(attribute.getKey()) - .isEqualTo(AppSignalsConstants.AWS_REMOTE_RESOURCE_IDENTIFIER); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo(identifier); - }); - } - - if (expectedSum != null) { - double actualSum = dp.getSum(); - switch (metricName) { - case AppSignalsConstants.LATENCY_METRIC: - assertThat(actualSum).isStrictlyBetween(0.0, expectedSum); - break; - default: - assertThat(actualSum).isEqualTo(expectedSum); - } - } - }); - }); - } -} diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcOperationTesterProvider.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcOperationTesterProvider.java deleted file mode 100644 index 06fa212323..0000000000 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcOperationTesterProvider.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.opentelemetry.appsignals.test.jdbc.operationtests; - -public class JdbcOperationTesterProvider { - - private JdbcOperationTesterProvider() {} - - public static JdbcOperationTester getOperationTester( - DBOperation operation, - String dbSystem, - String dbUser, - String jdbcUrl, - String dbName, - String dbTable) { - switch (operation) { - case CREATE_DATABASE: - return new JdbcCreateDatabaseOperationTester(dbSystem, dbUser, jdbcUrl, dbName, dbTable); - case SELECT: - return new JdbcSelectOperationTester(dbSystem, dbUser, jdbcUrl, dbName, dbTable); - default: - throw new UnsupportedOperationException("No tests for operation: " + operation); - } - } -} diff --git a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcSelectOperationTester.java b/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcSelectOperationTester.java deleted file mode 100644 index b08661ccd2..0000000000 --- a/appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/jdbc/operationtests/JdbcSelectOperationTester.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.opentelemetry.appsignals.test.jdbc.operationtests; - -import static org.assertj.core.api.Assertions.assertThat; -import static software.amazon.opentelemetry.appsignals.test.jdbc.operationtests.DBOperation.SELECT; - -import software.amazon.opentelemetry.appsignals.test.utils.ResourceScopeSpan; -import software.amazon.opentelemetry.appsignals.test.utils.SemanticConventionsConstants; - -public class JdbcSelectOperationTester extends JdbcOperationTester { - - public JdbcSelectOperationTester( - String dbSystem, String dbUser, String jdbcUrl, String dbName, String dbTable) { - super(dbSystem, dbUser, jdbcUrl, dbName, SELECT.toString(), dbTable); - } - - @Override - protected void assertOperationSemanticConventions(ResourceScopeSpan resourceScopeSpan) { - assertThat(resourceScopeSpan.getSpan().getName()) - .isEqualTo(String.format("%s %s.%s", SELECT, this.dbName, this.dbTable)); - - var attributesList = resourceScopeSpan.getSpan().getAttributesList(); - assertThat(attributesList) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_STATEMENT); - assertThat(attribute.getValue().getStringValue()) - .isEqualTo( - String.format( - "%s count(*) from %s", SELECT.toString().toLowerCase(), this.dbTable)); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_SQL_TABLE); - assertThat(attribute.getValue().getStringValue()).isEqualTo(this.dbTable); - }) - .satisfiesOnlyOnce( - attribute -> { - assertThat(attribute.getKey()).isEqualTo(SemanticConventionsConstants.DB_OPERATION); - assertThat(attribute.getValue().getStringValue()).isEqualTo(SELECT.toString()); - }); - } -} diff --git a/appsignals-tests/images/jdbc/src/main/java/software/amazon/opentelemetry/AppController.java b/appsignals-tests/images/jdbc/src/main/java/software/amazon/opentelemetry/AppController.java index 8789554862..81b1ff32ec 100644 --- a/appsignals-tests/images/jdbc/src/main/java/software/amazon/opentelemetry/AppController.java +++ b/appsignals-tests/images/jdbc/src/main/java/software/amazon/opentelemetry/AppController.java @@ -46,14 +46,10 @@ public void prepareDB() { logger.info("Application Ready"); } - @GetMapping("/success/CREATE_DATABASE") + @GetMapping("/success/CREATE DATABASE") @ResponseBody public ResponseEntity successCreateDatabase() { - try { - jdbcTemplate.execute("create database testdb2"); - } catch (Exception ex) { - return ResponseEntity.badRequest().body("failed"); - } + jdbcTemplate.execute("create database testdb2"); return ResponseEntity.ok().body("success"); }