diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index 71f068be23..6f56080aa0 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -56,8 +56,8 @@ Once the environment is setup properly, execute the desired set of commands belo ``` ```bash -> msbuild /t:BuildAllOSes -# Builds the driver for all Operating Systems. +> msbuild /t:BuildNetCoreAllOS +# Builds the .NET Core driver for all Operating Systems. ``` ## Building Tests diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs index 2566f441f0..e3b91c6ee5 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs @@ -304,7 +304,13 @@ private static extern unsafe uint SNISecGenClientContextWrapper( [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] private static extern uint SNIWriteSyncOverAsync(SNIHandle pConn, [In] SNIPacket pPacket); - #endregion + + [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] + internal static extern bool RegisterTraceProviderWrapper(int eventKeyword); + + [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] + internal static extern void UnregisterTraceProviderWrapper(); + #endregion internal static uint SniGetConnectionId(SNIHandle pConn, ref Guid connId) { @@ -461,6 +467,18 @@ private static void MarshalConsumerInfo(ConsumerInfo consumerInfo, ref Sni_Consu : IntPtr.Zero; native_consumerInfo.ConsumerKey = consumerInfo.key; } + + internal static bool RegisterTraceProvider(int eventKeyword) + { + // Registers the TraceLogging provider, enabling it to generate events. + // Return true if enabled, otherwise false. + return RegisterTraceProviderWrapper(eventKeyword); + } + + internal static void UnregisterTraceProvider() + { + UnregisterTraceProviderWrapper(); + } } } 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 29a0f61505..40003150cf 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -29,6 +29,11 @@ true + + + Microsoft\Data\SqlClient\SqlClientEventSource.Windows.cs + + Microsoft\Data\SqlClient\SqlClientEventSource.cs 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 f3b68d3da1..9764fe9e38 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -90,6 +90,9 @@ Microsoft\Data\SqlClient\SqlClientEventSource.cs + + Microsoft\Data\SqlClient\SqlClientEventSource.Windows.cs + Microsoft\Data\SqlClient\SqlClientLogger.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs index 0cddc32dc1..3b2549e5de 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs @@ -133,5 +133,11 @@ internal static extern unsafe uint SNISecGenClientContextWrapper( [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr SNIClientCertificateFallbackWrapper(IntPtr pCallbackContext); + + [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] + internal static extern bool RegisterTraceProviderWrapper(int eventKeyword); + + [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] + internal static extern void UnregisterTraceProviderWrapper(); } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs index 398ecc4872..fc1e90750c 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs @@ -133,5 +133,11 @@ internal static extern unsafe uint SNISecGenClientContextWrapper( [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr SNIClientCertificateFallbackWrapper(IntPtr pCallbackContext); + + [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] + internal static extern bool RegisterTraceProviderWrapper(int eventKeyword); + + [DllImport(SNI, CallingConvention = CallingConvention.Cdecl)] + internal static extern void UnregisterTraceProviderWrapper(); } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs index 66efa587b6..a79e0e71e5 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs @@ -51,7 +51,7 @@ internal static class SNINativeMethodWrapper internal const int LocalDBInvalidSqlUserInstanceDllPath = 55; internal const int LocalDBFailedToLoadDll = 56; internal const int LocalDBBadRuntime = 57; - internal const int SniIP6AddrStringBufferLength = 48; // from SNI layer + internal const int SniIP6AddrStringBufferLength = 48; // from SNI layer internal static int SniMaxComposedSpnLength { @@ -725,12 +725,12 @@ internal static uint SniGetConnectionId(SNIHandle pConn, ref Guid connId) { return SNIGetInfoWrapper(pConn, QTypes.SNI_QUERY_CONN_CONNID, out connId); } - + internal static uint SniGetProviderNumber(SNIHandle pConn, ref ProviderEnum provNum) { return SNIGetInfoWrapper(pConn, QTypes.SNI_QUERY_CONN_PROVIDERNUM, out provNum); } - + internal static uint SniGetConnectionPort(SNIHandle pConn, ref ushort portNum) { return SNIGetInfoWrapper(pConn, QTypes.SNI_QUERY_CONN_PEERPORT, out portNum); @@ -812,7 +812,7 @@ internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string cons clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv4 = cachedDNSInfo?.AddrIPv4; clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv6 = cachedDNSInfo?.AddrIPv6; clientConsumerInfo.DNSCacheInfo.wszCachedTcpPort = cachedDNSInfo?.Port; - + if (spnBuffer != null) { fixed (byte* pin_spnBuffer = &spnBuffer[0]) @@ -1075,6 +1075,32 @@ private static void MarshalConsumerInfo(ConsumerInfo consumerInfo, ref Sni_Consu : IntPtr.Zero; native_consumerInfo.ConsumerKey = consumerInfo.key; } + + internal static bool RegisterTraceProvider(int eventKeyword) + { + // Registers the TraceLogging provider, enabling it to generate events. + // Return true if enabled, otherwise false. + if (s_is64bitProcess) + { + return SNINativeManagedWrapperX64.RegisterTraceProviderWrapper(eventKeyword); + } + else + { + return SNINativeManagedWrapperX86.RegisterTraceProviderWrapper(eventKeyword); + } + } + + internal static void UnregisterTraceProvider() + { + if (s_is64bitProcess) + { + SNINativeManagedWrapperX64.UnregisterTraceProviderWrapper(); + } + else + { + SNINativeManagedWrapperX86.UnregisterTraceProviderWrapper(); + } + } } } 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 new file mode 100644 index 0000000000..f9af6024e4 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.Windows.cs @@ -0,0 +1,60 @@ +// 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; +using System.Diagnostics.Tracing; + +namespace Microsoft.Data.SqlClient +{ + internal partial class SqlClientEventSource : EventSource + { + private bool _traceLoggingProviderEnabled = false; + + /// + /// Captures application flow traces from native networking implementation + /// + private const EventCommand SNINativeTrace = (EventCommand)8192; + + /// + /// Captures scope trace events from native networking implementation + /// + private const EventCommand SNINativeScope = (EventCommand)16384; + + /// + /// Disables all event tracing in native networking implementation + /// + private const EventCommand SNINativeDisable = (EventCommand)32768; + + protected override void OnEventCommand(EventCommandEventArgs 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. + // If registration fails, all write and unregister commands will be a no-op. + + // If managed networking is enabled, don't call native wrapper methods +#if netcoreapp + if (AppContext.TryGetSwitch("Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows", out bool isEnabled) && isEnabled) + { + return; + } +#endif + // Only register the provider if it's not already registered. Registering a provider that is already + // registered can lead to unpredictable behaviour. + if (!_traceLoggingProviderEnabled && e.Command > 0 && (e.Command & (SNINativeTrace | SNINativeScope)) != 0) + { + int eventKeyword = (int)(e.Command & (SNINativeTrace | SNINativeScope)); + _traceLoggingProviderEnabled = SNINativeMethodWrapper.RegisterTraceProvider(eventKeyword); + Debug.Assert(_traceLoggingProviderEnabled, "Failed to enable TraceLogging provider."); + } + else if (_traceLoggingProviderEnabled && (e.Command == SNINativeDisable)) + { + // Only unregister the provider if it's currently registered. + SNINativeMethodWrapper.UnregisterTraceProvider(); + _traceLoggingProviderEnabled = false; + } + } + } +} 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 93e544a713..f9000f5d9f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs @@ -8,7 +8,7 @@ namespace Microsoft.Data.SqlClient { [EventSource(Name = "Microsoft.Data.SqlClient.EventSource")] - internal class SqlClientEventSource : EventSource + internal partial class SqlClientEventSource : EventSource { // Defines the singleton instance for the Resources ETW provider internal static readonly SqlClientEventSource Log = new SqlClientEventSource();