Skip to content

Commit 1fd8fd4

Browse files
johnnyphamTrayanZapryanov
authored andcommitted
Enable event tracing in SNI.dll (dotnet#650)
1 parent 30ebb76 commit 1fd8fd4

File tree

9 files changed

+132
-8
lines changed

9 files changed

+132
-8
lines changed

BUILDGUIDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ Once the environment is setup properly, execute the desired set of commands belo
5656
```
5757

5858
```bash
59-
> msbuild /t:BuildAllOSes
60-
# Builds the driver for all Operating Systems.
59+
> msbuild /t:BuildNetCoreAllOS
60+
# Builds the .NET Core driver for all Operating Systems.
6161
```
6262

6363
## Building Tests

src/Microsoft.Data.SqlClient/netcore/src/Interop/SNINativeMethodWrapper.Windows.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,13 @@ private static extern unsafe uint SNISecGenClientContextWrapper(
304304

305305
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
306306
private static extern uint SNIWriteSyncOverAsync(SNIHandle pConn, [In] SNIPacket pPacket);
307-
#endregion
307+
308+
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
309+
internal static extern bool RegisterTraceProviderWrapper(int eventKeyword);
310+
311+
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
312+
internal static extern void UnregisterTraceProviderWrapper();
313+
#endregion
308314

309315
internal static uint SniGetConnectionId(SNIHandle pConn, ref Guid connId)
310316
{
@@ -461,6 +467,18 @@ private static void MarshalConsumerInfo(ConsumerInfo consumerInfo, ref Sni_Consu
461467
: IntPtr.Zero;
462468
native_consumerInfo.ConsumerKey = consumerInfo.key;
463469
}
470+
471+
internal static bool RegisterTraceProvider(int eventKeyword)
472+
{
473+
// Registers the TraceLogging provider, enabling it to generate events.
474+
// Return true if enabled, otherwise false.
475+
return RegisterTraceProviderWrapper(eventKeyword);
476+
}
477+
478+
internal static void UnregisterTraceProvider()
479+
{
480+
UnregisterTraceProviderWrapper();
481+
}
464482
}
465483
}
466484

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
<DebugSymbols>true</DebugSymbols>
3434
</PropertyGroup>
3535
<!-- Contains common items shared between NetFx and NetCore -->
36+
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetsWindows)' == 'true'">
37+
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlClientEventSource.Windows.cs">
38+
<Link>Microsoft\Data\SqlClient\SqlClientEventSource.Windows.cs</Link>
39+
</Compile>
40+
</ItemGroup>
3641
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS'">
3742
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlClientEventSource.cs">
3843
<Link>Microsoft\Data\SqlClient\SqlClientEventSource.cs</Link>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@
9191
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlClientEventSource.cs">
9292
<Link>Microsoft\Data\SqlClient\SqlClientEventSource.cs</Link>
9393
</Compile>
94+
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlClientEventSource.Windows.cs">
95+
<Link>Microsoft\Data\SqlClient\SqlClientEventSource.Windows.cs</Link>
96+
</Compile>
9497
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlClientLogger.cs">
9598
<Link>Microsoft\Data\SqlClient\SqlClientLogger.cs</Link>
9699
</Compile>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX64.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,11 @@ internal static extern unsafe uint SNISecGenClientContextWrapper(
133133

134134
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
135135
internal static extern IntPtr SNIClientCertificateFallbackWrapper(IntPtr pCallbackContext);
136+
137+
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
138+
internal static extern bool RegisterTraceProviderWrapper(int eventKeyword);
139+
140+
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
141+
internal static extern void UnregisterTraceProviderWrapper();
136142
}
137143
}

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeManagedWrapperX86.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,11 @@ internal static extern unsafe uint SNISecGenClientContextWrapper(
133133

134134
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
135135
internal static extern IntPtr SNIClientCertificateFallbackWrapper(IntPtr pCallbackContext);
136+
137+
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
138+
internal static extern bool RegisterTraceProviderWrapper(int eventKeyword);
139+
140+
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
141+
internal static extern void UnregisterTraceProviderWrapper();
136142
}
137143
}

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Interop/SNINativeMethodWrapper.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ internal static class SNINativeMethodWrapper
5151
internal const int LocalDBInvalidSqlUserInstanceDllPath = 55;
5252
internal const int LocalDBFailedToLoadDll = 56;
5353
internal const int LocalDBBadRuntime = 57;
54-
internal const int SniIP6AddrStringBufferLength = 48; // from SNI layer
54+
internal const int SniIP6AddrStringBufferLength = 48; // from SNI layer
5555

5656
internal static int SniMaxComposedSpnLength
5757
{
@@ -725,12 +725,12 @@ internal static uint SniGetConnectionId(SNIHandle pConn, ref Guid connId)
725725
{
726726
return SNIGetInfoWrapper(pConn, QTypes.SNI_QUERY_CONN_CONNID, out connId);
727727
}
728-
728+
729729
internal static uint SniGetProviderNumber(SNIHandle pConn, ref ProviderEnum provNum)
730730
{
731731
return SNIGetInfoWrapper(pConn, QTypes.SNI_QUERY_CONN_PROVIDERNUM, out provNum);
732732
}
733-
733+
734734
internal static uint SniGetConnectionPort(SNIHandle pConn, ref ushort portNum)
735735
{
736736
return SNIGetInfoWrapper(pConn, QTypes.SNI_QUERY_CONN_PEERPORT, out portNum);
@@ -812,7 +812,7 @@ internal static unsafe uint SNIOpenSyncEx(ConsumerInfo consumerInfo, string cons
812812
clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv4 = cachedDNSInfo?.AddrIPv4;
813813
clientConsumerInfo.DNSCacheInfo.wszCachedTcpIPv6 = cachedDNSInfo?.AddrIPv6;
814814
clientConsumerInfo.DNSCacheInfo.wszCachedTcpPort = cachedDNSInfo?.Port;
815-
815+
816816
if (spnBuffer != null)
817817
{
818818
fixed (byte* pin_spnBuffer = &spnBuffer[0])
@@ -1075,6 +1075,32 @@ private static void MarshalConsumerInfo(ConsumerInfo consumerInfo, ref Sni_Consu
10751075
: IntPtr.Zero;
10761076
native_consumerInfo.ConsumerKey = consumerInfo.key;
10771077
}
1078+
1079+
internal static bool RegisterTraceProvider(int eventKeyword)
1080+
{
1081+
// Registers the TraceLogging provider, enabling it to generate events.
1082+
// Return true if enabled, otherwise false.
1083+
if (s_is64bitProcess)
1084+
{
1085+
return SNINativeManagedWrapperX64.RegisterTraceProviderWrapper(eventKeyword);
1086+
}
1087+
else
1088+
{
1089+
return SNINativeManagedWrapperX86.RegisterTraceProviderWrapper(eventKeyword);
1090+
}
1091+
}
1092+
1093+
internal static void UnregisterTraceProvider()
1094+
{
1095+
if (s_is64bitProcess)
1096+
{
1097+
SNINativeManagedWrapperX64.UnregisterTraceProviderWrapper();
1098+
}
1099+
else
1100+
{
1101+
SNINativeManagedWrapperX86.UnregisterTraceProviderWrapper();
1102+
}
1103+
}
10781104
}
10791105
}
10801106

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Diagnostics;
7+
using System.Diagnostics.Tracing;
8+
9+
namespace Microsoft.Data.SqlClient
10+
{
11+
internal partial class SqlClientEventSource : EventSource
12+
{
13+
private bool _traceLoggingProviderEnabled = false;
14+
15+
/// <summary>
16+
/// Captures application flow traces from native networking implementation
17+
/// </summary>
18+
private const EventCommand SNINativeTrace = (EventCommand)8192;
19+
20+
/// <summary>
21+
/// Captures scope trace events from native networking implementation
22+
/// </summary>
23+
private const EventCommand SNINativeScope = (EventCommand)16384;
24+
25+
/// <summary>
26+
/// Disables all event tracing in native networking implementation
27+
/// </summary>
28+
private const EventCommand SNINativeDisable = (EventCommand)32768;
29+
30+
protected override void OnEventCommand(EventCommandEventArgs e)
31+
{
32+
// Internally, EventListener.EnableEvents sends an event command, with a reserved value of 0, -2, or -3.
33+
// When a command is sent via EnableEvents or SendCommand, check if it is a user-defined value
34+
// to enable or disable event tracing in sni.dll.
35+
// If registration fails, all write and unregister commands will be a no-op.
36+
37+
// If managed networking is enabled, don't call native wrapper methods
38+
#if netcoreapp
39+
if (AppContext.TryGetSwitch("Switch.Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows", out bool isEnabled) && isEnabled)
40+
{
41+
return;
42+
}
43+
#endif
44+
// Only register the provider if it's not already registered. Registering a provider that is already
45+
// registered can lead to unpredictable behaviour.
46+
if (!_traceLoggingProviderEnabled && e.Command > 0 && (e.Command & (SNINativeTrace | SNINativeScope)) != 0)
47+
{
48+
int eventKeyword = (int)(e.Command & (SNINativeTrace | SNINativeScope));
49+
_traceLoggingProviderEnabled = SNINativeMethodWrapper.RegisterTraceProvider(eventKeyword);
50+
Debug.Assert(_traceLoggingProviderEnabled, "Failed to enable TraceLogging provider.");
51+
}
52+
else if (_traceLoggingProviderEnabled && (e.Command == SNINativeDisable))
53+
{
54+
// Only unregister the provider if it's currently registered.
55+
SNINativeMethodWrapper.UnregisterTraceProvider();
56+
_traceLoggingProviderEnabled = false;
57+
}
58+
}
59+
}
60+
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlClientEventSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace Microsoft.Data.SqlClient
99
{
1010
[EventSource(Name = "Microsoft.Data.SqlClient.EventSource")]
11-
internal class SqlClientEventSource : EventSource
11+
internal partial class SqlClientEventSource : EventSource
1212
{
1313
// Defines the singleton instance for the Resources ETW provider
1414
internal static readonly SqlClientEventSource Log = new SqlClientEventSource();

0 commit comments

Comments
 (0)