diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Sql/Instrumentation.xml b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Sql/Instrumentation.xml
index 386c2adcf8..f75714b70e 100644
--- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Sql/Instrumentation.xml
+++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/Sql/Instrumentation.xml
@@ -70,14 +70,30 @@ SPDX-License-Identifier: Apache-2.0
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -196,6 +212,32 @@ SPDX-License-Identifier: Apache-2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -329,6 +371,19 @@ SPDX-License-Identifier: Apache-2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -359,9 +414,10 @@ SPDX-License-Identifier: Apache-2.0
-
+
+
diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MFALatestPackages/MFALatestPackages.csproj b/tests/Agent/IntegrationTests/SharedApplications/Common/MFALatestPackages/MFALatestPackages.csproj
index b30c668a81..5526da8af0 100644
--- a/tests/Agent/IntegrationTests/SharedApplications/Common/MFALatestPackages/MFALatestPackages.csproj
+++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MFALatestPackages/MFALatestPackages.csproj
@@ -66,6 +66,11 @@
+
+
+
+
+
diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/MultiFunctionApplicationHelpers.csproj b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/MultiFunctionApplicationHelpers.csproj
index 4fa25338c4..13c4870720 100644
--- a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/MultiFunctionApplicationHelpers.csproj
+++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/MultiFunctionApplicationHelpers.csproj
@@ -80,6 +80,13 @@
+
+
+
+
+
+
+
diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/Oracle/OracleExerciser.cs b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/Oracle/OracleExerciser.cs
new file mode 100644
index 0000000000..39044a5ae2
--- /dev/null
+++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/Oracle/OracleExerciser.cs
@@ -0,0 +1,220 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System;
+using OracleConfiguration = NewRelic.Agent.IntegrationTests.Shared.OracleConfiguration;
+using Oracle.ManagedDataAccess.Client;
+using System.Data;
+using System.Runtime.CompilerServices;
+using NewRelic.Agent.IntegrationTests.Shared.ReflectionHelpers;
+using NewRelic.Api.Agent;
+using System.Linq;
+using System.Threading.Tasks;
+using NewRelic.Agent.IntegrationTests.Shared;
+
+
+namespace MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle
+{
+ [Library]
+ public class OracleExerciser : IDisposable
+ {
+ private const string CreateHotelTableOracleSql = "CREATE TABLE {0} (HOTEL_ID INT NOT NULL, BOOKING_DATE DATE NOT NULL, " +
+ "ROOMS_TAKEN INT DEFAULT 0, PRIMARY KEY (HOTEL_ID, BOOKING_DATE))";
+ private const string DropHotelTableOracleSql = "DROP TABLE {0}";
+ private const string InsertHotelOracleSql = "INSERT INTO {0} (HOTEL_ID, BOOKING_DATE) VALUES (1, SYSDATE)";
+ private const string DeleteHotelOracleSql = "DELETE FROM {0} WHERE HOTEL_ID = 1";
+ private const string CountHotelOracleSql = "SELECT COUNT(*) FROM {0}";
+ private const string SelectFromUserTablesOracleSql = "SELECT DEGREE FROM user_tables WHERE ROWNUM <= 1";
+
+
+ private string _tableName;
+ private string _storedProcedureName;
+
+ [LibraryMethod]
+ public void InitializeTable(string tableName)
+ {
+ _tableName = tableName;
+ CreateTable();
+ }
+
+ [LibraryMethod]
+ public void InitializeStoredProcedure(string storedProcName)
+ {
+ _storedProcedureName = storedProcName;
+ CreateProcedure();
+ }
+
+ [LibraryMethod]
+ [Transaction]
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ public void ExerciseSync()
+ {
+ if (string.IsNullOrEmpty(_tableName))
+ throw new Exception("Initialize table before exercising.");
+
+ var connectionString = OracleConfiguration.OracleConnectionString;
+
+ using var connection = new OracleConnection(connectionString);
+ connection.Open();
+
+ using (var command = new OracleCommand(SelectFromUserTablesOracleSql, connection))
+ using (var reader = command.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ var foo = reader.GetString(reader.GetOrdinal("DEGREE"));
+ }
+ }
+
+ var insertSql = string.Format(InsertHotelOracleSql, _tableName);
+ var countSql = string.Format(CountHotelOracleSql, _tableName);
+ var deleteSql = string.Format(DeleteHotelOracleSql, _tableName);
+
+ using (var command = new OracleCommand(insertSql, connection))
+ {
+ var insertCount = command.ExecuteNonQuery();
+ }
+
+ using (var command = new OracleCommand(countSql, connection))
+ {
+ var hotelCount = command.ExecuteScalar();
+ }
+
+ using (var command = new OracleCommand(deleteSql, connection))
+ {
+ var deleteCount = command.ExecuteNonQuery();
+ }
+ }
+
+ [LibraryMethod]
+ [Transaction]
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ public async Task ExerciseAsync()
+ {
+ if (string.IsNullOrEmpty(_tableName))
+ throw new Exception("Initialize table before exercising.");
+
+ var connectionString = OracleConfiguration.OracleConnectionString;
+
+ using var connection = new OracleConnection(connectionString);
+ await connection.OpenAsync();
+
+ using (var command = new OracleCommand(SelectFromUserTablesOracleSql, connection))
+ using (var reader = await command.ExecuteReaderAsync())
+ {
+ while (await reader.ReadAsync())
+ {
+ var foo = reader.GetString(reader.GetOrdinal("DEGREE"));
+ }
+ }
+
+ var insertSql = string.Format(InsertHotelOracleSql, _tableName);
+ var countSql = string.Format(CountHotelOracleSql, _tableName);
+ var deleteSql = string.Format(DeleteHotelOracleSql, _tableName);
+
+ using (var command = new OracleCommand(insertSql, connection))
+ {
+ var insertCount = await command.ExecuteNonQueryAsync();
+ }
+
+ using (var command = new OracleCommand(countSql, connection))
+ {
+ var hotelCount = await command.ExecuteScalarAsync();
+ }
+
+ using (var command = new OracleCommand(deleteSql, connection))
+ {
+ var deleteCount = await command.ExecuteNonQueryAsync();
+ }
+ }
+
+ [LibraryMethod]
+ [Transaction]
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ public async Task ExerciseStoredProcedure()
+ {
+ if (string.IsNullOrEmpty(_storedProcedureName))
+ throw new Exception("Initialize stored procedure before exercising.");
+
+ using (var connection = new OracleConnection(OracleConfiguration.OracleConnectionString))
+ {
+ using var command = new OracleCommand(_storedProcedureName, connection);
+
+ await connection.OpenAsync();
+
+ command.CommandType = CommandType.StoredProcedure;
+
+ foreach (var p in DbParameterData.OracleParameters)
+ {
+ command.Parameters.Add(p.ParameterName, p.Value);
+ }
+
+ await command.ExecuteNonQueryAsync();
+ }
+ }
+
+ private void CreateTable()
+ {
+ var createTable = string.Format(CreateHotelTableOracleSql, _tableName);
+
+ var connectionString = OracleConfiguration.OracleConnectionString;
+
+ using var connection = new OracleConnection(connectionString);
+ connection.Open();
+
+ using var command = new OracleCommand(createTable, connection);
+ command.ExecuteNonQuery();
+ }
+
+ private void DropTable()
+ {
+ if (!string.IsNullOrEmpty(_tableName))
+ {
+ var dropTableSql = string.Format(DropHotelTableOracleSql, _tableName);
+
+ using var connection = new OracleConnection(OracleConfiguration.OracleConnectionString);
+ connection.Open();
+
+ using var command = new OracleCommand(dropTableSql, connection);
+ command.ExecuteNonQuery();
+ }
+ }
+
+ public void Dispose()
+ {
+ DropTable();
+ DropProcedure();
+ _tableName = null;
+ _storedProcedureName = null;
+ }
+
+ private readonly string createProcedureStatement = @"CREATE PROCEDURE {0} ({1}) IS BEGIN NULL; END {0};";
+ private readonly string dropProcedureStatement = @"DROP PROCEDURE {0}";
+
+ private void CreateProcedure()
+ {
+ var parameters = string.Join(", ", DbParameterData.OracleParameters.Select(x => $"{x.ParameterName} IN {x.DbTypeName}"));
+ var statement = string.Format(createProcedureStatement, _storedProcedureName, parameters);
+ using (var connection = new OracleConnection(OracleConfiguration.OracleConnectionString))
+ using (var command = new OracleCommand(statement, connection))
+ {
+ connection.Open();
+ command.ExecuteNonQuery();
+ }
+ }
+
+ private void DropProcedure()
+ {
+ if (!string.IsNullOrEmpty(_storedProcedureName))
+ {
+ var statement = string.Format(dropProcedureStatement, _storedProcedureName);
+ using (var connection = new OracleConnection(OracleConfiguration.OracleConnectionString))
+ using (var command = new OracleCommand(statement, connection))
+ {
+ connection.Open();
+ command.ExecuteNonQuery();
+ }
+ }
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcApplication/Controllers/OracleController.cs b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcApplication/Controllers/OracleController.cs
index 73167f61b0..7c7efe4a4b 100644
--- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcApplication/Controllers/OracleController.cs
+++ b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcApplication/Controllers/OracleController.cs
@@ -5,13 +5,9 @@
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using NewRelic.Agent.IntegrationTests.Shared;
-using Oracle.ManagedDataAccess.Client;
-using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
using System.Web.Mvc;
namespace BasicMvcApplication.Controllers
@@ -22,96 +18,6 @@ public class OracleController : Controller
private const string DeleteHotelOracleSql = "DELETE FROM {0} WHERE HOTEL_ID = 1";
private const string CountHotelOracleSql = "SELECT COUNT(*) FROM {0}";
- [HttpGet]
- public string Oracle(string tableName)
- {
- var teamMembers = new List();
-
- var connectionString = OracleConfiguration.OracleConnectionString;
-
- using (var connection = new OracleConnection(connectionString))
- {
- connection.Open();
-
- using (var command = new OracleCommand("SELECT DEGREE FROM user_tables WHERE ROWNUM <= 1", connection))
- {
- using (var reader = command.ExecuteReader())
- {
- while (reader.Read())
- {
- teamMembers.Add(reader.GetString(reader.GetOrdinal("DEGREE")));
- }
- }
- }
-
- var insertSql = string.Format(InsertHotelOracleSql, tableName);
- var countSql = string.Format(CountHotelOracleSql, tableName);
- var deleteSql = string.Format(DeleteHotelOracleSql, tableName);
-
- using (var command = new OracleCommand(insertSql, connection))
- {
- var insertCount = command.ExecuteNonQuery();
- }
-
- using (var command = new OracleCommand(countSql, connection))
- {
- var hotelCount = command.ExecuteScalar();
- }
-
- using (var command = new OracleCommand(deleteSql, connection))
- {
- var deleteCount = command.ExecuteNonQuery();
- }
- }
-
- return string.Join(",", teamMembers);
- }
-
- [HttpGet]
- public async Task OracleAsync(string tableName)
- {
- var teamMembers = new List();
-
- var connectionString = OracleConfiguration.OracleConnectionString;
-
- using (var connection = new OracleConnection(connectionString))
- {
- await connection.OpenAsync();
-
- using (var command = new OracleCommand("SELECT DEGREE FROM user_tables WHERE ROWNUM <= 1", connection))
- {
- using (var reader = await command.ExecuteReaderAsync())
- {
- while (await reader.ReadAsync())
- {
- teamMembers.Add(reader.GetString(reader.GetOrdinal("DEGREE")));
- }
- }
- }
-
- var insertSql = string.Format(InsertHotelOracleSql, tableName);
- var countSql = string.Format(CountHotelOracleSql, tableName);
- var deleteSql = string.Format(DeleteHotelOracleSql, tableName);
-
- using (var command = new OracleCommand(insertSql, connection))
- {
- var insertCount = await command.ExecuteNonQueryAsync();
- }
-
- using (var command = new OracleCommand(countSql, connection))
- {
- var hotelCount = await command.ExecuteScalarAsync();
- }
-
- using (var command = new OracleCommand(deleteSql, connection))
- {
- var deleteCount = await command.ExecuteNonQueryAsync();
- }
- }
-
- return string.Join(",", teamMembers);
- }
-
[HttpGet]
public string EnterpriseLibraryOracle(string tableName)
{
@@ -143,58 +49,5 @@ public string EnterpriseLibraryOracle(string tableName)
return string.Join(",", teamMembers);
}
-
- [HttpGet]
- public void OracleParameterizedStoredProcedure(string procedureName)
- {
- CreateProcedure(procedureName);
-
- try
- {
- using (var connection = new OracleConnection(OracleConfiguration.OracleConnectionString))
- using (var command = new OracleCommand(procedureName, connection))
- {
- connection.Open();
- command.CommandType = CommandType.StoredProcedure;
-
- foreach (var p in DbParameterData.OracleParameters)
- {
- command.Parameters.Add(p.ParameterName, p.Value);
- }
-
- command.ExecuteNonQuery();
- }
- }
- finally
- {
- DropProcedure(procedureName);
- }
- }
-
- private readonly string createProcedureStatment = @"CREATE PROCEDURE {0} ({1}) IS BEGIN NULL; END {0};";
- private readonly string dropProcedureStatement = @"DROP PROCEDURE {0}";
-
- private void CreateProcedure(string procedureName)
- {
- var parameters = string.Join(", ", DbParameterData.OracleParameters.Select(x => $"{x.ParameterName} IN {x.DbTypeName}"));
- var statement = string.Format(createProcedureStatment, procedureName, parameters);
- using (var connection = new OracleConnection(OracleConfiguration.OracleConnectionString))
- using (var command = new OracleCommand(statement, connection))
- {
- connection.Open();
- command.ExecuteNonQuery();
- }
- }
-
- private void DropProcedure(string procedureName)
- {
- var statement = string.Format(dropProcedureStatement, procedureName);
- using (var connection = new OracleConnection(OracleConfiguration.OracleConnectionString))
- using (var command = new OracleCommand(statement, connection))
- {
- connection.Open();
- command.ExecuteNonQuery();
- }
- }
}
}
diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleAsyncTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleAsyncTests.cs
index 3479fde241..29810e8738 100644
--- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleAsyncTests.cs
+++ b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleAsyncTests.cs
@@ -1,28 +1,32 @@
// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
-
using System;
using System.Collections.Generic;
using System.Linq;
using NewRelic.Agent.IntegrationTestHelpers;
-using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
+using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures;
using NewRelic.Agent.IntegrationTests.Shared;
-using NewRelic.Testing.Assertions;
+using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
using Xunit;
using Xunit.Abstractions;
namespace NewRelic.Agent.UnboundedIntegrationTests.Oracle
{
- [NetFrameworkTest]
- public class OracleAsyncTests : NewRelicIntegrationTest
+ public abstract class OracleAsyncTestsBase : NewRelicIntegrationTest
+ where TFixture : ConsoleDynamicMethodFixture
{
- private readonly RemoteServiceFixtures.OracleBasicMvcFixture _fixture;
+ private readonly ConsoleDynamicMethodFixture _fixture;
+ private readonly string _tableName;
- public OracleAsyncTests(RemoteServiceFixtures.OracleBasicMvcFixture fixture, ITestOutputHelper output) : base(fixture)
+ protected OracleAsyncTestsBase(TFixture fixture, ITestOutputHelper output) : base(fixture)
{
_fixture = fixture;
_fixture.TestLogger = output;
+ _tableName = GenerateTableName();
+
+ _fixture.AddCommand($"OracleExerciser InitializeTable {_tableName}"); // creates a new table. The table gets dropped automatically when the exerciser goes out of scope
+ _fixture.AddCommand($"OracleExerciser ExerciseAsync");
_fixture.AddActions
(
@@ -37,17 +41,15 @@ public OracleAsyncTests(RemoteServiceFixtures.OracleBasicMvcFixture fixture, ITe
configModifier.ForceTransactionTraces();
CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainThreshold", "1");
+ CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainEnabled", "true");
var instrumentationFilePath = $@"{fixture.DestinationNewRelicExtensionsDirectoryPath}\NewRelic.Providers.Wrapper.Sql.Instrumentation.xml";
- CommonUtils.SetAttributeOnTracerFactoryInNewRelicInstrumentation(
- instrumentationFilePath,
- "", "enabled", "true");
+ CommonUtils.SetAttributeOnTracerFactoryInNewRelicInstrumentation(instrumentationFilePath, "", "enabled", "true");
},
exerciseApplication: () =>
{
- _fixture.GetOracleAsync();
_fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1));
- _fixture.AgentLog.WaitForLogLine(AgentLogBase.SqlTraceDataLogLineRegex, TimeSpan.FromMinutes(1));
+ _fixture.AgentLog.WaitForLogLine(AgentLogBase.ShutdownLogLineRegex, TimeSpan.FromMinutes(1));
}
);
@@ -57,39 +59,45 @@ public OracleAsyncTests(RemoteServiceFixtures.OracleBasicMvcFixture fixture, ITe
[Fact]
public void Test()
{
- var expectedDatastoreCallCount = 4; // SELECT, INSERT, SELECT COUNT, DELETE from the endpoint exercised by GetOracleAsync()
+ var expectedDatastoreCallCount = 4; // SELECT, INSERT, COUNT, and DELETE from GetOracle() above
+
+ //This value is dictated by the query that is being run as part of this test. In this case, we're running a query that returns a single row.
+ //This results in two calls to read. Therefore the call count for the Iterate metric should be 2.
+ var expectedIterateCallCount = 2;
var expectedMetrics = new List
{
- new Assertions.ExpectedMetric { metricName = @"Datastore/all", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = @"Datastore/allWeb", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = @"Datastore/Oracle/all", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = @"Datastore/Oracle/allWeb", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/Oracle/{OracleConfiguration.OracleServer}/{OracleConfiguration.OraclePort}", callCount = expectedDatastoreCallCount},
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/select", callCount = 2 },
- new Assertions.ExpectedMetric { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/OracleAsync"},
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/select", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/select", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/OracleAsync"},
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/insert", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/insert", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/insert", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/OracleAsync"},
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/delete", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/delete", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/delete", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/OracleAsync"}
+ new() { metricName = @"Datastore/all", callCount = expectedDatastoreCallCount },
+ new() { metricName = @"Datastore/allOther", callCount = expectedDatastoreCallCount },
+ new() { metricName = @"Datastore/Oracle/all", callCount = expectedDatastoreCallCount },
+ new() { metricName = @"Datastore/Oracle/allOther", callCount = expectedDatastoreCallCount },
+ new() { metricName = $@"Datastore/instance/Oracle/{OracleConfiguration.OracleServer}/{OracleConfiguration.OraclePort}", callCount = expectedDatastoreCallCount},
+ new() { metricName = @"Datastore/operation/Oracle/select", callCount = 2 },
+ new() { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1 },
+ new() { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync"},
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/select", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/select", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync"},
+ new() { metricName = @"Datastore/operation/Oracle/insert", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/insert", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/insert", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync"},
+ new() { metricName = @"Datastore/operation/Oracle/delete", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/delete", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/delete", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync"},
+
+ new() { metricName = @"DotNet/DatabaseResult/Iterate" , callCount = expectedIterateCallCount },
+ new() { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync"}
};
var unexpectedMetrics = new List
{
- // The datastore operation happened inside a web transaction so there should be no allOther metrics
- new Assertions.ExpectedMetric { metricName = @"Datastore/allOther" },
- new Assertions.ExpectedMetric { metricName = @"Datastore/Oracle/allOther" },
-
- // The operation metric should not be scoped because the statement metric is scoped instead
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/select", metricScope = "WebTransaction/MVC/OracleController/OracleAsync" },
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/insert", metricScope = "WebTransaction/MVC/OracleController/OracleAsync" },
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/delete", metricScope = "WebTransaction/MVC/OracleController/OracleAsync" }
+ // The datastore operation happened inside a non-web transaction so there should be no allWeb metrics
+ new() { metricName = @"Datastore/allWeb" },
+ new() { metricName = @"Datastore/Oracle/allWeb"},
+
+ // The operation metric should not be scoped because the statement metric is scoped instead
+ new() { metricName = @"Datastore/operation/Oracle/select", metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync" },
+ new() { metricName = @"Datastore/operation/Oracle/insert", metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync" },
+ new() { metricName = @"Datastore/operation/Oracle/delete", metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync" }
};
-
var expectedTransactionTraceSegments = new List
{
"Datastore/statement/Oracle/user_tables/select"
@@ -99,66 +107,98 @@ public void Test()
{
"databaseDuration"
};
-
- var expectedTransactionTraceSegmentParameters = new List
- {
- new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/Oracle/user_tables/select", parameterName = "sql", parameterValue = "SELECT DEGREE FROM user_tables WHERE ROWNUM <= ?"}
- };
-
var expectedSqlTraces = new List
{
- new Assertions.ExpectedSqlTrace
+ new()
{
- TransactionName = "WebTransaction/MVC/OracleController/OracleAsync",
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync",
Sql = "SELECT DEGREE FROM user_tables WHERE ROWNUM <= ?",
DatastoreMetricName = "Datastore/statement/Oracle/user_tables/select",
HasExplainPlan = false
},
- new Assertions.ExpectedSqlTrace
+ new()
{
- TransactionName = "WebTransaction/MVC/OracleController/OracleAsync",
- Sql = $"SELECT COUNT(*) FROM {_fixture.TableName}",
- DatastoreMetricName = $"Datastore/statement/Oracle/{_fixture.TableName}/select",
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync",
+ Sql = $"SELECT COUNT(*) FROM {_tableName}",
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_tableName}/select",
HasExplainPlan = false
},
- new Assertions.ExpectedSqlTrace
+ new()
{
- TransactionName = "WebTransaction/MVC/OracleController/OracleAsync",
- Sql = $"INSERT INTO {_fixture.TableName} (HOTEL_ID, BOOKING_DATE) VALUES (?, SYSDATE)",
- DatastoreMetricName = $"Datastore/statement/Oracle/{_fixture.TableName}/insert",
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync",
+ Sql = $"INSERT INTO {_tableName} (HOTEL_ID, BOOKING_DATE) VALUES (?, SYSDATE)",
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_tableName}/insert",
HasExplainPlan = false
},
- new Assertions.ExpectedSqlTrace
+ new()
{
- TransactionName = "WebTransaction/MVC/OracleController/OracleAsync",
- Sql = $"DELETE FROM {_fixture.TableName} WHERE HOTEL_ID = ?",
- DatastoreMetricName = $"Datastore/statement/Oracle/{_fixture.TableName}/delete",
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync",
+ Sql = $"DELETE FROM {_tableName} WHERE HOTEL_ID = ?",
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_tableName}/delete",
HasExplainPlan = false
}
};
var metrics = _fixture.AgentLog.GetMetrics().ToList();
- var transactionSample = _fixture.AgentLog.TryGetTransactionSample("WebTransaction/MVC/OracleController/OracleAsync");
- var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent("WebTransaction/MVC/OracleController/OracleAsync");
+ var transactionSample = _fixture.AgentLog.TryGetTransactionSample("OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync");
+ var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent("OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseAsync");
var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList();
- NrAssert.Multiple(
+ Assert.Multiple(
() => Assert.NotNull(transactionSample),
() => Assert.NotNull(transactionEvent)
);
- NrAssert.Multiple
+ Assert.Multiple
(
() => Assertions.MetricsExist(expectedMetrics, metrics),
() => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics),
() => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample),
() => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent),
- () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces),
- () => Assertions.TransactionTraceSegmentParametersExist(expectedTransactionTraceSegmentParameters, transactionSample)
+ () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces)
);
}
+
+ private static string GenerateTableName()
+ {
+ //Oracle tables must start w/ character and be <= 30 length. Table name = H{tableId}
+ var tableId = Guid.NewGuid().ToString("N").Substring(2, 29).ToLower();
+ return $"h{tableId}";
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleAsyncTestsFramework462 : OracleAsyncTestsBase
+ {
+ public OracleAsyncTestsFramework462(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleAsyncTestsFramework471 : OracleAsyncTestsBase
+ {
+ public OracleAsyncTestsFramework471(ConsoleDynamicMethodFixtureFW471 fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleAsyncTestsFrameworkLatest : OracleAsyncTestsBase
+ {
+ public OracleAsyncTestsFrameworkLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetCoreTest]
+ public class OracleAsyncTestsCoreLatest : OracleAsyncTestsBase
+ {
+ public OracleAsyncTestsCoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
}
}
diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleStoredProcedureTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleStoredProcedureTests.cs
index e301319585..703731bd13 100644
--- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleStoredProcedureTests.cs
+++ b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleStoredProcedureTests.cs
@@ -1,30 +1,34 @@
// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
-
using System;
using System.Collections.Generic;
using System.Linq;
using NewRelic.Agent.IntegrationTestHelpers;
+using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures;
using NewRelic.Agent.IntegrationTests.Shared;
-using NewRelic.Agent.UnboundedIntegrationTests.RemoteServiceFixtures;
-using NewRelic.Testing.Assertions;
+using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
using Xunit;
using Xunit.Abstractions;
namespace NewRelic.Agent.UnboundedIntegrationTests.Oracle
{
- [NetFrameworkTest]
- public class OracleStoredProcedureTests : NewRelicIntegrationTest
+ public abstract class OracleStoredProcedureTestsBase : NewRelicIntegrationTest
+ where TFixture : ConsoleDynamicMethodFixture
{
- private readonly OracleBasicMvcFixture _fixture;
- private readonly string _procedureName = $"OracleTestStoredProc{Guid.NewGuid():N}".Substring(0, 30);
+ private readonly ConsoleDynamicMethodFixture _fixture;
+ private readonly string _storedProcedureName;
- public OracleStoredProcedureTests(OracleBasicMvcFixture fixture, ITestOutputHelper output) : base(fixture)
+ protected OracleStoredProcedureTestsBase(TFixture fixture, ITestOutputHelper output) : base(fixture)
{
_fixture = fixture;
_fixture.TestLogger = output;
+ _storedProcedureName = GenerateStoredProcedureName();
+
+ _fixture.AddCommand($"OracleExerciser InitializeStoredProcedure {_storedProcedureName}"); // creates a new stored procedure. The stored procedure gets dropped automatically when the exerciser goes out of scope)
+ _fixture.AddCommand($"OracleExerciser ExerciseStoredProcedure");
+
_fixture.AddActions
(
setupConfiguration: () =>
@@ -45,7 +49,6 @@ public OracleStoredProcedureTests(OracleBasicMvcFixture fixture, ITestOutputHelp
},
exerciseApplication: () =>
{
- _fixture.OracleParameterizedStoredProcedure(_procedureName);
_fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1));
_fixture.AgentLog.WaitForLogLine(AgentLogBase.TransactionTransformCompletedLogLineRegex, TimeSpan.FromMinutes(2));
_fixture.AgentLog.WaitForLogLine(AgentLogBase.SqlTraceDataLogLineRegex, TimeSpan.FromMinutes(1));
@@ -60,42 +63,42 @@ public void Test()
{
var expectedMetrics = new List
{
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_procedureName.ToLower()}/ExecuteProcedure", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_procedureName.ToLower()}/ExecuteProcedure", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/OracleParameterizedStoredProcedure"}
+ new() { metricName = $@"Datastore/statement/Oracle/{_storedProcedureName.ToLower()}/ExecuteProcedure", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_storedProcedureName.ToLower()}/ExecuteProcedure", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseStoredProcedure"}
};
var expectedTransactionTraceSegments = new List
{
- $"Datastore/statement/Oracle/{_procedureName.ToLower()}/ExecuteProcedure"
+ $"Datastore/statement/Oracle/{_storedProcedureName.ToLower()}/ExecuteProcedure"
};
var expectedQueryParameters = DbParameterData.OracleParameters.ToDictionary(p => p.ParameterName, p => p.ExpectedValue);
- var expectedTransactionTraceQueryParameters = new Assertions.ExpectedSegmentQueryParameters { segmentName = $"Datastore/statement/Oracle/{_procedureName.ToLower()}/ExecuteProcedure", QueryParameters = expectedQueryParameters };
+ var expectedTransactionTraceQueryParameters = new Assertions.ExpectedSegmentQueryParameters { segmentName = $"Datastore/statement/Oracle/{_storedProcedureName.ToLower()}/ExecuteProcedure", QueryParameters = expectedQueryParameters };
var expectedSqlTraces = new List
{
- new Assertions.ExpectedSqlTrace
+ new()
{
- TransactionName = "WebTransaction/MVC/OracleController/OracleParameterizedStoredProcedure",
- Sql = _procedureName,
- DatastoreMetricName = $"Datastore/statement/Oracle/{_procedureName.ToLower()}/ExecuteProcedure",
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseStoredProcedure",
+ Sql = _storedProcedureName,
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_storedProcedureName.ToLower()}/ExecuteProcedure",
QueryParameters = expectedQueryParameters,
HasExplainPlan = false
}
};
var metrics = _fixture.AgentLog.GetMetrics().ToList();
- var transactionSample = _fixture.AgentLog.TryGetTransactionSample("WebTransaction/MVC/OracleController/OracleParameterizedStoredProcedure");
- var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent("WebTransaction/MVC/OracleController/OracleParameterizedStoredProcedure");
+ var transactionSample = _fixture.AgentLog.TryGetTransactionSample("OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseStoredProcedure");
+ var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent("OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseStoredProcedure");
var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList();
- NrAssert.Multiple(
+ Assert.Multiple(
() => Assert.NotNull(transactionSample),
() => Assert.NotNull(transactionEvent)
);
- NrAssert.Multiple
+ Assert.Multiple
(
() => Assertions.MetricsExist(expectedMetrics, metrics),
() => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample),
@@ -103,5 +106,42 @@ public void Test()
() => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces)
);
}
+
+ private string GenerateStoredProcedureName()
+ {
+ return $"OracleStoredProcedureTest{Guid.NewGuid():N}".Substring(0, 30);
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleStoredProcedureTestsFramework462 : OracleStoredProcedureTestsBase
+ {
+ public OracleStoredProcedureTestsFramework462(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+
+ [NetFrameworkTest]
+ public class OracleStoredProcedureTestsFramework471 : OracleStoredProcedureTestsBase
+ {
+ public OracleStoredProcedureTestsFramework471(ConsoleDynamicMethodFixtureFW471 fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+ [NetFrameworkTest]
+ public class OracleStoredProcedureTestsFrameworkLatest : OracleStoredProcedureTestsBase
+ {
+ public OracleStoredProcedureTestsFrameworkLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetCoreTest]
+ public class OracleStoredProcedureTestsCoreLatest : OracleStoredProcedureTestsBase
+ {
+ public OracleStoredProcedureTestsCoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
}
}
diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleSyncTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleSyncTests.cs
new file mode 100644
index 0000000000..d62d928623
--- /dev/null
+++ b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleSyncTests.cs
@@ -0,0 +1,204 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NewRelic.Agent.IntegrationTestHelpers;
+using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures;
+using NewRelic.Agent.IntegrationTests.Shared;
+using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace NewRelic.Agent.UnboundedIntegrationTests.Oracle
+{
+ public abstract class OracleSyncTestsBase : NewRelicIntegrationTest
+ where TFixture : ConsoleDynamicMethodFixture
+ {
+ private readonly ConsoleDynamicMethodFixture _fixture;
+ private readonly string _tableName;
+
+ protected OracleSyncTestsBase(TFixture fixture, ITestOutputHelper output) : base(fixture)
+ {
+ _fixture = fixture;
+ _fixture.TestLogger = output;
+ _tableName = GenerateTableName();
+
+ _fixture.AddCommand($"OracleExerciser InitializeTable {_tableName}"); // creates a new table. The table gets dropped automatically when the exerciser goes out of scope
+ _fixture.AddCommand($"OracleExerciser ExerciseSync");
+
+ _fixture.AddActions
+ (
+ setupConfiguration: () =>
+ {
+ var configPath = fixture.DestinationNewRelicConfigFilePath;
+ var configModifier = new NewRelicConfigModifier(configPath);
+ configModifier.ConfigureFasterMetricsHarvestCycle(15);
+ configModifier.ConfigureFasterTransactionTracesHarvestCycle(15);
+ configModifier.ConfigureFasterSqlTracesHarvestCycle(15);
+
+ configModifier.ForceTransactionTraces();
+
+ CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainThreshold", "1");
+ CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainEnabled", "true");
+
+ var instrumentationFilePath = $@"{fixture.DestinationNewRelicExtensionsDirectoryPath}\NewRelic.Providers.Wrapper.Sql.Instrumentation.xml";
+ CommonUtils.SetAttributeOnTracerFactoryInNewRelicInstrumentation(instrumentationFilePath, "", "enabled", "true");
+ },
+ exerciseApplication: () =>
+ {
+ _fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1));
+ _fixture.AgentLog.WaitForLogLine(AgentLogBase.ShutdownLogLineRegex, TimeSpan.FromMinutes(1));
+ }
+ );
+
+ _fixture.Initialize();
+ }
+
+ [Fact]
+ public void Test()
+ {
+ var expectedDatastoreCallCount = 4; // SELECT, INSERT, COUNT, and DELETE from GetOracle() above
+
+ //This value is dictated by the query that is being run as part of this test. In this case, we're running a query that returns a single row.
+ //This results in two calls to read. Therefore the call count for the Iterate metric should be 2.
+ var expectedIterateCallCount = 2;
+
+ var expectedMetrics = new List
+ {
+ new() { metricName = @"Datastore/all", callCount = expectedDatastoreCallCount },
+ new() { metricName = @"Datastore/allOther", callCount = expectedDatastoreCallCount },
+ new() { metricName = @"Datastore/Oracle/all", callCount = expectedDatastoreCallCount },
+ new() { metricName = @"Datastore/Oracle/allOther", callCount = expectedDatastoreCallCount },
+ new() { metricName = $@"Datastore/instance/Oracle/{OracleConfiguration.OracleServer}/{OracleConfiguration.OraclePort}", callCount = expectedDatastoreCallCount},
+ new() { metricName = @"Datastore/operation/Oracle/select", callCount = 2 },
+ new() { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1 },
+ new() { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync"},
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/select", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/select", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync"},
+ new() { metricName = @"Datastore/operation/Oracle/insert", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/insert", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/insert", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync"},
+ new() { metricName = @"Datastore/operation/Oracle/delete", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/delete", callCount = 1 },
+ new() { metricName = $@"Datastore/statement/Oracle/{_tableName}/delete", callCount = 1, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync"},
+
+ new() { metricName = @"DotNet/DatabaseResult/Iterate" , callCount = expectedIterateCallCount },
+ new() { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount, metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync"}
+ };
+ var unexpectedMetrics = new List
+ {
+ // The datastore operation happened inside a non-web transaction so there should be no allWeb metrics
+ new() { metricName = @"Datastore/allWeb" },
+ new() { metricName = @"Datastore/Oracle/allWeb"},
+
+ // The operation metric should not be scoped because the statement metric is scoped instead
+ new() { metricName = @"Datastore/operation/Oracle/select", metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync" },
+ new() { metricName = @"Datastore/operation/Oracle/insert", metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync" },
+ new() { metricName = @"Datastore/operation/Oracle/delete", metricScope = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync" }
+ };
+ var expectedTransactionTraceSegments = new List
+ {
+ "Datastore/statement/Oracle/user_tables/select"
+ };
+
+ var expectedTransactionEventIntrinsicAttributes = new List
+ {
+ "databaseDuration"
+ };
+ var expectedSqlTraces = new List
+ {
+ new()
+ {
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync",
+ Sql = "SELECT DEGREE FROM user_tables WHERE ROWNUM <= ?",
+ DatastoreMetricName = "Datastore/statement/Oracle/user_tables/select",
+ HasExplainPlan = false
+ },
+ new()
+ {
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync",
+ Sql = $"SELECT COUNT(*) FROM {_tableName}",
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_tableName}/select",
+
+ HasExplainPlan = false
+ },
+ new()
+ {
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync",
+ Sql = $"INSERT INTO {_tableName} (HOTEL_ID, BOOKING_DATE) VALUES (?, SYSDATE)",
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_tableName}/insert",
+
+ HasExplainPlan = false
+ },
+ new()
+ {
+ TransactionName = "OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync",
+ Sql = $"DELETE FROM {_tableName} WHERE HOTEL_ID = ?",
+ DatastoreMetricName = $"Datastore/statement/Oracle/{_tableName}/delete",
+
+ HasExplainPlan = false
+ }
+ };
+
+ var metrics = _fixture.AgentLog.GetMetrics().ToList();
+ var transactionSample = _fixture.AgentLog.TryGetTransactionSample("OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync");
+ var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent("OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.Oracle.OracleExerciser/ExerciseSync");
+ var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList();
+
+ Assert.Multiple(
+ () => Assert.NotNull(transactionSample),
+ () => Assert.NotNull(transactionEvent)
+ );
+
+ Assert.Multiple
+ (
+ () => Assertions.MetricsExist(expectedMetrics, metrics),
+ () => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics),
+ () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample),
+ () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent),
+ () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces)
+ );
+ }
+
+ private static string GenerateTableName()
+ {
+ //Oracle tables must start w/ character and be <= 30 length. Table name = H{tableId}
+ var tableId = Guid.NewGuid().ToString("N").Substring(2, 29).ToLower();
+ return $"h{tableId}";
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleSyncTestsFramework462 : OracleSyncTestsBase
+ {
+ public OracleSyncTestsFramework462(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleSyncTestsFramework471 : OracleSyncTestsBase
+ {
+ public OracleSyncTestsFramework471(ConsoleDynamicMethodFixtureFW471 fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetFrameworkTest]
+ public class OracleSyncTestsFrameworkLatest : OracleSyncTestsBase
+ {
+ public OracleSyncTestsFrameworkLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+
+ [NetCoreTest]
+ public class OracleSyncTestsCoreLatest : OracleSyncTestsBase
+ {
+ public OracleSyncTestsCoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) : base(fixture, output)
+ {
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleTests.cs
deleted file mode 100644
index f794e94417..0000000000
--- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/Oracle/OracleTests.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2020 New Relic, Inc. All rights reserved.
-// SPDX-License-Identifier: Apache-2.0
-
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using NewRelic.Agent.IntegrationTestHelpers;
-using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
-using NewRelic.Agent.IntegrationTests.Shared;
-using NewRelic.Testing.Assertions;
-using Xunit;
-using Xunit.Abstractions;
-
-namespace NewRelic.Agent.UnboundedIntegrationTests.Oracle
-{
- [NetFrameworkTest]
- public class OracleTests : NewRelicIntegrationTest
- {
- private readonly RemoteServiceFixtures.OracleBasicMvcFixture _fixture;
-
- public OracleTests(RemoteServiceFixtures.OracleBasicMvcFixture fixture, ITestOutputHelper output) : base(fixture)
- {
- _fixture = fixture;
- _fixture.TestLogger = output;
-
- _fixture.AddActions
- (
- setupConfiguration: () =>
- {
- var configPath = fixture.DestinationNewRelicConfigFilePath;
- var configModifier = new NewRelicConfigModifier(configPath);
- configModifier.ConfigureFasterMetricsHarvestCycle(15);
- configModifier.ConfigureFasterTransactionTracesHarvestCycle(15);
- configModifier.ConfigureFasterSqlTracesHarvestCycle(15);
-
- configModifier.ForceTransactionTraces();
-
- CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainThreshold", "1");
-
- var instrumentationFilePath = $@"{fixture.DestinationNewRelicExtensionsDirectoryPath}\NewRelic.Providers.Wrapper.Sql.Instrumentation.xml";
- CommonUtils.SetAttributeOnTracerFactoryInNewRelicInstrumentation(instrumentationFilePath, "", "enabled", "true");
- },
- exerciseApplication: () =>
- {
- _fixture.GetOracle();
- _fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1));
- _fixture.AgentLog.WaitForLogLine(AgentLogBase.SqlTraceDataLogLineRegex, TimeSpan.FromMinutes(1));
- }
- );
-
- _fixture.Initialize();
- }
-
- [Fact]
- public void Test()
- {
- var expectedDatastoreCallCount = 4; // SELECT, INSERT, COUNT, and DELETE from GetOracle() above
-
- //This value is dictated by the query that is being run as part of this test. In this case, we're running a query that returns a single row.
- //This results in two calls to read. Therefore the call count for the Iterate metric should be 2.
- var expectedIterateCallCount = 2;
-
- var expectedMetrics = new List
- {
- new Assertions.ExpectedMetric { metricName = @"Datastore/all", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = @"Datastore/allWeb", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = @"Datastore/Oracle/all", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = @"Datastore/Oracle/allWeb", callCount = expectedDatastoreCallCount },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/Oracle/{OracleConfiguration.OracleServer}/{OracleConfiguration.OraclePort}", callCount = expectedDatastoreCallCount},
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/select", callCount = 2 },
- new Assertions.ExpectedMetric { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = @"Datastore/statement/Oracle/user_tables/select", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/Oracle"},
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/select", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/select", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/Oracle"},
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/insert", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/insert", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/insert", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/Oracle"},
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/delete", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/delete", callCount = 1 },
- new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/Oracle/{_fixture.TableName}/delete", callCount = 1, metricScope = "WebTransaction/MVC/OracleController/Oracle"},
-
- new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate" , callCount = expectedIterateCallCount },
- new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount, metricScope = "WebTransaction/MVC/OracleController/Oracle"}
- };
- var unexpectedMetrics = new List
- {
- // The datastore operation happened inside a web transaction so there should be no allOther metrics
- new Assertions.ExpectedMetric { metricName = @"Datastore/allOther" },
- new Assertions.ExpectedMetric { metricName = @"Datastore/Oracle/allOther"},
-
- // The operation metric should not be scoped because the statement metric is scoped instead
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/select", metricScope = "WebTransaction/MVC/OracleController/Oracle" },
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/insert", metricScope = "WebTransaction/MVC/OracleController/Oracle" },
- new Assertions.ExpectedMetric { metricName = @"Datastore/operation/Oracle/delete", metricScope = "WebTransaction/MVC/OracleController/Oracle" }
- };
- var expectedTransactionTraceSegments = new List
- {
- "Datastore/statement/Oracle/user_tables/select"
- };
-
- var expectedTransactionEventIntrinsicAttributes = new List
- {
- "databaseDuration"
- };
- var expectedSqlTraces = new List
- {
- new Assertions.ExpectedSqlTrace
- {
- TransactionName = "WebTransaction/MVC/OracleController/Oracle",
- Sql = "SELECT DEGREE FROM user_tables WHERE ROWNUM <= ?",
- DatastoreMetricName = "Datastore/statement/Oracle/user_tables/select",
- HasExplainPlan = false
- },
- new Assertions.ExpectedSqlTrace
- {
- TransactionName = "WebTransaction/MVC/OracleController/Oracle",
- Sql = $"SELECT COUNT(*) FROM {_fixture.TableName}",
- DatastoreMetricName = $"Datastore/statement/Oracle/{_fixture.TableName}/select",
-
- HasExplainPlan = false
- },
- new Assertions.ExpectedSqlTrace
- {
- TransactionName = "WebTransaction/MVC/OracleController/Oracle",
- Sql = $"INSERT INTO {_fixture.TableName} (HOTEL_ID, BOOKING_DATE) VALUES (?, SYSDATE)",
- DatastoreMetricName = $"Datastore/statement/Oracle/{_fixture.TableName}/insert",
-
- HasExplainPlan = false
- },
- new Assertions.ExpectedSqlTrace
- {
- TransactionName = "WebTransaction/MVC/OracleController/Oracle",
- Sql = $"DELETE FROM {_fixture.TableName} WHERE HOTEL_ID = ?",
- DatastoreMetricName = $"Datastore/statement/Oracle/{_fixture.TableName}/delete",
-
- HasExplainPlan = false
- }
- };
-
- var metrics = _fixture.AgentLog.GetMetrics().ToList();
- var transactionSample = _fixture.AgentLog.TryGetTransactionSample("WebTransaction/MVC/OracleController/Oracle");
- var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent("WebTransaction/MVC/OracleController/Oracle");
- var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList();
-
- NrAssert.Multiple(
- () => Assert.NotNull(transactionSample),
- () => Assert.NotNull(transactionEvent)
- );
-
- NrAssert.Multiple
- (
- () => Assertions.MetricsExist(expectedMetrics, metrics),
- () => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics),
- () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample),
- () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent),
- () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces)
- );
- }
- }
-}