Skip to content

Cleanup | SqlDiagnosticListener Classes #3232

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ protected override void AfterCleared(SqlCommand owner)
private static bool _forceRetryableEnclaveQueryExecutionExceptionDuringGenerateEnclavePackage = false;
#endif

private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener(SqlDiagnosticListener.DiagnosticListenerName);
private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener();
private bool _parentOperationStarted = false;

internal static readonly Action<object> s_cancelIgnoreFailure = CancelIgnoreFailureCallback;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private enum CultureCheckState : uint
private SqlRetryLogicBaseProvider _retryLogicProvider;

// diagnostics listener
private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener(SqlDiagnosticListener.DiagnosticListenerName);
private static readonly SqlDiagnosticListener s_diagnosticListener = new SqlDiagnosticListener();

// Transient Fault handling flag. This is needed to convey to the downstream mechanism of connection establishment, if Transient Fault handling should be used or not
// The downstream handling of Connection open is the same for idle connection resiliency. Currently we want to apply transient fault handling only to the connections opened
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.Data.SqlClient
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlTransaction.xml' path='docs/members[@name="SqlTransaction"]/SqlTransaction/*' />
public sealed partial class SqlTransaction : DbTransaction
{
private static readonly SqlDiagnosticListener s_diagnosticListener = new(SqlDiagnosticListener.DiagnosticListenerName);
private static readonly SqlDiagnosticListener s_diagnosticListener = new();

////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,27 @@

namespace Microsoft.Data.SqlClient.Diagnostics
{
internal ref struct DiagnosticScope //: IDisposable //ref structs cannot implement interfaces but the compiler will use pattern matching
internal ref struct DiagnosticScope //: IDisposable
{
private const int CommandOperation = 1;
private const int ConnectionOpenOperation = 2;

private readonly object _context1;
private readonly object _context2;
private readonly SqlDiagnosticListener _diagnostics;
private readonly int _operation;
private readonly string _operationName;
private readonly Guid _operationId;
private readonly object _context1;
private readonly object _context2;
private readonly string _operationName;

private Exception _exception;

private DiagnosticScope(SqlDiagnosticListener diagnostics, int operation, Guid operationsId, string operationName, object context1, object context2)
private DiagnosticScope(
SqlDiagnosticListener diagnostics,
int operation,
Guid operationsId,
string operationName,
object context1,
object context2)
{
_diagnostics = diagnostics;
_operation = operation;
Expand All @@ -33,46 +40,70 @@ private DiagnosticScope(SqlDiagnosticListener diagnostics, int operation, Guid o
_exception = null;
}

public static DiagnosticScope CreateCommandScope(
SqlDiagnosticListener diagnostics,
SqlCommand command,
SqlTransaction transaction,
[CallerMemberName]
string operationName = "")
{
Guid operationId = diagnostics.WriteCommandBefore(command, transaction, operationName);
return new DiagnosticScope(diagnostics, CommandOperation, operationId, operationName, command, transaction);
}

// Although ref structs do not allow for inheriting from interfaces (< C#13), but the
// compiler will know to treat this like an IDisposable (> C# 8)
public void Dispose()
{
switch (_operation)
{
case CommandOperation:
if (_exception != null)
{
_diagnostics.WriteCommandError(_operationId, (SqlCommand)_context1, (SqlTransaction)_context2, _exception, _operationName);
_diagnostics.WriteCommandError(
_operationId,
(SqlCommand)_context1,
(SqlTransaction)_context2,
_exception,
_operationName);
}
else
{
_diagnostics.WriteCommandAfter(_operationId, (SqlCommand)_context1, (SqlTransaction)_context2, _operationName);
_diagnostics.WriteCommandAfter(
_operationId,
(SqlCommand)_context1,
(SqlTransaction)_context2,
_operationName);
}
break;

case ConnectionOpenOperation:
if (_exception != null)
{
_diagnostics.WriteConnectionOpenError(_operationId, (SqlConnection)_context1, _exception, _operationName);
_diagnostics.WriteConnectionOpenError(
_operationId,
(SqlConnection)_context1,
_exception,
_operationName);
}
else
{
_diagnostics.WriteConnectionOpenAfter(_operationId, (SqlConnection)_context1, _operationName);
_diagnostics.WriteConnectionOpenAfter(
_operationId,
(SqlConnection)_context1,
_operationName);
}
break;

// ConnectionCloseOperation is not implemented because it is conditionally emitted and that requires manual calls to the write apis
// ConnectionCloseOperation is not implemented because it is conditionally
// emitted and that requires manual calls to the write apis
}
}

public void SetException(Exception ex)
{
_exception = ex;
}

public static DiagnosticScope CreateCommandScope(SqlDiagnosticListener diagnostics, SqlCommand command, SqlTransaction transaction, [CallerMemberName] string operationName = "")
{
Guid operationId = diagnostics.WriteCommandBefore(command, transaction, operationName);
return new DiagnosticScope(diagnostics, CommandOperation, operationId, operationName, command, transaction);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,31 @@

namespace Microsoft.Data.SqlClient.Diagnostics
{
internal ref struct DiagnosticTransactionScope //: IDisposable //ref structs cannot implement interfaces but the compiler will use pattern matching
internal ref struct DiagnosticTransactionScope //: IDisposable
{
public const int TransactionCommit = 1;
public const int TransactionRollback = 2;

private readonly SqlConnection _connection;
private readonly SqlDiagnosticListener _diagnostics;
private readonly int _operation;
private readonly Guid _operationId;
private readonly string _operationName;
private readonly IsolationLevel _isolationLevel;
private readonly SqlConnection _connection;
private readonly SqlInternalTransaction _transaction;
private readonly string _transactionName;

private Exception _exception;

public DiagnosticTransactionScope(SqlDiagnosticListener diagnostics, int operation, Guid operationId, string operationName, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, string transactionName)
public DiagnosticTransactionScope(
SqlDiagnosticListener diagnostics,
int operation,
Guid operationId,
string operationName,
IsolationLevel isolationLevel,
SqlConnection connection,
SqlInternalTransaction transaction,
string transactionName)
{
_diagnostics = diagnostics;
_operation = operation;
Expand All @@ -38,29 +47,105 @@ public DiagnosticTransactionScope(SqlDiagnosticListener diagnostics, int operati
_exception = null;
}

public static DiagnosticTransactionScope CreateTransactionCommitScope(
SqlDiagnosticListener diagnostics,
IsolationLevel isolationLevel,
SqlConnection connection,
SqlInternalTransaction transaction,
[CallerMemberName]
string operationName = "")
{
Guid operationId = diagnostics.WriteTransactionCommitBefore(
isolationLevel,
connection,
transaction,
operationName);
return new DiagnosticTransactionScope(
diagnostics,
TransactionCommit,
operationId,
operationName,
isolationLevel,
connection,
transaction,
transactionName: null);
}

public static DiagnosticTransactionScope CreateTransactionRollbackScope(
SqlDiagnosticListener diagnostics,
IsolationLevel isolationLevel,
SqlConnection connection,
SqlInternalTransaction transaction,
string transactionName,
[CallerMemberName]
string operationName = "")
{
Guid operationId = diagnostics.WriteTransactionRollbackBefore(
isolationLevel,
connection,
transaction,
transactionName,
operationName);
return new DiagnosticTransactionScope(
diagnostics,
TransactionCommit,
operationId,
operationName,
isolationLevel,
connection,
transaction,
transactionName);
}

// Although ref structs do not allow for inheriting from interfaces (< C#13), but the
// compiler will know to treat this like an IDisposable (> C# 8)
public void Dispose()
{
switch (_operation)
{
case TransactionCommit:
if (_exception != null)
{
_diagnostics.WriteTransactionCommitError(_operationId, _isolationLevel, _connection, _transaction, _exception, _operationName);
_diagnostics.WriteTransactionCommitError(
_operationId,
_isolationLevel,
_connection,
_transaction,
_exception,
_operationName);
}
else
{
_diagnostics.WriteTransactionCommitAfter(_operationId, _isolationLevel, _connection, _transaction, _operationName);
_diagnostics.WriteTransactionCommitAfter(
_operationId,
_isolationLevel,
_connection,
_transaction,
_operationName);
}
break;

case TransactionRollback:
if (_exception != null)
{
_diagnostics.WriteTransactionRollbackError(_operationId, _isolationLevel, _connection, _transaction, _exception, _transactionName, _operationName);
_diagnostics.WriteTransactionRollbackError(
_operationId,
_isolationLevel,
_connection,
_transaction,
_exception,
_transactionName,
_operationName);
}
else
{
_diagnostics.WriteTransactionRollbackAfter(_operationId, _isolationLevel, _connection, _transaction, _transactionName, _operationName);
_diagnostics.WriteTransactionRollbackAfter(
_operationId,
_isolationLevel,
_connection,
_transaction,
_transactionName,
_operationName);
}
break;
}
Expand All @@ -70,18 +155,6 @@ public void SetException(Exception ex)
{
_exception = ex;
}

public static DiagnosticTransactionScope CreateTransactionCommitScope(SqlDiagnosticListener diagnostics, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, [CallerMemberName] string operationName = "")
{
Guid operationId = diagnostics.WriteTransactionCommitBefore(isolationLevel, connection, transaction, operationName);
return new DiagnosticTransactionScope(diagnostics, TransactionCommit, operationId, operationName, isolationLevel, connection, transaction, null);
}

public static DiagnosticTransactionScope CreateTransactionRollbackScope(SqlDiagnosticListener diagnostics, IsolationLevel isolationLevel, SqlConnection connection, SqlInternalTransaction transaction, string transactionName, [CallerMemberName] string operationName = "")
{
Guid operationId = diagnostics.WriteTransactionRollbackBefore(isolationLevel, connection, transaction, transactionName, operationName);
return new DiagnosticTransactionScope(diagnostics, TransactionCommit, operationId, operationName, isolationLevel, connection, transaction, transactionName);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ public sealed class SqlClientCommandAfter : IReadOnlyList<KeyValuePair<string, o
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml' path='docs/members[@name="SqlClientCommandAfter"]/Name/*'/>
public const string Name = "Microsoft.Data.SqlClient.WriteCommandAfter";

internal SqlClientCommandAfter(Guid operationId, string operation, long timestamp, Guid? connectionId, long? transactionId, SqlCommand command, IDictionary statistics)
internal SqlClientCommandAfter(
Guid operationId,
string operation,
long timestamp,
Guid? connectionId,
long? transactionId,
SqlCommand command,
IDictionary statistics)
{
OperationId = operationId;
Operation = operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ public sealed class SqlClientCommandBefore : IReadOnlyList<KeyValuePair<string,
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml' path='docs/members[@name="SqlClientCommandBefore"]/SqlClientCommandBefore/*'/>
public const string Name = "Microsoft.Data.SqlClient.WriteCommandBefore";

internal SqlClientCommandBefore(Guid operationId, string operation, long timestamp, Guid? connectionId, long? transactionId, SqlCommand command)
internal SqlClientCommandBefore(
Guid operationId,
string operation,
long timestamp,
Guid? connectionId,
long? transactionId,
SqlCommand command)
{
OperationId = operationId;
Operation = operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ public sealed class SqlClientCommandError : IReadOnlyList<KeyValuePair<string, o

public const string Name = "Microsoft.Data.SqlClient.WriteCommandError";

internal SqlClientCommandError(Guid operationId, string operation, long timestamp, Guid? connectionId, long? transactionId, SqlCommand command, Exception exception)
internal SqlClientCommandError(
Guid operationId,
string operation,
long timestamp,
Guid? connectionId,
long? transactionId,
SqlCommand command,
Exception exception)
{
OperationId = operationId;
Operation = operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ public sealed class SqlClientConnectionCloseAfter : IReadOnlyList<KeyValuePair<s
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml' path='docs/members[@name="SqlClientConnectionCloseAfter"]/Name/*'/>
public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseAfter";

internal SqlClientConnectionCloseAfter(Guid operationId, string operation, long timestamp, Guid? connectionId, SqlConnection connection, IDictionary statistics)
internal SqlClientConnectionCloseAfter(
Guid operationId,
string operation,
long timestamp,
Guid? connectionId,
SqlConnection connection,
IDictionary statistics)
{
OperationId = operationId;
Operation = operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ public sealed class SqlClientConnectionCloseBefore : IReadOnlyList<KeyValuePair<
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml' path='docs/members[@name="SqlClientConnectionCloseBefore"]//*'/>
public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseBefore";

internal SqlClientConnectionCloseBefore(Guid operationId, string operation, long timestamp, Guid? connectionId, SqlConnection connection, IDictionary statistics)
internal SqlClientConnectionCloseBefore(
Guid operationId,
string operation,
long timestamp,
Guid? connectionId,
SqlConnection connection,
IDictionary statistics)
{
OperationId = operationId;
Operation = operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ public sealed class SqlClientConnectionCloseError : IReadOnlyList<KeyValuePair<s
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlClientDiagnostic.xml' path='docs/members[@name="SqlClientConnectionCloseError"]/Name/*'/>
public const string Name = "Microsoft.Data.SqlClient.WriteConnectionCloseError";

internal SqlClientConnectionCloseError(Guid operationId, string operation, long timestamp, Guid? connectionId, SqlConnection connection, IDictionary statistics, Exception ex)
internal SqlClientConnectionCloseError(
Guid operationId,
string operation,
long timestamp,
Guid? connectionId,
SqlConnection connection,
IDictionary statistics,
Exception ex)
{
OperationId = operationId;
Operation = operation;
Expand Down
Loading
Loading