2020using System . ComponentModel ;
2121using System . Data ;
2222using System . Data . Common ;
23+ using System . Diagnostics ;
2324using System . Text ;
2425using System . Threading ;
2526using System . Threading . Tasks ;
2627using FirebirdSql . Data . Common ;
2728using FirebirdSql . Data . Logging ;
29+ using FirebirdSql . Data . Trace ;
2830
2931namespace FirebirdSql . Data . FirebirdClient ;
3032
@@ -49,6 +51,7 @@ public sealed class FbCommand : DbCommand, IFbPreparedCommand, IDescriptorFiller
4951 private int ? _commandTimeout ;
5052 private int _fetchSize ;
5153 private Type [ ] _expectedColumnTypes ;
54+ private Activity _currentActivity ;
5255
5356 #endregion
5457
@@ -1094,6 +1097,13 @@ internal void Release()
10941097 _statement . Dispose2 ( ) ;
10951098 _statement = null ;
10961099 }
1100+
1101+ if ( _currentActivity != null )
1102+ {
1103+ // Do not set status to Ok: https://opentelemetry.io/docs/concepts/signals/traces/#span-status
1104+ _currentActivity . Dispose ( ) ;
1105+ _currentActivity = null ;
1106+ }
10971107 }
10981108 Task IFbPreparedCommand . ReleaseAsync ( CancellationToken cancellationToken ) => ReleaseAsync ( cancellationToken ) ;
10991109 internal async Task ReleaseAsync ( CancellationToken cancellationToken = default )
@@ -1112,6 +1122,13 @@ internal async Task ReleaseAsync(CancellationToken cancellationToken = default)
11121122 await _statement . Dispose2Async ( cancellationToken ) . ConfigureAwait ( false ) ;
11131123 _statement = null ;
11141124 }
1125+
1126+ if ( _currentActivity != null )
1127+ {
1128+ // Do not set status to Ok: https://opentelemetry.io/docs/concepts/signals/traces/#span-status
1129+ _currentActivity . Dispose ( ) ;
1130+ _currentActivity = null ;
1131+ }
11151132 }
11161133
11171134 void IFbPreparedCommand . TransactionCompleted ( ) => TransactionCompleted ( ) ;
@@ -1332,6 +1349,26 @@ private async ValueTask UpdateParameterValuesAsync(Descriptor descriptor, Cancel
13321349
13331350 #endregion
13341351
1352+ #region Tracing
1353+
1354+ private void TraceCommandStart ( )
1355+ {
1356+ Debug . Assert ( _currentActivity == null ) ;
1357+ if ( FbActivitySource . Source . HasListeners ( ) )
1358+ _currentActivity = FbActivitySource . CommandStart ( this ) ;
1359+ }
1360+
1361+ private void TraceCommandException ( Exception e )
1362+ {
1363+ if ( _currentActivity != null )
1364+ {
1365+ FbActivitySource . CommandException ( _currentActivity , e ) ;
1366+ _currentActivity = null ;
1367+ }
1368+ }
1369+
1370+ #endregion Tracing
1371+
13351372 #region Private Methods
13361373
13371374 private void Prepare ( bool returnsSet )
@@ -1476,57 +1513,73 @@ private async Task PrepareAsync(bool returnsSet, CancellationToken cancellationT
14761513 private void ExecuteCommand ( CommandBehavior behavior , bool returnsSet )
14771514 {
14781515 LogMessages . CommandExecution ( Log , this ) ;
1516+ TraceCommandStart ( ) ;
1517+ try
1518+ {
1519+ Prepare ( returnsSet ) ;
14791520
1480- Prepare ( returnsSet ) ;
1521+ if ( ( behavior & CommandBehavior . SequentialAccess ) == CommandBehavior . SequentialAccess ||
1522+ ( behavior & CommandBehavior . SingleResult ) == CommandBehavior . SingleResult ||
1523+ ( behavior & CommandBehavior . SingleRow ) == CommandBehavior . SingleRow ||
1524+ ( behavior & CommandBehavior . CloseConnection ) == CommandBehavior . CloseConnection ||
1525+ behavior == CommandBehavior . Default )
1526+ {
1527+ // Set the fetch size
1528+ _statement . FetchSize = _fetchSize ;
14811529
1482- if ( ( behavior & CommandBehavior . SequentialAccess ) == CommandBehavior . SequentialAccess ||
1483- ( behavior & CommandBehavior . SingleResult ) == CommandBehavior . SingleResult ||
1484- ( behavior & CommandBehavior . SingleRow ) == CommandBehavior . SingleRow ||
1485- ( behavior & CommandBehavior . CloseConnection ) == CommandBehavior . CloseConnection ||
1486- behavior == CommandBehavior . Default )
1487- {
1488- // Set the fetch size
1489- _statement . FetchSize = _fetchSize ;
1530+ // Set if it's needed the Records Affected information
1531+ _statement . ReturnRecordsAffected = _connection . ConnectionOptions . ReturnRecordsAffected ;
14901532
1491- // Set if it's needed the Records Affected information
1492- _statement . ReturnRecordsAffected = _connection . ConnectionOptions . ReturnRecordsAffected ;
1533+ // Validate input parameter count
1534+ if ( _namedParameters . Count > 0 && ! HasParameters )
1535+ {
1536+ throw FbException . Create ( "Must declare command parameters." ) ;
1537+ }
14931538
1494- // Validate input parameter count
1495- if ( _namedParameters . Count > 0 && ! HasParameters )
1496- {
1497- throw FbException . Create ( "Must declare command parameters." ) ;
1539+ // Execute
1540+ _statement . Execute ( CommandTimeout * 1000 , this ) ;
14981541 }
1499-
1500- // Execute
1501- _statement . Execute ( CommandTimeout * 1000 , this ) ;
1542+ }
1543+ catch ( Exception e )
1544+ {
1545+ TraceCommandException ( e ) ;
1546+ throw ;
15021547 }
15031548 }
15041549 private async Task ExecuteCommandAsync ( CommandBehavior behavior , bool returnsSet , CancellationToken cancellationToken = default )
15051550 {
15061551 LogMessages . CommandExecution ( Log , this ) ;
1552+ TraceCommandStart ( ) ;
1553+ try
1554+ {
1555+ await PrepareAsync ( returnsSet , cancellationToken ) . ConfigureAwait ( false ) ;
15071556
1508- await PrepareAsync ( returnsSet , cancellationToken ) . ConfigureAwait ( false ) ;
1557+ if ( ( behavior & CommandBehavior . SequentialAccess ) == CommandBehavior . SequentialAccess ||
1558+ ( behavior & CommandBehavior . SingleResult ) == CommandBehavior . SingleResult ||
1559+ ( behavior & CommandBehavior . SingleRow ) == CommandBehavior . SingleRow ||
1560+ ( behavior & CommandBehavior . CloseConnection ) == CommandBehavior . CloseConnection ||
1561+ behavior == CommandBehavior . Default )
1562+ {
1563+ // Set the fetch size
1564+ _statement . FetchSize = _fetchSize ;
15091565
1510- if ( ( behavior & CommandBehavior . SequentialAccess ) == CommandBehavior . SequentialAccess ||
1511- ( behavior & CommandBehavior . SingleResult ) == CommandBehavior . SingleResult ||
1512- ( behavior & CommandBehavior . SingleRow ) == CommandBehavior . SingleRow ||
1513- ( behavior & CommandBehavior . CloseConnection ) == CommandBehavior . CloseConnection ||
1514- behavior == CommandBehavior . Default )
1515- {
1516- // Set the fetch size
1517- _statement . FetchSize = _fetchSize ;
1566+ // Set if it's needed the Records Affected information
1567+ _statement . ReturnRecordsAffected = _connection . ConnectionOptions . ReturnRecordsAffected ;
15181568
1519- // Set if it's needed the Records Affected information
1520- _statement . ReturnRecordsAffected = _connection . ConnectionOptions . ReturnRecordsAffected ;
1569+ // Validate input parameter count
1570+ if ( _namedParameters . Count > 0 && ! HasParameters )
1571+ {
1572+ throw FbException . Create ( "Must declare command parameters." ) ;
1573+ }
15211574
1522- // Validate input parameter count
1523- if ( _namedParameters . Count > 0 && ! HasParameters )
1524- {
1525- throw FbException . Create ( "Must declare command parameters." ) ;
1575+ // Execute
1576+ await _statement . ExecuteAsync ( CommandTimeout * 1000 , this , cancellationToken ) . ConfigureAwait ( false ) ;
15261577 }
1527-
1528- // Execute
1529- await _statement . ExecuteAsync ( CommandTimeout * 1000 , this , cancellationToken ) . ConfigureAwait ( false ) ;
1578+ }
1579+ catch ( Exception e )
1580+ {
1581+ TraceCommandException ( e ) ;
1582+ throw ;
15301583 }
15311584 }
15321585
0 commit comments