diff --git a/src/DataDog.Tracing.AspNetCore/DataDog.Tracing.AspNetCore.csproj b/src/DataDog.Tracing.AspNetCore/DataDog.Tracing.AspNetCore.csproj index cec12cd..b7a3aee 100644 --- a/src/DataDog.Tracing.AspNetCore/DataDog.Tracing.AspNetCore.csproj +++ b/src/DataDog.Tracing.AspNetCore/DataDog.Tracing.AspNetCore.csproj @@ -1,6 +1,6 @@  - netstandard1.4 + netstandard2.0 datadog tracing apm aspnetcore A C# client implementation for DataDog's APM solution for AspNetCore. diff --git a/src/DataDog.Tracing.Sql.Tests/DataDog.Tracing.Sql.Tests.csproj b/src/DataDog.Tracing.Sql.Tests/DataDog.Tracing.Sql.Tests.csproj index f06ebf8..c18fa7b 100644 --- a/src/DataDog.Tracing.Sql.Tests/DataDog.Tracing.Sql.Tests.csproj +++ b/src/DataDog.Tracing.Sql.Tests/DataDog.Tracing.Sql.Tests.csproj @@ -1,6 +1,6 @@ - netcoreapp2.0 + netcoreapp2.2 false diff --git a/src/DataDog.Tracing.Sql.Tests/TraceDbCommandTests.cs b/src/DataDog.Tracing.Sql.Tests/TraceDbCommandTests.cs index 583cf38..e888d14 100644 --- a/src/DataDog.Tracing.Sql.Tests/TraceDbCommandTests.cs +++ b/src/DataDog.Tracing.Sql.Tests/TraceDbCommandTests.cs @@ -43,7 +43,7 @@ public void ExecuteReader_is_traced(CommandBehavior commandBehavior) } } customers.Count.Should().Be(2); - _root.Spans[1].Name.Should().Be("sql." + nameof(IDbCommand.ExecuteReader)); + _root.Spans[1].Name.Should().Be("sql.ExecuteDbDataReader"); _root.Spans[1].Service.Should().Be("sql"); _root.Spans[1].Resource.Should().Be("main"); _root.Spans[1].Type.Should().Be("sql"); diff --git a/src/DataDog.Tracing.Sql/DataDog.Tracing.Sql.csproj b/src/DataDog.Tracing.Sql/DataDog.Tracing.Sql.csproj index 7735dd8..4a45da4 100644 --- a/src/DataDog.Tracing.Sql/DataDog.Tracing.Sql.csproj +++ b/src/DataDog.Tracing.Sql/DataDog.Tracing.Sql.csproj @@ -1,6 +1,6 @@  - netstandard1.4 + netstandard2.0 datadog tracing apm sql A C# client implementation for DataDog's APM solution for tracing ADO .NET implementations. diff --git a/src/DataDog.Tracing.Sql/TraceDbCommand.cs b/src/DataDog.Tracing.Sql/TraceDbCommand.cs index 909d179..4d96504 100644 --- a/src/DataDog.Tracing.Sql/TraceDbCommand.cs +++ b/src/DataDog.Tracing.Sql/TraceDbCommand.cs @@ -1,51 +1,105 @@ using System; using System.Data; +using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; namespace DataDog.Tracing.Sql { - public class TraceDbCommand : IDbCommand + public class TraceDbCommand : DbCommand { private const string ServiceName = "sql"; - private readonly IDbCommand _command; + private readonly DbCommand _command; private readonly ISpanSource _spanSource; - public TraceDbCommand(IDbCommand command) + public TraceDbCommand(DbCommand command) : this(command, TraceContextSpanSource.Instance) { } - public TraceDbCommand(IDbCommand command, ISpanSource spanSource) + public TraceDbCommand(DbCommand command, ISpanSource spanSource) { _command = command; _spanSource = spanSource; } public IDbCommand InnerCommand => _command; + + #region Overrides - public void Dispose() => _command.Dispose(); + public override string CommandText + { + get => _command.CommandText; + set => _command.CommandText = value; + } - public void Cancel() => _command.Cancel(); + public override int CommandTimeout + { + get => _command.CommandTimeout; + set => _command.CommandTimeout = value; + } - public IDbDataParameter CreateParameter() => _command.CreateParameter(); + public override CommandType CommandType + { + get => _command.CommandType; + set => _command.CommandType = value; + } - private void SetMeta(ISpan span) + protected override DbConnection DbConnection { - span.SetMeta("sql.CommandText", CommandText); - span.SetMeta("sql.CommandType", CommandType.ToString()); + get => _command.Connection; + set => _command.Connection = value; + } + + protected override DbParameterCollection DbParameterCollection + { + get => _command.Parameters; + } + + protected override DbTransaction DbTransaction + { + get => _command.Transaction; + set => _command.Transaction = value; } - public int ExecuteNonQuery() + public override bool DesignTimeVisible + { + get => _command.DesignTimeVisible; + set => _command.DesignTimeVisible = value; + } + + public override UpdateRowSource UpdatedRowSource + { + get => _command.UpdatedRowSource; + set => _command.UpdatedRowSource = value; + } + + public override void Cancel() + { + _command.Cancel(); + } + + protected override DbParameter CreateDbParameter() + { + return _command.CreateParameter(); + } + + public override int ExecuteNonQuery() { const string name = "sql." + nameof(ExecuteNonQuery); + var span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); + try { - var result = _command.ExecuteNonQuery(); + int result = _command.ExecuteNonQuery(); + if (span != null) { span.SetMeta("sql.RowsAffected", result.ToString()); SetMeta(span); } + return result; } catch (Exception ex) @@ -59,21 +113,23 @@ public int ExecuteNonQuery() } } - public IDataReader ExecuteReader() => ExecuteReader(CommandBehavior.Default); - - public IDataReader ExecuteReader(CommandBehavior behavior) + public override async Task ExecuteNonQueryAsync(CancellationToken cancellationToken) { - const string name = "sql." + nameof(ExecuteReader); + const string name = "sql." + nameof(ExecuteNonQueryAsync); + var span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); + try { + int result = await _command.ExecuteNonQueryAsync(cancellationToken); + if (span != null) { - const string metaKey = "sql." + nameof(CommandBehavior); - span.SetMeta(metaKey, behavior.ToString("x")); + span.SetMeta("sql.RowsAffected", result.ToString()); SetMeta(span); } - return _command.ExecuteReader(behavior); + + return result; } catch (Exception ex) { @@ -86,13 +142,19 @@ public IDataReader ExecuteReader(CommandBehavior behavior) } } - public object ExecuteScalar() + public override object ExecuteScalar() { const string name = "sql." + nameof(ExecuteScalar); - var span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); + + ISpan span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); + try { - if (span != null) SetMeta(span); + if (span != null) + { + SetMeta(span); + } + return _command.ExecuteScalar(); } catch (Exception ex) @@ -106,44 +168,123 @@ public object ExecuteScalar() } } - public void Prepare() => _command.Prepare(); - - public string CommandText + public override async Task ExecuteScalarAsync(CancellationToken cancellationToken) { - get => _command.CommandText; - set => _command.CommandText = value; - } + const string name = "sql." + nameof(ExecuteScalarAsync); + + ISpan span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); - public int CommandTimeout + try + { + if (span != null) + { + SetMeta(span); + } + + return await _command.ExecuteScalarAsync(cancellationToken); + } + catch (Exception ex) + { + span?.SetError(ex); + throw; + } + finally + { + span?.Dispose(); + } + } + + protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { - get => _command.CommandTimeout; - set => _command.CommandTimeout = value; + const string name = "sql." + nameof(ExecuteDbDataReader); + + ISpan span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); + + try + { + if (span != null) + { + const string metaKey = "sql." + nameof(CommandBehavior); + + span.SetMeta(metaKey, behavior.ToString("x")); + SetMeta(span); + } + + return _command.ExecuteReader(behavior); + } + catch (Exception ex) + { + span?.SetError(ex); + throw; + } + finally + { + span?.Dispose(); + } } - public CommandType CommandType + protected override async Task ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) { - get => _command.CommandType; - set => _command.CommandType = value; + const string name = "sql." + nameof(ExecuteDbDataReaderAsync); + + ISpan span = _spanSource.Begin(name, ServiceName, _command.Connection.Database, ServiceName); + + try + { + if (span != null) + { + const string metaKey = "sql." + nameof(CommandBehavior); + + span.SetMeta(metaKey, behavior.ToString("x")); + SetMeta(span); + } + + return await _command.ExecuteReaderAsync(behavior, cancellationToken); + } + catch (Exception ex) + { + span?.SetError(ex); + throw; + } + finally + { + span?.Dispose(); + } } - public IDbConnection Connection + public override void Prepare() { - get => _command.Connection; - set => _command.Connection = value; + _command.Prepare(); } - public IDataParameterCollection Parameters => _command.Parameters; + #endregion - public IDbTransaction Transaction + #region Private Methods + + private void SetMeta(ISpan span) { - get => _command.Transaction; - set => _command.Transaction = value; + span.SetMeta("sql.CommandText", CommandText); + span.SetMeta("sql.CommandType", CommandType.ToString()); } - public UpdateRowSource UpdatedRowSource + #endregion + + #region Dispose Pattern + + private bool _disposed; + + protected override void Dispose(bool disposing) { - get => _command.UpdatedRowSource; - set => _command.UpdatedRowSource = value; + if (disposing && !_disposed) + { + _command?.Dispose(); + } + + _disposed = true; + + base.Dispose(disposing); } + + #endregion } } diff --git a/src/DataDog.Tracing.Sql/TraceDbConnection.cs b/src/DataDog.Tracing.Sql/TraceDbConnection.cs index 9bb3bec..5524c33 100644 --- a/src/DataDog.Tracing.Sql/TraceDbConnection.cs +++ b/src/DataDog.Tracing.Sql/TraceDbConnection.cs @@ -1,44 +1,117 @@ using System; using System.Data; +using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; +using System.Transactions; +using IsolationLevel = System.Data.IsolationLevel; namespace DataDog.Tracing.Sql { - public class TraceDbConnection : IDbConnection + public class TraceDbConnection : DbConnection { - const string ServiceName = "sql"; + private const string ServiceName = "sql"; - readonly ISpanSource _spanSource; - readonly IDbConnection _connection; + private readonly ISpanSource _spanSource; + private readonly DbConnection _connection; - public TraceDbConnection(IDbConnection connection) + public TraceDbConnection(DbConnection connection) : this(connection, TraceContextSpanSource.Instance) { } - public TraceDbConnection(IDbConnection connection, ISpanSource spanSource) + public TraceDbConnection(DbConnection connection, ISpanSource spanSource) { _connection = connection ?? throw new ArgumentNullException(nameof(connection)); _spanSource = spanSource ?? throw new ArgumentNullException(nameof(spanSource)); } public IDbConnection InnerConnection => _connection; + + #region Overrides - public void Dispose() => _connection.Dispose(); + public override string ConnectionString + { + get => _connection.ConnectionString; + set => _connection.ConnectionString = value; + } + + public override int ConnectionTimeout + { + get => _connection.ConnectionTimeout; + } + + public override string Database + { + get => _connection.Database; + } + + public override string DataSource + { + get => _connection.DataSource; + } + + public override string ServerVersion + { + get => _connection.ServerVersion; + } + + public override ConnectionState State + { + get => _connection.State; + } + public override event StateChangeEventHandler StateChange + { + add => _connection.StateChange += value; + remove => _connection.StateChange -= value; + } + // todo - span around transactions - public IDbTransaction BeginTransaction() => _connection.BeginTransaction(); + protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) + { + return _connection.BeginTransaction(isolationLevel); + } + + public override void Close() + { + _connection.Close(); + } - public IDbTransaction BeginTransaction(IsolationLevel il) => _connection.BeginTransaction(il); + public override void ChangeDatabase(string databaseName) + { + _connection.ChangeDatabase(databaseName); + } + + protected override DbCommand CreateDbCommand() + { + return new TraceDbCommand(_connection.CreateCommand(), _spanSource); + } + + public override void EnlistTransaction(Transaction transaction) + { + _connection.EnlistTransaction(transaction); + } - public void ChangeDatabase(string databaseName) => _connection.ChangeDatabase(databaseName); + public override DataTable GetSchema() + { + return _connection.GetSchema(); + } - public void Close() => _connection.Close(); + public override DataTable GetSchema(string collectionName) + { + return _connection.GetSchema(collectionName); + } - public IDbCommand CreateCommand() => new TraceDbCommand(_connection.CreateCommand(), _spanSource); + public override DataTable GetSchema(string collectionName, string[] restrictionValues) + { + return _connection.GetSchema(collectionName, restrictionValues); + } - public void Open() + public override void Open() { - var span = _spanSource.Begin("sql.connect", ServiceName, _connection.Database, ServiceName); + ISpan span = _spanSource.Begin("sql.connect", ServiceName, _connection.Database, ServiceName); + try { _connection.Open(); @@ -54,16 +127,43 @@ public void Open() } } - public string ConnectionString + public override async Task OpenAsync(CancellationToken cancellationToken) { - get => _connection.ConnectionString; - set => _connection.ConnectionString = value; + ISpan span = _spanSource.Begin("sql.connect", ServiceName, _connection.Database, ServiceName); + + try + { + await _connection.OpenAsync(cancellationToken); + } + catch (Exception ex) + { + span?.SetError(ex); + throw; + } + finally + { + span?.Dispose(); + } } - public int ConnectionTimeout => _connection.ConnectionTimeout; + #endregion + + #region Dispose Pattern - public string Database => _connection.Database; + private bool _disposed; + + protected override void Dispose(bool disposing) + { + if (disposing && !_disposed) + { + _connection?.Dispose(); + } + + _disposed = true; + + base.Dispose(disposing); + } - public ConnectionState State => _connection.State; + #endregion } } diff --git a/src/DataDog.Tracing.Tests/DataDog.Tracing.Tests.csproj b/src/DataDog.Tracing.Tests/DataDog.Tracing.Tests.csproj index 9e2165d..8e4515c 100644 --- a/src/DataDog.Tracing.Tests/DataDog.Tracing.Tests.csproj +++ b/src/DataDog.Tracing.Tests/DataDog.Tracing.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp1.1 + netcoreapp2.2 false diff --git a/src/DataDog.Tracing/DataDog.Tracing.csproj b/src/DataDog.Tracing/DataDog.Tracing.csproj index 3b79c87..68f4573 100644 --- a/src/DataDog.Tracing/DataDog.Tracing.csproj +++ b/src/DataDog.Tracing/DataDog.Tracing.csproj @@ -1,6 +1,6 @@  - netstandard1.4 + netstandard2.0 datadog tracing apm A C# client implementation for DataDog's APM solution. diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b02e405..bbe50bf 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,10 +1,10 @@ - 1.0.5 - 1.0.5 + 2.0.0 + 2.0.0 bcuff bcuff - 2017 + 2019 https://github.com/bcuff/dd-trace-csharp/blob/master/LICENSE https://github.com/bcuff/dd-trace-csharp https://github.com/bcuff/dd-trace-csharp diff --git a/src/TestApp/TestApp.csproj b/src/TestApp/TestApp.csproj index 1dba18c..f464e2d 100644 --- a/src/TestApp/TestApp.csproj +++ b/src/TestApp/TestApp.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp1.1 + netcoreapp2.2