diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index 58772da574..8e5d668070 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -28,9 +28,6 @@
$(DefineConstants);NETCORE3
-
- $(DefineConstants);NETSTANDARD21
-
portable
true
@@ -45,7 +42,6 @@
Microsoft\Data\SqlClient\SqlClientEventSource.cs
-
Microsoft\Data\SqlClient\SqlClientLogger.cs
@@ -251,6 +247,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp2.cs
similarity index 65%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp.cs
rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp2.cs
index f15f691a42..da7a59b51b 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp2.cs
@@ -7,7 +7,10 @@
namespace Microsoft.Data.SqlClient
{
- internal partial class SqlClientEventSource : EventSource
+ ///
+ /// supported frameworks: .Net core 2.1 and .Net standard 2.0
+ ///
+ internal partial class SqlClientEventSource : SqlClientEventSourceBase
{
private EventCounter _activeHardConnections;
private EventCounter _hardConnectsPerSecond;
@@ -53,151 +56,31 @@ internal partial class SqlClientEventSource : EventSource
private long _stasisConnectionsCounter = 0;
private long _reclaimedConnectionsCounter = 0;
- public SqlClientEventSource()
+ protected override void EventCommandMethodCall(EventCommandEventArgs command)
{
- _activeHardConnections = _activeHardConnections ??
- new EventCounter("active-hard-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Actual active connections are made to servers",
- DisplayUnits = "count"
-#endif
- };
-
- _hardConnectsPerSecond = _hardConnectsPerSecond ??
- new EventCounter("hard-connects", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Actual connections are made to servers",
- DisplayUnits = "count / sec"
-#endif
- };
-
- _hardDisconnectsPerSecond = _hardDisconnectsPerSecond ??
- new EventCounter("hard-disconnects", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Actual disconnections are made to servers",
- DisplayUnits = "count / sec"
-#endif
- };
-
- _activeSoftConnections = _activeSoftConnections ??
- new EventCounter("active-soft-connects", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Active connections got from connection pool",
- DisplayUnits = "count"
-#endif
- };
-
- _softConnects = _softConnects ??
- new EventCounter("soft-connects", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Connections got from connection pool",
- DisplayUnits = "count / sec"
-#endif
- };
-
- _softDisconnects = _softDisconnects ??
- new EventCounter("soft-disconnects", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Connections returned to the connection pool",
- DisplayUnits = "count / sec"
-#endif
- };
-
- _numberOfNonPooledConnections = _numberOfNonPooledConnections ??
- new EventCounter("number-of-non-pooled-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of connections are not using connection pooling",
- DisplayUnits = "count / sec"
-#endif
- };
-
- _numberOfPooledConnections = _numberOfPooledConnections ??
- new EventCounter("number-of-pooled-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of connections are managed by connection pooler",
- DisplayUnits = "count / sec"
-#endif
- };
-
- _numberOfActiveConnectionPoolGroups = _numberOfActiveConnectionPoolGroups ??
- new EventCounter("number-of-active-connection-pool-groups", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of active unique connection strings",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfInactiveConnectionPoolGroups = _numberOfInactiveConnectionPoolGroups ??
- new EventCounter("number-of-inactive-connection-pool-groups", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of unique connection strings waiting for pruning",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfActiveConnectionPools = _numberOfActiveConnectionPools ??
- new EventCounter("number-of-active-connection-pools", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of active connection pools",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfInactiveConnectionPools = _numberOfInactiveConnectionPools ??
- new EventCounter("number-of-inactive-connection-pools", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of inactive connection pools",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfActiveConnections = _numberOfActiveConnections ??
- new EventCounter("number-of-active-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of active connections",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfFreeConnections = _numberOfFreeConnections ??
- new EventCounter("number-of-free-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of free-ready connections",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfStasisConnections = _numberOfStasisConnections ??
- new EventCounter("number-of-stasis-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of connections currently waiting to be ready",
- DisplayUnits = "count"
-#endif
- };
-
- _numberOfReclaimedConnections = _numberOfReclaimedConnections ??
- new EventCounter("number-of-reclaimed-connections", this)
- {
-#if NETCORE3 || NETSTANDARD21
- DisplayName = "Number of reclaimed connections from GC",
- DisplayUnits = "count"
-#endif
- };
+ if (command.Command != EventCommand.Enable)
+ {
+ return;
+ }
+
+ _activeHardConnections = _activeHardConnections ?? new EventCounter("active-hard-connections", this);
+ _hardConnectsPerSecond = _hardConnectsPerSecond ?? new EventCounter("hard-connects", this);
+ _hardDisconnectsPerSecond = _hardDisconnectsPerSecond ?? new EventCounter("hard-disconnects", this);
+
+ _activeSoftConnections = _activeSoftConnections ?? new EventCounter("active-soft-connects", this);
+ _softConnects = _softConnects ?? new EventCounter("soft-connects", this);
+ _softDisconnects = _softDisconnects ?? new EventCounter("soft-disconnects", this);
+
+ _numberOfNonPooledConnections = _numberOfNonPooledConnections ?? new EventCounter("number-of-non-pooled-connections", this);
+ _numberOfPooledConnections = _numberOfPooledConnections ?? new EventCounter("number-of-pooled-connections", this);
+ _numberOfActiveConnectionPoolGroups = _numberOfActiveConnectionPoolGroups ?? new EventCounter("number-of-active-connection-pool-groups", this);
+ _numberOfInactiveConnectionPoolGroups = _numberOfInactiveConnectionPoolGroups ?? new EventCounter("number-of-inactive-connection-pool-groups", this);
+ _numberOfActiveConnectionPools = _numberOfActiveConnectionPools ?? new EventCounter("number-of-active-connection-pools", this);
+ _numberOfInactiveConnectionPools = _numberOfInactiveConnectionPools ?? new EventCounter("number-of-inactive-connection-pools", this);
+ _numberOfActiveConnections = _numberOfActiveConnections ?? new EventCounter("number-of-active-connections", this);
+ _numberOfFreeConnections = _numberOfFreeConnections ?? new EventCounter("number-of-free-connections", this);
+ _numberOfStasisConnections = _numberOfStasisConnections ?? new EventCounter("number-of-stasis-connections", this);
+ _numberOfReclaimedConnections = _numberOfReclaimedConnections ?? new EventCounter("number-of-reclaimed-connections", this);
}
///
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp3.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp3.cs
new file mode 100644
index 0000000000..6d27a88cbe
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlClientEventSource.NetCoreApp3.cs
@@ -0,0 +1,352 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Tracing;
+using System.Threading;
+
+namespace Microsoft.Data.SqlClient
+{
+ ///
+ /// supported frameworks: .Net core 3.1 and .Net standard 2.1 and above
+ ///
+ internal partial class SqlClientEventSource : SqlClientEventSourceBase
+ {
+ private PollingCounter _activeHardConnections;
+ private IncrementingPollingCounter _hardConnectsPerSecond;
+ private IncrementingPollingCounter _hardDisconnectsPerSecond;
+
+ private PollingCounter _activeSoftConnections;
+ private IncrementingPollingCounter _softConnects;
+ private IncrementingPollingCounter _softDisconnects;
+
+ private PollingCounter _numberOfNonPooledConnections;
+ private PollingCounter _numberOfPooledConnections;
+
+ private PollingCounter _numberOfActiveConnectionPoolGroups;
+ private PollingCounter _numberOfInactiveConnectionPoolGroups;
+
+ private PollingCounter _numberOfActiveConnectionPools;
+ private PollingCounter _numberOfInactiveConnectionPools;
+
+ private PollingCounter _numberOfActiveConnections;
+ private PollingCounter _numberOfFreeConnections;
+ private PollingCounter _numberOfStasisConnections;
+ private IncrementingPollingCounter _numberOfReclaimedConnections;
+
+ private long _activeHardConnectionsCounter = 0;
+ private long _hardConnectsCounter = 0;
+ private long _hardDisconnectsCounter = 0;
+
+ private long _activeSoftConnectionsCounter = 0;
+ private long _softConnectsCounter = 0;
+ private long _softDisconnectsCounter = 0;
+
+ private long _nonPooledConnectionsCounter = 0;
+ private long _pooledConnectionsCounter = 0;
+
+ private long _activeConnectionPoolGroupsCounter = 0;
+ private long _inactiveConnectionPoolGroupsCounter = 0;
+
+ private long _activeConnectionPoolsCounter = 0;
+ private long _inactiveConnectionPoolsCounter = 0;
+
+ private long _activeConnectionsCounter = 0;
+ private long _freeConnectionsCounter = 0;
+ private long _stasisConnectionsCounter = 0;
+ private long _reclaimedConnectionsCounter = 0;
+
+ protected override void EventCommandMethodCall(EventCommandEventArgs command)
+ {
+ if(command.Command != EventCommand.Enable)
+ {
+ return;
+ }
+
+ _activeHardConnections = _activeHardConnections ??
+ new PollingCounter("active-hard-connections", this, () => _activeHardConnectionsCounter)
+ {
+ DisplayName = "Actual active connections are made to servers",
+ DisplayUnits = "count"
+ };
+
+ _hardConnectsPerSecond = _hardConnectsPerSecond ??
+ new IncrementingPollingCounter("hard-connects", this, () => _hardConnectsCounter)
+ {
+ DisplayName = "Actual connections are made to servers",
+ DisplayUnits = "count / sec",
+ DisplayRateTimeScale = TimeSpan.FromSeconds(1)
+ };
+
+ _hardDisconnectsPerSecond = _hardDisconnectsPerSecond ??
+ new IncrementingPollingCounter("hard-disconnects", this, () => _hardDisconnectsCounter)
+ {
+ DisplayName = "Actual disconnections are made to servers",
+ DisplayUnits = "count / sec",
+ DisplayRateTimeScale = TimeSpan.FromSeconds(1)
+ };
+
+ _activeSoftConnections = _activeSoftConnections ??
+ new PollingCounter("active-soft-connects", this, () => _activeSoftConnectionsCounter)
+ {
+ DisplayName = "Active connections got from connection pool",
+ DisplayUnits = "count"
+ };
+
+ _softConnects = _softConnects ??
+ new IncrementingPollingCounter("soft-connects", this, () => _softConnectsCounter)
+ {
+ DisplayName = "Connections got from connection pool",
+ DisplayUnits = "count / sec",
+ DisplayRateTimeScale = TimeSpan.FromSeconds(1)
+ };
+
+ _softDisconnects = _softDisconnects ??
+ new IncrementingPollingCounter("soft-disconnects", this, () => _softDisconnectsCounter)
+ {
+ DisplayName = "Connections returned to the connection pool",
+ DisplayUnits = "count / sec",
+ DisplayRateTimeScale = TimeSpan.FromSeconds(1)
+ };
+
+ _numberOfNonPooledConnections = _numberOfNonPooledConnections ??
+ new PollingCounter("number-of-non-pooled-connections", this, () => _nonPooledConnectionsCounter)
+ {
+ DisplayName = "Number of connections are not using connection pooling",
+ DisplayUnits = "count / sec"
+ };
+
+ _numberOfPooledConnections = _numberOfPooledConnections ??
+ new PollingCounter("number-of-pooled-connections", this, () => _pooledConnectionsCounter)
+ {
+ DisplayName = "Number of connections are managed by connection pooler",
+ DisplayUnits = "count / sec"
+ };
+
+ _numberOfActiveConnectionPoolGroups = _numberOfActiveConnectionPoolGroups ??
+ new PollingCounter("number-of-active-connection-pool-groups", this, () => _activeConnectionPoolsCounter)
+ {
+ DisplayName = "Number of active unique connection strings",
+ DisplayUnits = "count"
+ };
+
+ _numberOfInactiveConnectionPoolGroups = _numberOfInactiveConnectionPoolGroups ??
+ new PollingCounter("number-of-inactive-connection-pool-groups", this, () => _inactiveConnectionPoolGroupsCounter)
+ {
+ DisplayName = "Number of unique connection strings waiting for pruning",
+ DisplayUnits = "count"
+ };
+
+ _numberOfActiveConnectionPools = _numberOfActiveConnectionPools ??
+ new PollingCounter("number-of-active-connection-pools", this, () => _activeConnectionPoolsCounter)
+ {
+ DisplayName = "Number of active connection pools",
+ DisplayUnits = "count"
+ };
+
+ _numberOfInactiveConnectionPools = _numberOfInactiveConnectionPools ??
+ new PollingCounter("number-of-inactive-connection-pools", this, () => _inactiveConnectionPoolsCounter)
+ {
+ DisplayName = "Number of inactive connection pools",
+ DisplayUnits = "count"
+ };
+
+ _numberOfActiveConnections = _numberOfActiveConnections ??
+ new PollingCounter("number-of-active-connections", this, () => _activeConnectionsCounter)
+ {
+ DisplayName = "Number of active connections",
+ DisplayUnits = "count"
+ };
+
+ _numberOfFreeConnections = _numberOfFreeConnections ??
+ new PollingCounter("number-of-free-connections", this, () => _freeConnectionsCounter)
+ {
+ DisplayName = "Number of free-ready connections",
+ DisplayUnits = "count"
+ };
+
+ _numberOfStasisConnections = _numberOfStasisConnections ??
+ new PollingCounter("number-of-stasis-connections", this, () => _stasisConnectionsCounter)
+ {
+ DisplayName = "Number of connections currently waiting to be ready",
+ DisplayUnits = "count"
+ };
+
+ _numberOfReclaimedConnections = _numberOfReclaimedConnections ??
+ new IncrementingPollingCounter("number-of-reclaimed-connections", this, () => _reclaimedConnectionsCounter)
+ {
+ DisplayName = "Number of reclaimed connections from GC",
+ DisplayUnits = "count",
+ DisplayRateTimeScale = TimeSpan.FromSeconds(1)
+ };
+ }
+
+ ///
+ /// The number of actual connections that are being made to servers
+ ///
+ [NonEvent]
+ internal void HardConnectRequest()
+ {
+ if (IsEnabled())
+ {
+ Interlocked.Increment(ref _activeHardConnectionsCounter);
+ Interlocked.Increment(ref _hardConnectsCounter);
+ }
+ }
+
+ ///
+ /// The number of actual disconnects that are being made to servers
+ ///
+ [NonEvent]
+ internal void HardDisconnectRequest()
+ {
+ if (IsEnabled())
+ {
+ Interlocked.Decrement(ref _activeHardConnectionsCounter);
+ Interlocked.Increment(ref _hardDisconnectsCounter);
+ }
+ }
+
+ ///
+ /// The number of connections we get from the pool
+ ///
+ [NonEvent]
+ internal void SoftConnectRequest()
+ {
+ if (IsEnabled())
+ {
+ Interlocked.Increment(ref _activeSoftConnectionsCounter);
+ Interlocked.Increment(ref _softConnectsCounter);
+ }
+ }
+
+ ///
+ /// The number of connections we return to the pool
+ ///
+ [NonEvent]
+ internal void SoftDisconnectRequest()
+ {
+ if (IsEnabled())
+ {
+ Interlocked.Decrement(ref _activeSoftConnectionsCounter);
+ Interlocked.Increment(ref _softDisconnectsCounter);
+ }
+ }
+
+ ///
+ /// The number of connections that are not using connection pooling
+ ///
+ ///
+ [NonEvent]
+ internal void NonPooledConnectionRequest(bool increment = true)
+ {
+ Request(ref _nonPooledConnectionsCounter, increment);
+ }
+
+ ///
+ /// The number of connections that are managed by the connection pooler
+ ///
+ ///
+ [NonEvent]
+ internal void PooledConnectionRequest(bool increment = true)
+ {
+ Request(ref _pooledConnectionsCounter, increment);
+ }
+
+ ///
+ /// The number of unique connection strings
+ ///
+ ///
+ [NonEvent]
+ internal void ActiveConnectionPoolGroupRequest(bool increment = true)
+ {
+ Request(ref _activeConnectionPoolGroupsCounter, increment);
+ }
+
+ ///
+ /// The number of unique connection strings waiting for pruning
+ ///
+ ///
+ [NonEvent]
+ internal void InactiveConnectionPoolGroupRequest(bool increment = true)
+ {
+ Request(ref _inactiveConnectionPoolGroupsCounter, increment);
+ }
+
+ ///
+ /// The number of connection pools
+ ///
+ ///
+ [NonEvent]
+ internal void ActiveConnectionPoolRequest(bool increment = true)
+ {
+ Request(ref _activeConnectionPoolsCounter, increment);
+ }
+
+ ///
+ /// The number of connection pools
+ ///
+ ///
+ [NonEvent]
+ internal void InactiveConnectionPoolRequest(bool increment = true)
+ {
+ Request(ref _inactiveConnectionPoolsCounter, increment);
+ }
+
+ ///
+ /// The number of connections currently in-use
+ ///
+ ///
+ [NonEvent]
+ internal void ActiveConnectionRequest(bool increment = true)
+ {
+ Request(ref _activeConnectionsCounter, increment);
+ }
+
+ ///
+ /// The number of connections currently available for use
+ ///
+ ///
+ [NonEvent]
+ internal void FreeConnectionRequest(bool increment = true)
+ {
+ Request(ref _freeConnectionsCounter, increment);
+ }
+
+ ///
+ /// The number of connections currently waiting to be made ready for use
+ ///
+ ///
+ [NonEvent]
+ internal void StasisConnectionRequest(bool increment = true)
+ {
+ Request(ref _stasisConnectionsCounter, increment);
+ }
+
+ ///
+ /// The number of connections we reclaim from GC'd external connections
+ ///
+ [NonEvent]
+ internal void ReclaimedConnectionRequest()
+ {
+ Request(ref _reclaimedConnectionsCounter, true);
+ }
+
+ [NonEvent]
+ private void Request(ref long counter, bool increment)
+ {
+ if (IsEnabled())
+ {
+ if (increment)
+ {
+ Interlocked.Increment(ref counter);
+ }
+ else
+ {
+ Interlocked.Decrement(ref counter);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 927ddf3c95..a63ed87bce 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -318,16 +318,10 @@
-
- Component
-
-
- Component
-
+
+
-
- Component
-
+
@@ -335,9 +329,7 @@
-
- Component
-
+
@@ -407,9 +399,7 @@
-
- Component
-
+
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.Windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.Windows.cs
index f9af6024e4..cc5db8c738 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.Windows.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.Windows.cs
@@ -8,7 +8,7 @@
namespace Microsoft.Data.SqlClient
{
- internal partial class SqlClientEventSource : EventSource
+ internal partial class SqlClientEventSource : SqlClientEventSourceBase
{
private bool _traceLoggingProviderEnabled = false;
@@ -29,6 +29,7 @@ internal partial class SqlClientEventSource : EventSource
protected override void OnEventCommand(EventCommandEventArgs e)
{
+ base.OnEventCommand(e);
// Internally, EventListener.EnableEvents sends an event command, with a reserved value of 0, -2, or -3.
// When a command is sent via EnableEvents or SendCommand, check if it is a user-defined value
// to enable or disable event tracing in sni.dll.
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs
index a2d49e96c8..2febb4b5d9 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs
@@ -7,8 +7,19 @@
namespace Microsoft.Data.SqlClient
{
+ internal abstract class SqlClientEventSourceBase : EventSource
+ {
+ protected override void OnEventCommand(EventCommandEventArgs command)
+ {
+ base.OnEventCommand(command);
+ EventCommandMethodCall(command);
+ }
+
+ protected virtual void EventCommandMethodCall(EventCommandEventArgs command){}
+ }
+
[EventSource(Name = "Microsoft.Data.SqlClient.EventSource")]
- internal partial class SqlClientEventSource : EventSource
+ internal partial class SqlClientEventSource : SqlClientEventSourceBase
{
// Defines the singleton instance for the Resources ETW provider
internal static readonly SqlClientEventSource Log = new SqlClientEventSource();
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
index e65d4e6693..e089868555 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs
@@ -15,6 +15,7 @@
using Microsoft.Identity.Client;
using Microsoft.Data.SqlClient.TestUtilities;
using Xunit;
+using System.Linq;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests
{
@@ -688,20 +689,62 @@ public static string RetrieveValueFromConnStr(string connStr, string[] keywords)
public class TraceEventListener : EventListener
{
+ private const string Name = "Name";
+
public List IDs = new List();
+
+ public Dictionary EventCounters { get; private set; }
+
+ public TraceEventListener()
+ {
+ EventCounters = new Dictionary
+ {
+ { "active-hard-connections", 0 },
+ { "hard-connects", 0 },
+ { "hard-disconnects", 0 },
+ { "active-soft-connects", 0 },
+ { "soft-connects", 0 },
+ { "soft-disconnects", 0 },
+ { "number-of-non-pooled-connections", 0 },
+ { "number-of-pooled-connections", 0 },
+ { "number-of-active-connection-pool-groups", 0 },
+ { "number-of-inactive-connection-pool-groups", 0 },
+ { "number-of-active-connection-pools", 0 },
+ { "number-of-inactive-connection-pools", 0 },
+ { "number-of-active-connections", 0 },
+ { "number-of-free-connections", 0 },
+ { "number-of-stasis-connections", 0 },
+ { "number-of-reclaimed-connections", 0 }
+ };
+ }
protected override void OnEventSourceCreated(EventSource eventSource)
{
if (eventSource.Name.Equals("Microsoft.Data.SqlClient.EventSource"))
{
+#if netcoreapp
+ var options = new Dictionary();
+ options.Add("EventCounterIntervalSec", "1");
// Collect all traces for better code coverage
+ EnableEvents(eventSource, EventLevel.Informational, EventKeywords.All, options);
+#else
EnableEvents(eventSource, EventLevel.Informational, EventKeywords.All);
+#endif
}
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
- IDs.Add(eventData.EventId);
+#if netcoreapp
+ object counter = null;
+ eventData.Payload.FirstOrDefault(p => p is IDictionary x && x.TryGetValue(Name, out counter));
+ if (counter is string cntName && EventCounters.ContainsKey(cntName))
+ {
+ EventCounters[cntName] += 1;
+ }
+ else
+#endif
+ IDs.Add(eventData.EventId);
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/EventSourceTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/EventSourceTest.cs
index a6a1d2287c..08ae370fe9 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/EventSourceTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/EventSourceTest.cs
@@ -2,7 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Collections.Generic;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
using Xunit;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests
@@ -33,5 +36,39 @@ public void EventSourceTestAll()
Assert.All(TraceListener.IDs, item => { Assert.Contains(item, Enumerable.Range(1, 21)); });
}
}
+
+ [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
+ public void EventCounterTestAll()
+ {
+ var stringBuilder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString)
+ {
+ Pooling = true,
+ MaxPoolSize = 20
+ };
+
+ using (var TraceListener = new DataTestUtility.TraceEventListener())
+ {
+ OpenConnections(stringBuilder.ConnectionString);
+ stringBuilder.Pooling = false;
+ OpenConnections(stringBuilder.ConnectionString);
+
+ Thread.Sleep(3000); //wait to complete sampling!
+ Assert.All(TraceListener.EventCounters, item => Assert.True(item.Value > 0));
+ }
+ }
+
+ private void OpenConnections(string cnnString)
+ {
+ List tasks = new List();
+
+ Enumerable.Range(1, 100).ToList().ForEach(i =>
+ {
+ SqlConnection cnn = new SqlConnection(cnnString);
+ cnn.Open();
+ int x = i;
+ tasks.Add(Task.Run(() => { Thread.Sleep(x); cnn.Close(); }));
+ });
+ Task.WhenAll(tasks).Wait();
+ }
}
}