diff --git a/Datadog.Trace.sln b/Datadog.Trace.sln
index d194eec941c9..0a57f35d256b 100644
--- a/Datadog.Trace.sln
+++ b/Datadog.Trace.sln
@@ -236,6 +236,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".azure-pipelines", ".azure-
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SynchronizeVersions", "tools\SynchronizeVersions\SynchronizeVersions.csproj", "{7F0BD409-FA74-4FB1-853F-D10D888E1542}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.MySql", "samples\Samples.MySql\Samples.MySql.csproj", "{42FA33DD-AEA3-4FF3-8319-F30244A666A4}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -744,6 +746,16 @@ Global
{7F0BD409-FA74-4FB1-853F-D10D888E1542}.Release|x64.Build.0 = Release|Any CPU
{7F0BD409-FA74-4FB1-853F-D10D888E1542}.Release|x86.ActiveCfg = Release|Any CPU
{7F0BD409-FA74-4FB1-853F-D10D888E1542}.Release|x86.Build.0 = Release|Any CPU
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Debug|x64.ActiveCfg = Debug|x64
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Debug|x64.Build.0 = Debug|x64
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Debug|x86.ActiveCfg = Debug|x86
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Debug|x86.Build.0 = Debug|x86
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Release|Any CPU.ActiveCfg = Release|x86
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Release|x64.ActiveCfg = Release|x64
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Release|x64.Build.0 = Release|x64
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Release|x86.ActiveCfg = Release|x86
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -797,6 +809,7 @@ Global
{6ABAD006-E206-488E-ACA1-1AA73F9B5146} = {FEBCE7DC-9FD1-48A6-B911-71ABB240A030}
{C52D6695-4E05-4930-88F8-0EFF8056A967} = {FEBCE7DC-9FD1-48A6-B911-71ABB240A030}
{7F0BD409-FA74-4FB1-853F-D10D888E1542} = {5D8E1F81-B820-4736-B797-271B0FE787EE}
+ {42FA33DD-AEA3-4FF3-8319-F30244A666A4} = {AA6F5582-3B71-49AC-AA39-8F7815AC46BE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
diff --git a/docker-compose.yml b/docker-compose.yml
index 11206a22d3db..8705b033bf1e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -43,6 +43,16 @@ services:
ports:
- "127.0.0.1:5432:5432"
+ mysql:
+ image: mysql/mysql-server:5.7
+ environment:
+ - MYSQL_DATABASE=world
+ - MYSQL_ROOT_PASSWORD=mysqldb
+ - MYSQL_USER=mysqldb
+ - MYSQL_PASSWORD=mysqldb
+ ports:
+ - "127.0.0.1:3306:3306"
+
sqlserver:
image: microsoft/mssql-server-linux:latest
ports:
@@ -163,6 +173,19 @@ services:
- POSTGRES_HOST=postgres
depends_on:
- postgres
+
+ Samples.MySql:
+ build:
+ context: ./
+ dockerfile: ./docker/dotnet.dockerfile
+ image: datadog-dotnet
+ command: bash -c "/project/docker/with-profiler-logs.bash wait-for-it mysql:3306 -- /project/docker/with-profiler.bash dotnet /project/samples/Samples.MySql/bin/Release/netcoreapp2.1/publish/Samples.MySql.dll"
+ volumes:
+ - ./:/project
+ environment:
+ - MYSQL_HOST=mysql
+ depends_on:
+ - mysql
Samples.MongoDB:
build:
@@ -191,6 +214,7 @@ services:
- ELASTICSEARCH5_HOST=elasticsearch5:9200
- SQLSERVER_CONNECTION_STRING=Server=sqlserver;Database=BlogDatabase;User=sa;Password=Strong!Passw0rd
- POSTGRES_HOST=postgres
+ - MYSQL_HOST=mysql
depends_on:
- servicestackredis
- stackexchangeredis
diff --git a/samples/Samples.MySql/Program.cs b/samples/Samples.MySql/Program.cs
new file mode 100644
index 000000000000..995f86e20408
--- /dev/null
+++ b/samples/Samples.MySql/Program.cs
@@ -0,0 +1,83 @@
+using System;
+using Datadog.Trace.ClrProfiler;
+using MySql.Data.MySqlClient;
+
+namespace Samples.MySql
+{
+ class Program
+ {
+ private static string Host()
+ {
+ return Environment.GetEnvironmentVariable("MYSQL_HOST") ?? "localhost";
+ }
+
+ private static string ConnectionString(string database)
+ {
+ return $"server={Host()};user=mysqldb;password=mysqldb;port=3306;database={database}";
+ }
+
+ private static void Main(string[] args)
+ {
+ Console.WriteLine($"Profiler attached: {Instrumentation.ProfilerAttached}");
+ Console.WriteLine($"Platform: {(Environment.Is64BitProcess ? "x64" : "x32")}");
+ Console.WriteLine();
+
+ Console.WriteLine("Opening the connection.");
+
+ string connStr = ConnectionString("world");
+ var conn = new MySqlConnection(connStr);
+ conn.Open();
+
+ Console.WriteLine("Creating the table for the continents.");
+
+ // Create table
+ var tableCommand =
+ new MySqlCommand(
+ "DROP TABLE IF EXISTS `continent`; CREATE TABLE continent (continent_id INT AUTO_INCREMENT, name VARCHAR(255) NOT NULL, PRIMARY KEY(continent_id));",
+ conn);
+ tableCommand.ExecuteNonQuery();
+
+ Console.WriteLine("Creating the continents.");
+
+ // Create continents
+ MySqlCommand createContinent;
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('Africa');", conn);
+ createContinent.ExecuteNonQuery();
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('Antarctica');", conn);
+ createContinent.ExecuteNonQuery();
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('Asia');", conn);
+ createContinent.ExecuteNonQuery();
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('Australia');", conn);
+ createContinent.ExecuteNonQuery();
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('Europe');", conn);
+ createContinent.ExecuteNonQuery();
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('North America');", conn);
+ createContinent.ExecuteNonQuery();
+ createContinent = new MySqlCommand("INSERT INTO continent (name) VALUES ('South America');", conn);
+ createContinent.ExecuteNonQuery();
+
+ try
+ {
+ Console.WriteLine("Beginning to read the continents.");
+ string sql = "SELECT continent_id, name FROM continent";
+ var readContinents = new MySqlCommand(sql, conn);
+ using (var rdr = readContinents.ExecuteReader())
+ {
+ while (rdr.Read())
+ {
+ Console.WriteLine(rdr[0] + " -- " + rdr[1]);
+ }
+ rdr.Close();
+ }
+ Console.WriteLine("Done reading the continents.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.ToString());
+ }
+
+ conn.Close();
+ Console.WriteLine("Done setting up, inserting, and reading from MySQL.");
+ }
+ }
+}
diff --git a/samples/Samples.MySql/Properties/launchSettings.json b/samples/Samples.MySql/Properties/launchSettings.json
new file mode 100644
index 000000000000..a6fbbc0dd4a6
--- /dev/null
+++ b/samples/Samples.MySql/Properties/launchSettings.json
@@ -0,0 +1,19 @@
+{
+ "profiles": {
+ "Samples.MySql": {
+ "commandName": "Project",
+ "environmentVariables": {
+ "COR_ENABLE_PROFILING": "1",
+ "COR_PROFILER": "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}",
+ "COR_PROFILER_PATH": "$(ProjectDir)$(OutputPath)profiler-lib\\Datadog.Trace.ClrProfiler.Native.dll",
+
+ "CORECLR_ENABLE_PROFILING": "1",
+ "CORECLR_PROFILER": "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}",
+ "CORECLR_PROFILER_PATH": "$(ProjectDir)$(OutputPath)profiler-lib\\Datadog.Trace.ClrProfiler.Native.dll",
+
+ "DD_INTEGRATIONS": "$(ProjectDir)$(OutputPath)profiler-lib\\integrations.json"
+ },
+ "nativeDebugging": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/Samples.MySql/Samples.MySql.csproj b/samples/Samples.MySql/Samples.MySql.csproj
new file mode 100644
index 000000000000..3a0fef0e4257
--- /dev/null
+++ b/samples/Samples.MySql/Samples.MySql.csproj
@@ -0,0 +1,13 @@
+
+
+
+ 8.0.17
+
+ false
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/Samples.Npgsql/Program.cs b/samples/Samples.Npgsql/Program.cs
index b3f71a5299f7..eb36fefc50c3 100644
--- a/samples/Samples.Npgsql/Program.cs
+++ b/samples/Samples.Npgsql/Program.cs
@@ -1,5 +1,4 @@
using System;
-using System.Data.Common;
using System.Linq;
using Datadog.Trace.ClrProfiler;
using Npgsql;
diff --git a/samples/Samples.SqlServer/Program.cs b/samples/Samples.SqlServer/Program.cs
index 007997c0d02a..e47e0b6c05a8 100644
--- a/samples/Samples.SqlServer/Program.cs
+++ b/samples/Samples.SqlServer/Program.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using Microsoft.EntityFrameworkCore;
namespace Samples.SqlServer
{
@@ -22,16 +23,37 @@ static void Main(string[] args)
db.SaveChanges();
}
- // Display all Blogs from the database
+ // Display all Blogs from the database synchronously
var query = from b in db.Blogs
orderby b.Name
select b;
- Console.WriteLine("All blogs in the database:");
+ Console.WriteLine("All blogs in the database from the synchronous call:");
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
+
+ var asyncName = "test-async";
+
+ var asyncBlog = (from b in db.Blogs where b.Name == asyncName select b).FirstOrDefaultAsync();
+ if (asyncBlog.Result == null)
+ {
+ blog = new Blog { Name = asyncName };
+ db.Blogs.Add(blog);
+ db.SaveChangesAsync().Wait();
+ }
+
+ // Display all Blogs from the database asynchronously
+ var asyncQueryTask = db.Blogs.Where(b => b.Name == asyncName).ToListAsync();
+
+ asyncQueryTask.Wait();
+
+ Console.WriteLine("All blogs in the database from the async call:");
+ foreach (var item in asyncQueryTask.Result)
+ {
+ Console.WriteLine(item.Name);
+ }
}
}
}
diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNetIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNetIntegration.cs
index 46f2f255e4e9..1123640936ad 100644
--- a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNetIntegration.cs
+++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNetIntegration.cs
@@ -1,9 +1,11 @@
using System;
using System.Data;
using System.Data.Common;
+using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Datadog.Trace.ClrProfiler.Emit;
+using Datadog.Trace.ClrProfiler.Helpers;
using Datadog.Trace.ExtensionMethods;
using Datadog.Trace.Logging;
@@ -16,6 +18,11 @@ public static class AdoNetIntegration
{
private const string IntegrationName = "AdoNet";
private const string Major4 = "4";
+ private const string FrameworkAssembly = "System.Data";
+ private const string CoreAssembly = "System.Data.Common";
+ private const string SystemDataCommonDbCommand = "System.Data.Common.DbCommand";
+ private const string SystemDataCommonDbDataReader = "System.Data.Common.DbDataReader";
+ private const string SystemDataCommonCommandBehavior = "System.Data.CommandBehavior";
private static readonly ILog Log = LogProvider.GetLogger(typeof(AdoNetIntegration));
@@ -29,15 +36,15 @@ public static class AdoNetIntegration
/// A pointer to the module version GUID.
/// The value returned by the instrumented method.
[InterceptMethod(
- TargetAssembly = "System.Data", // .NET Framework
- TargetType = "System.Data.Common.DbCommand",
- TargetSignatureTypes = new[] { "System.Data.Common.DbDataReader", "System.Data.CommandBehavior" },
+ TargetAssembly = FrameworkAssembly, // .NET Framework
+ TargetType = SystemDataCommonDbCommand,
+ TargetSignatureTypes = new[] { SystemDataCommonDbDataReader, SystemDataCommonCommandBehavior },
TargetMinimumVersion = Major4,
TargetMaximumVersion = Major4)]
[InterceptMethod(
- TargetAssembly = "System.Data.Common", // .NET Core
- TargetType = "System.Data.Common.DbCommand",
- TargetSignatureTypes = new[] { "System.Data.Common.DbDataReader", "System.Data.CommandBehavior" },
+ TargetAssembly = CoreAssembly, // .NET Core
+ TargetType = SystemDataCommonDbCommand,
+ TargetSignatureTypes = new[] { SystemDataCommonDbDataReader, SystemDataCommonCommandBehavior },
TargetMinimumVersion = Major4,
TargetMaximumVersion = Major4)]
public static object ExecuteDbDataReader(
@@ -47,24 +54,35 @@ public static object ExecuteDbDataReader(
int mdToken,
long moduleVersionPtr)
{
- var command = (DbCommand)@this;
+ Func