From 0ece7c6b2fb63cce0c87a45ee34a458676ebec7c Mon Sep 17 00:00:00 2001 From: Koen Punt Date: Mon, 24 Jul 2023 17:00:13 +0200 Subject: [PATCH 1/5] make sure postgres starts on not already assigned port --- .../instrumentation/r2dbc/PostgresqlInstrumentedTest.java | 5 +++-- .../r2dbc/PostgresqlNoInstrumentationTest.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java b/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java index 3bd577a8a1..913bea9d03 100644 --- a/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java +++ b/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertEquals; import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; +import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; @RunWith(InstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "io.r2dbc.postgresql") @@ -27,7 +28,7 @@ public class PostgresqlInstrumentedTest { @Before public void setup() throws Exception { String databaseName = "Postgres" + System.currentTimeMillis(); - final String url = postgres.start("localhost", 5432, databaseName, "user", "password"); + final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); connection = Mono.from(connectionFactory.create()).block(); @@ -68,4 +69,4 @@ public void testBasicRequests() { helper.assertUnscopedStatementMetricCount("UPDATE", "USERS", 1); helper.assertUnscopedStatementMetricCount("DELETE", "USERS", 1); } -} \ No newline at end of file +} diff --git a/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java b/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java index 51115a235d..825d68078d 100644 --- a/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java +++ b/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertEquals; import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; +import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; @RunWith(InstrumentationTestRunner.class) @InstrumentationTestConfig(includePrefixes = "none") @@ -27,7 +28,7 @@ public class PostgresqlNoInstrumentationTest { @Before public void setup() throws Exception { String databaseName = "Postgres" + System.currentTimeMillis(); - final String url = postgres.start("localhost", 5432, databaseName, "user", "password"); + final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); connection = Mono.from(connectionFactory.create()).block(); @@ -59,4 +60,4 @@ public void testBasicRequests() { helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 0); helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 0); } -} \ No newline at end of file +} From e810581ec69e7805465d9cc06dac513e488b13c6 Mon Sep 17 00:00:00 2001 From: Koen Punt Date: Tue, 25 Jul 2023 12:47:28 +0200 Subject: [PATCH 2/5] add instrumentation for r2dbc-postgresql-1.0.0 --- .../r2dbc-postgresql-1.0.0/build.gradle | 20 ++++ .../PostgresqlStatement_Instrumentation.java | 21 +++++ .../java/io/r2dbc/postgresql/R2dbcUtils.java | 93 +++++++++++++++++++ .../r2dbc/PostgresqlInstrumentedTest.java | 72 ++++++++++++++ .../PostgresqlNoInstrumentationTest.java | 63 +++++++++++++ .../instrumentation/r2dbc/R2dbcTestUtils.java | 17 ++++ settings.gradle | 1 + 7 files changed, 287 insertions(+) create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/build.gradle create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java diff --git a/instrumentation/r2dbc-postgresql-1.0.0/build.gradle b/instrumentation/r2dbc-postgresql-1.0.0/build.gradle new file mode 100644 index 0000000000..09008d8f71 --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/build.gradle @@ -0,0 +1,20 @@ +dependencies { + implementation(project(":agent-bridge")) + implementation(project(":agent-bridge-datastore")) + implementation("org.postgresql:r2dbc-postgresql:1.0.2.RELEASE") + testImplementation("ru.yandex.qatools.embed:postgresql-embedded:2.10") +} + +jar { + manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.r2dbc-postgresql-1.0.0' } +} + +verifyInstrumentation { + passesOnly 'org.postgresql:r2dbc-postgresql:[1.0.0.RELEASE,)' + excludeRegex(".*(M1|M2|RC).*") +} + +site { + title 'PostgreSQL R2DBC' + type 'Datastore' +} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java new file mode 100644 index 0000000000..47abffd14b --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java @@ -0,0 +1,21 @@ +package io.r2dbc.postgresql; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.Weave; +import com.newrelic.api.agent.weaver.Weaver; +import io.r2dbc.postgresql.api.PostgresqlResult; +import reactor.core.publisher.Flux; + +@Weave(type = MatchType.ExactClass, originalName = "io.r2dbc.postgresql.PostgresqlStatement") +final class PostgresqlStatement_Instrumentation { + private final ParsedSql parsedSql = Weaver.callOriginal(); + private final ConnectionResources resources = Weaver.callOriginal(); + + public Flux execute() { + Flux request = Weaver.callOriginal(); + if(request != null && parsedSql != null && resources != null) { + return R2dbcUtils.wrapRequest(request, parsedSql.getSql(), resources.getConfiguration()); + } + return request; + } +} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java new file mode 100644 index 0000000000..49b373bccb --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java @@ -0,0 +1,93 @@ +package io.r2dbc.postgresql; + +import com.newrelic.agent.bridge.NoOpTransaction; +import com.newrelic.agent.bridge.datastore.DatastoreVendor; +import com.newrelic.agent.bridge.datastore.OperationAndTableName; +import com.newrelic.agent.bridge.datastore.R2dbcObfuscator; +import com.newrelic.agent.bridge.datastore.R2dbcOperation; +import com.newrelic.api.agent.DatastoreParameters; +import com.newrelic.api.agent.NewRelic; +import com.newrelic.api.agent.Segment; +import com.newrelic.api.agent.Transaction; +import io.r2dbc.postgresql.api.PostgresqlResult; +import io.r2dbc.postgresql.client.MultiHostConfiguration; +import io.r2dbc.postgresql.client.SingleHostConfiguration; +import org.reactivestreams.Subscription; +import reactor.core.publisher.Flux; +import reactor.util.annotation.Nullable; + +import java.util.List; +import java.util.function.Consumer; + +public class R2dbcUtils { + public static Flux wrapRequest(Flux request, String sql, PostgresqlConnectionConfiguration connectionConfiguration) { + if(request != null) { + Transaction transaction = NewRelic.getAgent().getTransaction(); + if(transaction != null && !(transaction instanceof NoOpTransaction)) { + Segment segment = transaction.startSegment("execute"); + + return request + .doOnSubscribe(reportExecution(sql, connectionConfiguration, segment)) + .doFinally((type) -> segment.end()); + } + } + return request; + } + + private static Consumer reportExecution(String sql, PostgresqlConnectionConfiguration connectionConfiguration, Segment segment) { + return (subscription) -> { + OperationAndTableName sqlOperation = R2dbcOperation.extractFrom(sql); + + if (sqlOperation != null) { + ServerHost serverHost = getServerHost(connectionConfiguration); + + if (serverHost != null) { + segment.reportAsExternal(DatastoreParameters + .product(DatastoreVendor.Postgres.name()) + .collection(sqlOperation.getTableName()) + .operation(sqlOperation.getOperation()) + .instance(serverHost.getHost(), serverHost.getPort()) + .databaseName(connectionConfiguration.getDatabase()) + .slowQuery(sql, R2dbcObfuscator.POSTGRES_QUERY_CONVERTER) + .build()); + } + } + }; + } + + private static @Nullable ServerHost getServerHost(PostgresqlConnectionConfiguration connectionConfiguration) { + SingleHostConfiguration singleHostConfiguration = connectionConfiguration.getSingleHostConfiguration(); + MultiHostConfiguration multiHostConfiguration = connectionConfiguration.getMultiHostConfiguration(); + + if (multiHostConfiguration != null) { + List hosts = multiHostConfiguration.getHosts(); + + return hosts.stream().findFirst() + .map(s -> new ServerHost(s.getHost(), s.getPort())).orElse(null); + } + + if (singleHostConfiguration != null && singleHostConfiguration.getHost() != null) { + return new ServerHost(singleHostConfiguration.getHost(), singleHostConfiguration.getPort()); + } + + return null; + } + + private static class ServerHost { + private final String host; + private final int port; + + public ServerHost(String host, int port) { + this.host = host; + this.port = port; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + } +} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java new file mode 100644 index 0000000000..913bea9d03 --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java @@ -0,0 +1,72 @@ +package com.nr.agent.instrumentation.r2dbc; + +import com.newrelic.agent.introspec.DatastoreHelper; +import com.newrelic.agent.introspec.InstrumentationTestConfig; +import com.newrelic.agent.introspec.InstrumentationTestRunner; +import com.newrelic.agent.introspec.Introspector; +import io.r2dbc.spi.Connection; +import io.r2dbc.spi.ConnectionFactories; +import io.r2dbc.spi.ConnectionFactory; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import reactor.core.publisher.Mono; +import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; + +import static org.junit.Assert.assertEquals; +import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; +import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; + +@RunWith(InstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = "io.r2dbc.postgresql") +public class PostgresqlInstrumentedTest { + + public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); + public static Connection connection; + + @Before + public void setup() throws Exception { + String databaseName = "Postgres" + System.currentTimeMillis(); + final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); + final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); + ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); + connection = Mono.from(connectionFactory.create()).block(); + Mono.from(connection.createStatement("CREATE TABLE IF NOT EXISTS USERS(id int primary key, first_name varchar(255), last_name varchar(255), age int);").execute()).block(); + Mono.from(connection.createStatement("TRUNCATE TABLE USERS;").execute()).block(); + } + + @AfterClass + public static void teardown() { + Mono.from(connection.close()).block(); + postgres.stop(); + } + + @Test + public void testBasicRequests() { + //Given + Introspector introspector = InstrumentationTestRunner.getIntrospector(); + DatastoreHelper helper = new DatastoreHelper("Postgres"); + + //When + R2dbcTestUtils.basicRequests(connection); + + //Then + assertEquals(1, introspector.getFinishedTransactionCount(1000)); + assertEquals(1, introspector.getTransactionNames().size()); + String transactionName = introspector.getTransactionNames().stream().findFirst().orElse(""); + helper.assertScopedStatementMetricCount(transactionName, "INSERT", "USERS", 1); + helper.assertScopedStatementMetricCount(transactionName, "SELECT", "USERS", 3); + helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 1); + helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 1); + helper.assertAggregateMetrics(); + helper.assertUnscopedOperationMetricCount("INSERT", 1); + helper.assertUnscopedOperationMetricCount("SELECT", 3); + helper.assertUnscopedOperationMetricCount("UPDATE", 1); + helper.assertUnscopedOperationMetricCount("DELETE", 1); + helper.assertUnscopedStatementMetricCount("INSERT", "USERS", 1); + helper.assertUnscopedStatementMetricCount("SELECT", "USERS", 3); + helper.assertUnscopedStatementMetricCount("UPDATE", "USERS", 1); + helper.assertUnscopedStatementMetricCount("DELETE", "USERS", 1); + } +} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java new file mode 100644 index 0000000000..825d68078d --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java @@ -0,0 +1,63 @@ +package com.nr.agent.instrumentation.r2dbc; + +import com.newrelic.agent.introspec.DatastoreHelper; +import com.newrelic.agent.introspec.InstrumentationTestConfig; +import com.newrelic.agent.introspec.InstrumentationTestRunner; +import com.newrelic.agent.introspec.Introspector; +import io.r2dbc.spi.Connection; +import io.r2dbc.spi.ConnectionFactories; +import io.r2dbc.spi.ConnectionFactory; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import reactor.core.publisher.Mono; +import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; + +import static org.junit.Assert.assertEquals; +import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; +import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; + +@RunWith(InstrumentationTestRunner.class) +@InstrumentationTestConfig(includePrefixes = "none") +public class PostgresqlNoInstrumentationTest { + + public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); + public static Connection connection; + + @Before + public void setup() throws Exception { + String databaseName = "Postgres" + System.currentTimeMillis(); + final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); + final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); + ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); + connection = Mono.from(connectionFactory.create()).block(); + Mono.from(connection.createStatement("CREATE TABLE IF NOT EXISTS USERS(id int primary key, first_name varchar(255), last_name varchar(255), age int);").execute()).block(); + Mono.from(connection.createStatement("TRUNCATE TABLE USERS;").execute()).block(); + } + + @AfterClass + public static void teardown() { + Mono.from(connection.close()).block(); + postgres.stop(); + } + + @Test + public void testBasicRequests() { + //Given + Introspector introspector = InstrumentationTestRunner.getIntrospector(); + DatastoreHelper helper = new DatastoreHelper("Postgres"); + + //When + R2dbcTestUtils.basicRequests(connection); + + //Then + assertEquals(1, introspector.getFinishedTransactionCount(1000)); + assertEquals(1, introspector.getTransactionNames().size()); + String transactionName = introspector.getTransactionNames().stream().findFirst().orElse(""); + helper.assertScopedStatementMetricCount(transactionName, "INSERT", "USERS", 0); + helper.assertScopedStatementMetricCount(transactionName, "SELECT", "USERS", 0); + helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 0); + helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 0); + } +} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java new file mode 100644 index 0000000000..9324bbda88 --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java @@ -0,0 +1,17 @@ +package com.nr.agent.instrumentation.r2dbc; + +import com.newrelic.api.agent.Trace; +import io.r2dbc.spi.Connection; +import reactor.core.publisher.Mono; + +public class R2dbcTestUtils { + @Trace(dispatcher = true) + public static void basicRequests(Connection connection) { + Mono.from(connection.createStatement("INSERT INTO USERS(id, first_name, last_name, age) VALUES(1, 'Max', 'Power', 30)").execute()).block(); + Mono.from(connection.createStatement("SELECT * FROM USERS WHERE last_name='Power'").execute()).block(); + Mono.from(connection.createStatement("UPDATE USERS SET age = 36 WHERE last_name = 'Power'").execute()).block(); + Mono.from(connection.createStatement("SELECT * FROM USERS WHERE last_name='Power'").execute()).block(); + Mono.from(connection.createStatement("DELETE FROM USERS WHERE last_name = 'Power'").execute()).block(); + Mono.from(connection.createStatement("SELECT * FROM USERS").execute()).block(); + } +} diff --git a/settings.gradle b/settings.gradle index 3d6120d011..19ccad03a7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -272,6 +272,7 @@ include 'instrumentation:r2dbc-h2' include 'instrumentation:r2dbc-mariadb' include 'instrumentation:r2dbc-mysql' include 'instrumentation:r2dbc-postgresql-0.9.0' +include 'instrumentation:r2dbc-postgresql-1.0.0' include 'instrumentation:r2dbc-mssql' include 'instrumentation:rabbit-amqp-2.7' include 'instrumentation:rabbit-amqp-3.5.0' From c8abb22bb73ee9327b9027cb495894ae3d6d432a Mon Sep 17 00:00:00 2001 From: Koen Punt Date: Fri, 28 Jul 2023 12:50:25 +0200 Subject: [PATCH 3/5] retrieve host and port from current connection --- .../PostgresqlStatement_Instrumentation.java | 2 +- .../java/io/r2dbc/postgresql/R2dbcUtils.java | 82 +++++++------------ .../ReactorNettyClient_Instrumentation.java | 16 ++++ 3 files changed, 46 insertions(+), 54 deletions(-) create mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java index 47abffd14b..51417ea6f1 100644 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java @@ -14,7 +14,7 @@ final class PostgresqlStatement_Instrumentation { public Flux execute() { Flux request = Weaver.callOriginal(); if(request != null && parsedSql != null && resources != null) { - return R2dbcUtils.wrapRequest(request, parsedSql.getSql(), resources.getConfiguration()); + return R2dbcUtils.wrapRequest(request, parsedSql.getSql(), resources.getClient(), resources.getConfiguration()); } return request; } diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java index 49b373bccb..8f3cf1e50d 100644 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java @@ -10,84 +10,60 @@ import com.newrelic.api.agent.Segment; import com.newrelic.api.agent.Transaction; import io.r2dbc.postgresql.api.PostgresqlResult; -import io.r2dbc.postgresql.client.MultiHostConfiguration; -import io.r2dbc.postgresql.client.SingleHostConfiguration; +import io.r2dbc.postgresql.client.Client; +import io.r2dbc.postgresql.client.ReactorNettyClient_Instrumentation; import org.reactivestreams.Subscription; import reactor.core.publisher.Flux; +import reactor.netty.Connection; import reactor.util.annotation.Nullable; -import java.util.List; +import java.net.InetSocketAddress; import java.util.function.Consumer; public class R2dbcUtils { - public static Flux wrapRequest(Flux request, String sql, PostgresqlConnectionConfiguration connectionConfiguration) { + public static Flux wrapRequest(Flux request, String sql, Client client, PostgresqlConnectionConfiguration connectionConfiguration) { if(request != null) { Transaction transaction = NewRelic.getAgent().getTransaction(); if(transaction != null && !(transaction instanceof NoOpTransaction)) { Segment segment = transaction.startSegment("execute"); return request - .doOnSubscribe(reportExecution(sql, connectionConfiguration, segment)) + .doOnSubscribe(reportExecution(sql, client, connectionConfiguration, segment)) .doFinally((type) -> segment.end()); } } return request; } - private static Consumer reportExecution(String sql, PostgresqlConnectionConfiguration connectionConfiguration, Segment segment) { + private static Consumer reportExecution(String sql, Client client, PostgresqlConnectionConfiguration connectionConfiguration, Segment segment) { return (subscription) -> { OperationAndTableName sqlOperation = R2dbcOperation.extractFrom(sql); - - if (sqlOperation != null) { - ServerHost serverHost = getServerHost(connectionConfiguration); - - if (serverHost != null) { - segment.reportAsExternal(DatastoreParameters - .product(DatastoreVendor.Postgres.name()) - .collection(sqlOperation.getTableName()) - .operation(sqlOperation.getOperation()) - .instance(serverHost.getHost(), serverHost.getPort()) - .databaseName(connectionConfiguration.getDatabase()) - .slowQuery(sql, R2dbcObfuscator.POSTGRES_QUERY_CONVERTER) - .build()); - } + InetSocketAddress socketAddress = extractSocketAddress(client); + if (sqlOperation != null && socketAddress != null) { + segment.reportAsExternal(DatastoreParameters + .product(DatastoreVendor.Postgres.name()) + .collection(sqlOperation.getTableName()) + .operation(sqlOperation.getOperation()) + .instance(socketAddress.getHostName(), socketAddress.getPort()) + .databaseName(connectionConfiguration.getDatabase()) + .slowQuery(sql, R2dbcObfuscator.POSTGRES_QUERY_CONVERTER) + .build()); } }; } - private static @Nullable ServerHost getServerHost(PostgresqlConnectionConfiguration connectionConfiguration) { - SingleHostConfiguration singleHostConfiguration = connectionConfiguration.getSingleHostConfiguration(); - MultiHostConfiguration multiHostConfiguration = connectionConfiguration.getMultiHostConfiguration(); - - if (multiHostConfiguration != null) { - List hosts = multiHostConfiguration.getHosts(); - - return hosts.stream().findFirst() - .map(s -> new ServerHost(s.getHost(), s.getPort())).orElse(null); - } - - if (singleHostConfiguration != null && singleHostConfiguration.getHost() != null) { - return new ServerHost(singleHostConfiguration.getHost(), singleHostConfiguration.getPort()); - } - - return null; - } - - private static class ServerHost { - private final String host; - private final int port; - - public ServerHost(String host, int port) { - this.host = host; - this.port = port; - } - - public String getHost() { - return host; - } - - public int getPort() { - return port; + public static @Nullable InetSocketAddress extractSocketAddress(Client client) { + try { + if(client instanceof ReactorNettyClient_Instrumentation) { + ReactorNettyClient_Instrumentation instrumentedClient = (ReactorNettyClient_Instrumentation) client; + Connection clientConnection = instrumentedClient.clientConnection; + if(clientConnection.channel().remoteAddress() != null && clientConnection.channel().remoteAddress() instanceof InetSocketAddress) { + return (InetSocketAddress) clientConnection.channel().remoteAddress(); + } + } + return null; + } catch(Exception exception) { + return null; } } } diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java new file mode 100644 index 0000000000..630cf32da1 --- /dev/null +++ b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java @@ -0,0 +1,16 @@ +package io.r2dbc.postgresql.client; + +import com.newrelic.api.agent.weaver.MatchType; +import com.newrelic.api.agent.weaver.NewField; +import com.newrelic.api.agent.weaver.Weave; +import reactor.netty.Connection; + +@Weave(type = MatchType.ExactClass, originalName = "io.r2dbc.postgresql.client.ReactorNettyClient") +public class ReactorNettyClient_Instrumentation { + @NewField + public final Connection clientConnection; + + private ReactorNettyClient_Instrumentation(Connection connection, ConnectionSettings settings) { + this.clientConnection = connection; + } +} From b59d6aae90ba2fa8d9363120e3615ec2cf18d527 Mon Sep 17 00:00:00 2001 From: Andre Onuki Date: Fri, 20 Oct 2023 10:12:02 -0400 Subject: [PATCH 4/5] Moving r2dbc-postgresql 1.0.0 instrumentation to 0.9.2 --- .../PostgresqlNoInstrumentationTest.java | 63 ---------------- .../r2dbc-postgresql-0.9.2/build.gradle | 4 +- .../PostgresqlStatement_Instrumentation.java | 2 +- .../java/io/r2dbc/postgresql/R2dbcUtils.java | 32 +++++++-- .../ReactorNettyClient_Instrumentation.java | 7 +- .../PostgresqlNoInstrumentationTest.java | 63 ---------------- .../r2dbc-postgresql-1.0.0/build.gradle | 20 ------ .../PostgresqlStatement_Instrumentation.java | 21 ------ .../java/io/r2dbc/postgresql/R2dbcUtils.java | 69 ------------------ .../r2dbc/PostgresqlInstrumentedTest.java | 72 ------------------- .../PostgresqlNoInstrumentationTest.java | 63 ---------------- .../instrumentation/r2dbc/R2dbcTestUtils.java | 17 ----- settings.gradle | 1 - 13 files changed, 36 insertions(+), 398 deletions(-) delete mode 100644 instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java rename instrumentation/{r2dbc-postgresql-1.0.0 => r2dbc-postgresql-0.9.2}/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java (75%) delete mode 100644 instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java delete mode 100644 instrumentation/r2dbc-postgresql-1.0.0/build.gradle delete mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java delete mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java delete mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java delete mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java delete mode 100644 instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java diff --git a/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java b/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java deleted file mode 100644 index 825d68078d..0000000000 --- a/instrumentation/r2dbc-postgresql-0.9.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.nr.agent.instrumentation.r2dbc; - -import com.newrelic.agent.introspec.DatastoreHelper; -import com.newrelic.agent.introspec.InstrumentationTestConfig; -import com.newrelic.agent.introspec.InstrumentationTestRunner; -import com.newrelic.agent.introspec.Introspector; -import io.r2dbc.spi.Connection; -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Mono; -import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; - -import static org.junit.Assert.assertEquals; -import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; - -@RunWith(InstrumentationTestRunner.class) -@InstrumentationTestConfig(includePrefixes = "none") -public class PostgresqlNoInstrumentationTest { - - public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); - public static Connection connection; - - @Before - public void setup() throws Exception { - String databaseName = "Postgres" + System.currentTimeMillis(); - final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); - final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); - ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); - connection = Mono.from(connectionFactory.create()).block(); - Mono.from(connection.createStatement("CREATE TABLE IF NOT EXISTS USERS(id int primary key, first_name varchar(255), last_name varchar(255), age int);").execute()).block(); - Mono.from(connection.createStatement("TRUNCATE TABLE USERS;").execute()).block(); - } - - @AfterClass - public static void teardown() { - Mono.from(connection.close()).block(); - postgres.stop(); - } - - @Test - public void testBasicRequests() { - //Given - Introspector introspector = InstrumentationTestRunner.getIntrospector(); - DatastoreHelper helper = new DatastoreHelper("Postgres"); - - //When - R2dbcTestUtils.basicRequests(connection); - - //Then - assertEquals(1, introspector.getFinishedTransactionCount(1000)); - assertEquals(1, introspector.getTransactionNames().size()); - String transactionName = introspector.getTransactionNames().stream().findFirst().orElse(""); - helper.assertScopedStatementMetricCount(transactionName, "INSERT", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "SELECT", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 0); - } -} diff --git a/instrumentation/r2dbc-postgresql-0.9.2/build.gradle b/instrumentation/r2dbc-postgresql-0.9.2/build.gradle index 5b34cb2235..c557eb7de8 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/build.gradle +++ b/instrumentation/r2dbc-postgresql-0.9.2/build.gradle @@ -10,8 +10,8 @@ jar { } verifyInstrumentation { - passesOnly 'org.postgresql:r2dbc-postgresql:[0.9.2,1.0.0.RELEASE)' - excludeRegex(".*(M1|M2|RC).*") + passesOnly 'org.postgresql:r2dbc-postgresql:[0.9.2,)' + exclude 'org.postgresql:r2dbc-postgresql:1.0.0.RC1' } site { diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java index 47abffd14b..51417ea6f1 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java @@ -14,7 +14,7 @@ final class PostgresqlStatement_Instrumentation { public Flux execute() { Flux request = Weaver.callOriginal(); if(request != null && parsedSql != null && resources != null) { - return R2dbcUtils.wrapRequest(request, parsedSql.getSql(), resources.getConfiguration()); + return R2dbcUtils.wrapRequest(request, parsedSql.getSql(), resources.getClient(), resources.getConfiguration()); } return request; } diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java index fef1630b27..7eae449b20 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java @@ -9,39 +9,61 @@ import com.newrelic.api.agent.NewRelic; import com.newrelic.api.agent.Segment; import com.newrelic.api.agent.Transaction; +import io.r2dbc.postgresql.PostgresqlConnectionConfiguration; import io.r2dbc.postgresql.api.PostgresqlResult; +import io.r2dbc.postgresql.client.Client; +import io.r2dbc.postgresql.client.ReactorNettyClient_Instrumentation; import org.reactivestreams.Subscription; import reactor.core.publisher.Flux; +import reactor.netty.Connection; +import reactor.util.annotation.Nullable; +import java.net.InetSocketAddress; import java.util.function.Consumer; public class R2dbcUtils { - public static Flux wrapRequest(Flux request, String sql, PostgresqlConnectionConfiguration connectionConfiguration) { + public static Flux wrapRequest(Flux request, String sql, Client client, PostgresqlConnectionConfiguration connectionConfiguration) { if(request != null) { Transaction transaction = NewRelic.getAgent().getTransaction(); if(transaction != null && !(transaction instanceof NoOpTransaction)) { Segment segment = transaction.startSegment("execute"); return request - .doOnSubscribe(reportExecution(sql, connectionConfiguration, segment)) + .doOnSubscribe(reportExecution(sql, client, connectionConfiguration, segment)) .doFinally((type) -> segment.end()); } } return request; } - private static Consumer reportExecution(String sql, PostgresqlConnectionConfiguration connectionConfiguration, Segment segment) { + private static Consumer reportExecution(String sql, Client client, PostgresqlConnectionConfiguration connectionConfiguration, Segment segment) { return (subscription) -> { OperationAndTableName sqlOperation = R2dbcOperation.extractFrom(sql); - if (sqlOperation != null) { + InetSocketAddress socketAddress = extractSocketAddress(client); + if (sqlOperation != null && socketAddress != null) { segment.reportAsExternal(DatastoreParameters .product(DatastoreVendor.Postgres.name()) .collection(sqlOperation.getTableName()) .operation(sqlOperation.getOperation()) - .instance(connectionConfiguration.getHost(), connectionConfiguration.getPort()) + .instance(socketAddress.getHostName(), socketAddress.getPort()) .databaseName(connectionConfiguration.getDatabase()) .slowQuery(sql, R2dbcObfuscator.POSTGRES_QUERY_CONVERTER) .build()); } }; } + + public static @Nullable InetSocketAddress extractSocketAddress(Client client) { + try { + if(client instanceof ReactorNettyClient_Instrumentation) { + ReactorNettyClient_Instrumentation instrumentedClient = (ReactorNettyClient_Instrumentation) client; + Connection clientConnection = instrumentedClient.clientConnection; + if(clientConnection.channel().remoteAddress() != null && clientConnection.channel().remoteAddress() instanceof InetSocketAddress) { + return (InetSocketAddress) clientConnection.channel().remoteAddress(); + } + } + return null; + } catch(Exception exception) { + return null; + } + } } diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java similarity index 75% rename from instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java rename to instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java index 630cf32da1..fc92b3f149 100644 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java @@ -3,14 +3,19 @@ import com.newrelic.api.agent.weaver.MatchType; import com.newrelic.api.agent.weaver.NewField; import com.newrelic.api.agent.weaver.Weave; +import io.r2dbc.postgresql.client.ConnectionSettings; import reactor.netty.Connection; +import java.util.Optional; +import java.util.TimeZone; + @Weave(type = MatchType.ExactClass, originalName = "io.r2dbc.postgresql.client.ReactorNettyClient") -public class ReactorNettyClient_Instrumentation { +public abstract class ReactorNettyClient_Instrumentation { @NewField public final Connection clientConnection; private ReactorNettyClient_Instrumentation(Connection connection, ConnectionSettings settings) { this.clientConnection = connection; } + } diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java b/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java deleted file mode 100644 index 825d68078d..0000000000 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.nr.agent.instrumentation.r2dbc; - -import com.newrelic.agent.introspec.DatastoreHelper; -import com.newrelic.agent.introspec.InstrumentationTestConfig; -import com.newrelic.agent.introspec.InstrumentationTestRunner; -import com.newrelic.agent.introspec.Introspector; -import io.r2dbc.spi.Connection; -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Mono; -import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; - -import static org.junit.Assert.assertEquals; -import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; - -@RunWith(InstrumentationTestRunner.class) -@InstrumentationTestConfig(includePrefixes = "none") -public class PostgresqlNoInstrumentationTest { - - public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); - public static Connection connection; - - @Before - public void setup() throws Exception { - String databaseName = "Postgres" + System.currentTimeMillis(); - final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); - final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); - ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); - connection = Mono.from(connectionFactory.create()).block(); - Mono.from(connection.createStatement("CREATE TABLE IF NOT EXISTS USERS(id int primary key, first_name varchar(255), last_name varchar(255), age int);").execute()).block(); - Mono.from(connection.createStatement("TRUNCATE TABLE USERS;").execute()).block(); - } - - @AfterClass - public static void teardown() { - Mono.from(connection.close()).block(); - postgres.stop(); - } - - @Test - public void testBasicRequests() { - //Given - Introspector introspector = InstrumentationTestRunner.getIntrospector(); - DatastoreHelper helper = new DatastoreHelper("Postgres"); - - //When - R2dbcTestUtils.basicRequests(connection); - - //Then - assertEquals(1, introspector.getFinishedTransactionCount(1000)); - assertEquals(1, introspector.getTransactionNames().size()); - String transactionName = introspector.getTransactionNames().stream().findFirst().orElse(""); - helper.assertScopedStatementMetricCount(transactionName, "INSERT", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "SELECT", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 0); - } -} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/build.gradle b/instrumentation/r2dbc-postgresql-1.0.0/build.gradle deleted file mode 100644 index 09008d8f71..0000000000 --- a/instrumentation/r2dbc-postgresql-1.0.0/build.gradle +++ /dev/null @@ -1,20 +0,0 @@ -dependencies { - implementation(project(":agent-bridge")) - implementation(project(":agent-bridge-datastore")) - implementation("org.postgresql:r2dbc-postgresql:1.0.2.RELEASE") - testImplementation("ru.yandex.qatools.embed:postgresql-embedded:2.10") -} - -jar { - manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.r2dbc-postgresql-1.0.0' } -} - -verifyInstrumentation { - passesOnly 'org.postgresql:r2dbc-postgresql:[1.0.0.RELEASE,)' - excludeRegex(".*(M1|M2|RC).*") -} - -site { - title 'PostgreSQL R2DBC' - type 'Datastore' -} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java deleted file mode 100644 index 51417ea6f1..0000000000 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.r2dbc.postgresql; - -import com.newrelic.api.agent.weaver.MatchType; -import com.newrelic.api.agent.weaver.Weave; -import com.newrelic.api.agent.weaver.Weaver; -import io.r2dbc.postgresql.api.PostgresqlResult; -import reactor.core.publisher.Flux; - -@Weave(type = MatchType.ExactClass, originalName = "io.r2dbc.postgresql.PostgresqlStatement") -final class PostgresqlStatement_Instrumentation { - private final ParsedSql parsedSql = Weaver.callOriginal(); - private final ConnectionResources resources = Weaver.callOriginal(); - - public Flux execute() { - Flux request = Weaver.callOriginal(); - if(request != null && parsedSql != null && resources != null) { - return R2dbcUtils.wrapRequest(request, parsedSql.getSql(), resources.getClient(), resources.getConfiguration()); - } - return request; - } -} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java b/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java deleted file mode 100644 index 8f3cf1e50d..0000000000 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.r2dbc.postgresql; - -import com.newrelic.agent.bridge.NoOpTransaction; -import com.newrelic.agent.bridge.datastore.DatastoreVendor; -import com.newrelic.agent.bridge.datastore.OperationAndTableName; -import com.newrelic.agent.bridge.datastore.R2dbcObfuscator; -import com.newrelic.agent.bridge.datastore.R2dbcOperation; -import com.newrelic.api.agent.DatastoreParameters; -import com.newrelic.api.agent.NewRelic; -import com.newrelic.api.agent.Segment; -import com.newrelic.api.agent.Transaction; -import io.r2dbc.postgresql.api.PostgresqlResult; -import io.r2dbc.postgresql.client.Client; -import io.r2dbc.postgresql.client.ReactorNettyClient_Instrumentation; -import org.reactivestreams.Subscription; -import reactor.core.publisher.Flux; -import reactor.netty.Connection; -import reactor.util.annotation.Nullable; - -import java.net.InetSocketAddress; -import java.util.function.Consumer; - -public class R2dbcUtils { - public static Flux wrapRequest(Flux request, String sql, Client client, PostgresqlConnectionConfiguration connectionConfiguration) { - if(request != null) { - Transaction transaction = NewRelic.getAgent().getTransaction(); - if(transaction != null && !(transaction instanceof NoOpTransaction)) { - Segment segment = transaction.startSegment("execute"); - - return request - .doOnSubscribe(reportExecution(sql, client, connectionConfiguration, segment)) - .doFinally((type) -> segment.end()); - } - } - return request; - } - - private static Consumer reportExecution(String sql, Client client, PostgresqlConnectionConfiguration connectionConfiguration, Segment segment) { - return (subscription) -> { - OperationAndTableName sqlOperation = R2dbcOperation.extractFrom(sql); - InetSocketAddress socketAddress = extractSocketAddress(client); - if (sqlOperation != null && socketAddress != null) { - segment.reportAsExternal(DatastoreParameters - .product(DatastoreVendor.Postgres.name()) - .collection(sqlOperation.getTableName()) - .operation(sqlOperation.getOperation()) - .instance(socketAddress.getHostName(), socketAddress.getPort()) - .databaseName(connectionConfiguration.getDatabase()) - .slowQuery(sql, R2dbcObfuscator.POSTGRES_QUERY_CONVERTER) - .build()); - } - }; - } - - public static @Nullable InetSocketAddress extractSocketAddress(Client client) { - try { - if(client instanceof ReactorNettyClient_Instrumentation) { - ReactorNettyClient_Instrumentation instrumentedClient = (ReactorNettyClient_Instrumentation) client; - Connection clientConnection = instrumentedClient.clientConnection; - if(clientConnection.channel().remoteAddress() != null && clientConnection.channel().remoteAddress() instanceof InetSocketAddress) { - return (InetSocketAddress) clientConnection.channel().remoteAddress(); - } - } - return null; - } catch(Exception exception) { - return null; - } - } -} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java deleted file mode 100644 index 913bea9d03..0000000000 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.nr.agent.instrumentation.r2dbc; - -import com.newrelic.agent.introspec.DatastoreHelper; -import com.newrelic.agent.introspec.InstrumentationTestConfig; -import com.newrelic.agent.introspec.InstrumentationTestRunner; -import com.newrelic.agent.introspec.Introspector; -import io.r2dbc.spi.Connection; -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Mono; -import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; - -import static org.junit.Assert.assertEquals; -import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; - -@RunWith(InstrumentationTestRunner.class) -@InstrumentationTestConfig(includePrefixes = "io.r2dbc.postgresql") -public class PostgresqlInstrumentedTest { - - public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); - public static Connection connection; - - @Before - public void setup() throws Exception { - String databaseName = "Postgres" + System.currentTimeMillis(); - final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); - final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); - ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); - connection = Mono.from(connectionFactory.create()).block(); - Mono.from(connection.createStatement("CREATE TABLE IF NOT EXISTS USERS(id int primary key, first_name varchar(255), last_name varchar(255), age int);").execute()).block(); - Mono.from(connection.createStatement("TRUNCATE TABLE USERS;").execute()).block(); - } - - @AfterClass - public static void teardown() { - Mono.from(connection.close()).block(); - postgres.stop(); - } - - @Test - public void testBasicRequests() { - //Given - Introspector introspector = InstrumentationTestRunner.getIntrospector(); - DatastoreHelper helper = new DatastoreHelper("Postgres"); - - //When - R2dbcTestUtils.basicRequests(connection); - - //Then - assertEquals(1, introspector.getFinishedTransactionCount(1000)); - assertEquals(1, introspector.getTransactionNames().size()); - String transactionName = introspector.getTransactionNames().stream().findFirst().orElse(""); - helper.assertScopedStatementMetricCount(transactionName, "INSERT", "USERS", 1); - helper.assertScopedStatementMetricCount(transactionName, "SELECT", "USERS", 3); - helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 1); - helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 1); - helper.assertAggregateMetrics(); - helper.assertUnscopedOperationMetricCount("INSERT", 1); - helper.assertUnscopedOperationMetricCount("SELECT", 3); - helper.assertUnscopedOperationMetricCount("UPDATE", 1); - helper.assertUnscopedOperationMetricCount("DELETE", 1); - helper.assertUnscopedStatementMetricCount("INSERT", "USERS", 1); - helper.assertUnscopedStatementMetricCount("SELECT", "USERS", 3); - helper.assertUnscopedStatementMetricCount("UPDATE", "USERS", 1); - helper.assertUnscopedStatementMetricCount("DELETE", "USERS", 1); - } -} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java deleted file mode 100644 index 825d68078d..0000000000 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlNoInstrumentationTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.nr.agent.instrumentation.r2dbc; - -import com.newrelic.agent.introspec.DatastoreHelper; -import com.newrelic.agent.introspec.InstrumentationTestConfig; -import com.newrelic.agent.introspec.InstrumentationTestRunner; -import com.newrelic.agent.introspec.Introspector; -import io.r2dbc.spi.Connection; -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Mono; -import ru.yandex.qatools.embed.postgresql.EmbeddedPostgres; - -import static org.junit.Assert.assertEquals; -import static ru.yandex.qatools.embed.postgresql.distribution.Version.Main.V9_6; -import static ru.yandex.qatools.embed.postgresql.util.SocketUtil.findFreePort; - -@RunWith(InstrumentationTestRunner.class) -@InstrumentationTestConfig(includePrefixes = "none") -public class PostgresqlNoInstrumentationTest { - - public static final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6); - public static Connection connection; - - @Before - public void setup() throws Exception { - String databaseName = "Postgres" + System.currentTimeMillis(); - final String url = postgres.start("localhost", findFreePort(), databaseName, "user", "password"); - final String updatedUrl = url.replace("jdbc", "r2dbc").replace("localhost", "user:password@localhost").replace("?user=user&password=password", ""); - ConnectionFactory connectionFactory = ConnectionFactories.get(updatedUrl); - connection = Mono.from(connectionFactory.create()).block(); - Mono.from(connection.createStatement("CREATE TABLE IF NOT EXISTS USERS(id int primary key, first_name varchar(255), last_name varchar(255), age int);").execute()).block(); - Mono.from(connection.createStatement("TRUNCATE TABLE USERS;").execute()).block(); - } - - @AfterClass - public static void teardown() { - Mono.from(connection.close()).block(); - postgres.stop(); - } - - @Test - public void testBasicRequests() { - //Given - Introspector introspector = InstrumentationTestRunner.getIntrospector(); - DatastoreHelper helper = new DatastoreHelper("Postgres"); - - //When - R2dbcTestUtils.basicRequests(connection); - - //Then - assertEquals(1, introspector.getFinishedTransactionCount(1000)); - assertEquals(1, introspector.getTransactionNames().size()); - String transactionName = introspector.getTransactionNames().stream().findFirst().orElse(""); - helper.assertScopedStatementMetricCount(transactionName, "INSERT", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "SELECT", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "UPDATE", "USERS", 0); - helper.assertScopedStatementMetricCount(transactionName, "DELETE", "USERS", 0); - } -} diff --git a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java b/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java deleted file mode 100644 index 9324bbda88..0000000000 --- a/instrumentation/r2dbc-postgresql-1.0.0/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.nr.agent.instrumentation.r2dbc; - -import com.newrelic.api.agent.Trace; -import io.r2dbc.spi.Connection; -import reactor.core.publisher.Mono; - -public class R2dbcTestUtils { - @Trace(dispatcher = true) - public static void basicRequests(Connection connection) { - Mono.from(connection.createStatement("INSERT INTO USERS(id, first_name, last_name, age) VALUES(1, 'Max', 'Power', 30)").execute()).block(); - Mono.from(connection.createStatement("SELECT * FROM USERS WHERE last_name='Power'").execute()).block(); - Mono.from(connection.createStatement("UPDATE USERS SET age = 36 WHERE last_name = 'Power'").execute()).block(); - Mono.from(connection.createStatement("SELECT * FROM USERS WHERE last_name='Power'").execute()).block(); - Mono.from(connection.createStatement("DELETE FROM USERS WHERE last_name = 'Power'").execute()).block(); - Mono.from(connection.createStatement("SELECT * FROM USERS").execute()).block(); - } -} diff --git a/settings.gradle b/settings.gradle index 6eddae7379..fd11d9eb3c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -277,7 +277,6 @@ include 'instrumentation:r2dbc-mariadb' include 'instrumentation:r2dbc-mysql' include 'instrumentation:r2dbc-postgresql-0.9.0' include 'instrumentation:r2dbc-postgresql-0.9.2' -include 'instrumentation:r2dbc-postgresql-1.0.0' include 'instrumentation:r2dbc-mssql' include 'instrumentation:rabbit-amqp-2.7' include 'instrumentation:rabbit-amqp-3.5.0' From c77d353fa084e59ba0346b3244608de4dec6a961 Mon Sep 17 00:00:00 2001 From: Andre Onuki Date: Mon, 23 Oct 2023 15:16:54 -0400 Subject: [PATCH 5/5] Adding copyright --- .../postgresql/PostgresqlStatement_Instrumentation.java | 6 ++++++ .../src/main/java/io/r2dbc/postgresql/R2dbcUtils.java | 6 ++++++ .../client/ReactorNettyClient_Instrumentation.java | 6 ++++++ .../instrumentation/r2dbc/PostgresqlInstrumentedTest.java | 6 ++++++ .../com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java | 6 ++++++ 5 files changed, 30 insertions(+) diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java index 51417ea6f1..552de0a0ee 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/PostgresqlStatement_Instrumentation.java @@ -1,3 +1,9 @@ +/* + * + * * Copyright 2023 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ package io.r2dbc.postgresql; import com.newrelic.api.agent.weaver.MatchType; diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java index 7eae449b20..aee9e3a309 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/R2dbcUtils.java @@ -1,3 +1,9 @@ +/* + * + * * Copyright 2023 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ package io.r2dbc.postgresql; import com.newrelic.agent.bridge.NoOpTransaction; diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java index fc92b3f149..c903b1e0d0 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient_Instrumentation.java @@ -1,3 +1,9 @@ +/* + * + * * Copyright 2023 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ package io.r2dbc.postgresql.client; import com.newrelic.api.agent.weaver.MatchType; diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java b/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java index 913bea9d03..95790ca30d 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/PostgresqlInstrumentedTest.java @@ -1,3 +1,9 @@ +/* + * + * * Copyright 2023 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ package com.nr.agent.instrumentation.r2dbc; import com.newrelic.agent.introspec.DatastoreHelper; diff --git a/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java b/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java index 9324bbda88..35819449ee 100644 --- a/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java +++ b/instrumentation/r2dbc-postgresql-0.9.2/src/test/java/com/nr/agent/instrumentation/r2dbc/R2dbcTestUtils.java @@ -1,3 +1,9 @@ +/* + * + * * Copyright 2023 New Relic Corporation. All rights reserved. + * * SPDX-License-Identifier: Apache-2.0 + * + */ package com.nr.agent.instrumentation.r2dbc; import com.newrelic.api.agent.Trace;