Skip to content

Commit

Permalink
Merge pull request #2146 from newrelic/mariadb-updates
Browse files Browse the repository at this point in the history
NR-336630-Full-support-for-r2dbc-maria-db-client - credit to @dhilpipre - clone of 2142
  • Loading branch information
jtduffy authored Nov 20, 2024
2 parents a57293a + ef4981c commit 9f6dfea
Show file tree
Hide file tree
Showing 31 changed files with 1,194 additions and 5 deletions.
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,18 @@
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,45 @@
package com.nr.agent.instrumentation.r2dbc;

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

import java.util.function.Consumer;

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

0 comments on commit 9f6dfea

Please sign in to comment.