Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

NR-336630-Full-support-for-r2dbc-maria-db-client #2142

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions instrumentation/jdbc-mariadb-3.0.0/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
dependencies {
implementation(project(":agent-bridge"))
implementation(project(":agent-bridge-datastore"))
implementation("org.mariadb.jdbc:mariadb-java-client:3.0.3")

testImplementation("ch.vorburger.mariaDB4j:mariaDB4j:2.2.1")
testImplementation(project(":instrumentation:jdbc-generic")){ transitive = false }
}

jar {
manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.jdbc-mariadb-3.0.0' }
}

verifyInstrumentation {
passesOnly 'org.mariadb.jdbc:mariadb-java-client:(3.0.2-rc,)'
exclude 'org.mariadb.jdbc:mariadb-java-client:[3.0.0-alpha,3.0.2-rc]'
}

site {
title 'MariaDB Java Client'
type 'Datastore'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*
* * Copyright 2020 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/

package com.nr.agent.instrumentation.jdbc.mariadb;

import com.newrelic.agent.bridge.datastore.DatabaseVendor;
import com.newrelic.agent.bridge.datastore.DatastoreVendor;
import com.newrelic.agent.bridge.datastore.JdbcDatabaseVendor;

public class MariaDbDatabaseVendor extends JdbcDatabaseVendor {

public static final DatabaseVendor INSTANCE = new MariaDbDatabaseVendor();

private MariaDbDatabaseVendor() {
super("MariaDB", "mysql", false);
}

@Override
public DatastoreVendor getDatastoreVendor() {
return DatastoreVendor.MySQL;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
*
* * Copyright 2020 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/

package org.mariadb.jdbc;

import java.util.Properties;

import com.newrelic.agent.bridge.datastore.JdbcHelper;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.agent.instrumentation.jdbc.mariadb.MariaDbDatabaseVendor;

@Weave
public abstract class Driver {

public Connection connect(String url, Properties props) {
JdbcHelper.putVendor(getClass(), MariaDbDatabaseVendor.INSTANCE);
return Weaver.callOriginal();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
*
* * Copyright 2020 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/

package org.mariadb.jdbc;

import java.sql.Connection;

import com.newrelic.agent.bridge.datastore.JdbcHelper;
import com.newrelic.api.agent.weaver.Weave;
import com.newrelic.api.agent.weaver.Weaver;
import com.nr.agent.instrumentation.jdbc.mariadb.MariaDbDatabaseVendor;

@Weave
public abstract class MariaDbDataSource {

public Connection getConnection() {
JdbcHelper.putVendor(getClass(), MariaDbDatabaseVendor.INSTANCE);
return Weaver.callOriginal();
}

public Connection getConnection(String user, String password) {
JdbcHelper.putVendor(getClass(), MariaDbDatabaseVendor.INSTANCE);
return Weaver.callOriginal();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
*
* * Copyright 2020 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/

package org.mariadb.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import ch.vorburger.mariadb4j.DB;
import ch.vorburger.mariadb4j.DBConfigurationBuilder;
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 com.newrelic.api.agent.Trace;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(InstrumentationTestRunner.class)
@InstrumentationTestConfig(includePrefixes = {"org.mariadb.jdbc"})
public class MariaDbTest {

private static DB mariaDb;

private static String connectionString;
private static String dbName;

@BeforeClass
public static void setUpDb() throws Exception {
DBConfigurationBuilder builder = DBConfigurationBuilder.newBuilder()
.setPort(0); // This will automatically find a free port

dbName = "MariaDB" + System.currentTimeMillis();
mariaDb = DB.newEmbeddedDB(builder.build());
connectionString = builder.getURL(dbName);
mariaDb.start();

mariaDb.createDB(dbName);
mariaDb.source("maria-db-test.sql", null, null, dbName);
}

@AfterClass
public static void tearDownDb() throws Exception {
mariaDb.stop();
}

@Test
@Ignore
public void testPreparedStatementQuery() throws Exception {
mariaDbPreparedStatementQuery();

Introspector introspector = InstrumentationTestRunner.getIntrospector();
Assert.assertEquals(1, introspector.getFinishedTransactionCount());
DatastoreHelper helper = new DatastoreHelper("MySQL");
helper.assertAggregateMetrics();
helper.assertUnscopedOperationMetricCount("select", 1);
}

@Test
@Ignore
public void testCrud() throws Exception {
mariaDbInsert();
mariaDbReadInsert();
mariaDbUpdate();
mariaDbReadUpdate();
mariaDbDelete();
mariaDbReadDelete();

Introspector introspector = InstrumentationTestRunner.getIntrospector();
Assert.assertEquals(6, introspector.getFinishedTransactionCount());

DatastoreHelper helper = new DatastoreHelper("MySQL");
helper.assertAggregateMetrics();
helper.assertUnscopedOperationMetricCount("insert", 1); // C
helper.assertUnscopedOperationMetricCount("select", 3); // R (once per step)
helper.assertUnscopedOperationMetricCount("update", 1); // U
helper.assertUnscopedOperationMetricCount("delete", 1); // D
}

@Trace(dispatcher = true)
public void mariaDbPreparedStatementQuery() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");
PreparedStatement statement = connection.prepareStatement("SELECT id FROM testQuery WHERE value LIKE ?");
statement.setString(1, "cool");
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
long value = resultSet.getLong(1);
Assert.assertEquals(1, value);
} else {
Assert.fail("Unable to get any results from database");
}
connection.close();
}

@Trace(dispatcher = true)
public void mariaDbInsert() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");

PreparedStatement statement = connection.prepareStatement("INSERT INTO testCrud (id, value) VALUES (1, ?)");
statement.setString(1, "insert");
int inserted = statement.executeUpdate();
Assert.assertEquals(1, inserted); // Only 1 row to insert
connection.close();
}


@Trace(dispatcher = true)
public void mariaDbReadInsert() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT id FROM testCrud WHERE value = 'insert'");
if (resultSet.next()) {
long value = resultSet.getLong(1);
Assert.assertEquals(1, value);
} else {
Assert.fail("Unable to find inserted row");
}
connection.close();
}

@Trace(dispatcher = true)
public void mariaDbUpdate() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");

PreparedStatement statement = connection.prepareStatement("UPDATE testCrud SET value = ? WHERE id = ?");
statement.setString(1, "update");
statement.setInt(2, 1);
int updated = statement.executeUpdate();
Assert.assertEquals(1, updated); // Only 1 row to update
connection.close();
}

@Trace(dispatcher = true)
public void mariaDbReadUpdate() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");
Statement statement = connection.createStatement();
statement.execute("SELECT value FROM testCrud WHERE id = 1");
ResultSet resultSet = statement.getResultSet();
if (resultSet.next()) {
String value = resultSet.getString(1);
Assert.assertEquals("update", value);
} else {
Assert.fail("Unable to find updated row");
}
connection.close();
}

@Trace(dispatcher = true)
public void mariaDbDelete() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");

Statement statement = connection.createStatement();
int updated = statement.executeUpdate("DELETE FROM testCrud WHERE id = 1");
Assert.assertEquals(1, updated); // Only 1 row to remove
connection.close();
}

@Trace(dispatcher = true)
public void mariaDbReadDelete() throws Exception {
Connection connection = DriverManager.getConnection(connectionString, "root", "");
PreparedStatement statement = connection.prepareStatement("SELECT * FROM testCrud");
ResultSet resultSet = statement.executeQuery();
Assert.assertFalse("We found a row when we didn't expect one", resultSet.next());
connection.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE testQuery (id int not null primary key, value varchar(20));
INSERT INTO testQuery (id, value) VALUES (1, 'cool');
INSERT INTO testQuery (id, value) VALUES (2, 'nice');
INSERT INTO testQuery (id, value) VALUES (3, 'sweet');

CREATE TABLE testCrud (id int not null primary key, value varchar(20));
20 changes: 20 additions & 0 deletions instrumentation/r2dbc-mariadb-1.1.2/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
dependencies {
implementation(project(":agent-bridge"))
implementation(project(":agent-bridge-datastore"))
implementation("org.mariadb:r2dbc-mariadb:1.1.2")
testImplementation("ch.vorburger.mariaDB4j:mariaDB4j:2.2.1")
}

jar {
manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.r2dbc-mariadb-1.1.2' }
}

verifyInstrumentation {
passesOnly 'org.mariadb:r2dbc-mariadb:[1.1.2,1.2.1)'
excludeRegex(".*(alpha|beta|rc).*")
}

site {
title 'MariaDB R2DBC'
type 'Datastore'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.nr.agent.instrumentation.r2dbc;


public class CancelHandler implements Runnable {

private NRHolder holder = null;

public CancelHandler(NRHolder hold) {
holder = hold;
}


@Override
public void run() {
if(holder != null) {
holder.ignore();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.nr.agent.instrumentation.r2dbc;


import java.util.function.Consumer;

import com.newrelic.api.agent.DatastoreParameters;
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Segment;

public class NRHolder implements Consumer<Throwable>, Runnable {

private Segment segment = null;
private DatastoreParameters params = null;

public NRHolder(Segment seg, DatastoreParameters p) {
segment = seg;
params = p;
}

@Override
public void accept(Throwable t) {
NewRelic.noticeError(t);
segment.ignore();
segment = null;

}

@Override
public void run() {
if(segment != null) {
if(params != null) {
segment.reportAsExternal(params);
}
segment.end();
segment = null;
}
}

public void ignore() {
if(segment != null) {
segment.ignore();
segment = null;
}
}

}
Loading
Loading