Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit b01c282

Browse files
committed
Add more tracing to HttpClient on Unix
Some recent investigations based on tracing data revealed some gaps in usefulness. This adds some more tracing to try to fill those gaps.
1 parent ecc6266 commit b01c282

File tree

6 files changed

+39
-13
lines changed

6 files changed

+39
-13
lines changed

src/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,19 @@ public void HeadersInvalidValue(string name, string rawValue) =>
6161
WriteEvent(HeadersInvalidValueId, name, rawValue);
6262

6363
[Event(HandlerMessageId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
64-
public void HandlerMessage(int workerId, int requestId, string memberName, string message) =>
65-
WriteEvent(HandlerMessageId, workerId, requestId, memberName, message);
64+
public void HandlerMessage(int handlerId, int workerId, int requestId, string memberName, string message) =>
65+
WriteEvent(HandlerMessageId, handlerId, workerId, requestId, memberName, message);
6666

6767
[NonEvent]
68-
private unsafe void WriteEvent(int eventId, int arg1, int arg2, string arg3, string arg4)
68+
private unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3, string arg4, string arg5)
6969
{
7070
if (IsEnabled())
7171
{
72-
if (arg3 == null) arg3 = "";
7372
if (arg4 == null) arg4 = "";
73+
if (arg5 == null) arg5 = "";
7474

75-
fixed (char* string3Bytes = arg3)
7675
fixed (char* string4Bytes = arg4)
76+
fixed (char* string5Bytes = arg5)
7777
{
7878
const int NumEventDatas = 4;
7979
var descrs = stackalloc EventData[NumEventDatas];
@@ -84,12 +84,15 @@ private unsafe void WriteEvent(int eventId, int arg1, int arg2, string arg3, str
8484
descrs[1].DataPointer = (IntPtr)(&arg2);
8585
descrs[1].Size = sizeof(int);
8686

87-
descrs[2].DataPointer = (IntPtr)string3Bytes;
88-
descrs[2].Size = ((arg3.Length + 1) * 2);
87+
descrs[2].DataPointer = (IntPtr)(&arg3);
88+
descrs[2].Size = sizeof(int);
8989

9090
descrs[3].DataPointer = (IntPtr)string4Bytes;
9191
descrs[3].Size = ((arg4.Length + 1) * 2);
9292

93+
descrs[4].DataPointer = (IntPtr)string5Bytes;
94+
descrs[4].Size = ((arg5.Length + 1) * 2);
95+
9396
WriteEventCore(eventId, NumEventDatas, descrs);
9497
}
9598
}

src/System.Net.Http/src/System/Net/Http/Unix/CurlHandler.ClientCertificateProvider.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ internal ClientCertificateProvider(X509Certificate2Collection clientCertificates
2828

2929
private int TlsClientCertCallback(IntPtr ssl, out IntPtr certHandle, out IntPtr privateKeyHandle)
3030
{
31+
EventSourceTrace("SSL: {0}", ssl);
3132
const int CertificateSet = 1, NoCertificateSet = 0, SuspendHandshake = -1;
3233

3334
certHandle = IntPtr.Zero;
@@ -52,16 +53,23 @@ private int TlsClientCertCallback(IntPtr ssl, out IntPtr certHandle, out IntPtr
5253
if (_clientCertificates != null) // manual mode
5354
{
5455
// If there's one certificate, just use it. Otherwise, try to find the best one.
55-
if (_clientCertificates.Count == 1)
56+
int certCount = _clientCertificates.Count;
57+
if (certCount == 1)
5658
{
59+
EventSourceTrace("Single certificate. Building chain.");
5760
certificate = _clientCertificates[0];
5861
chain = TLSCertificateExtensions.BuildNewChain(certificate, includeClientApplicationPolicy: false);
5962
}
60-
else if (!_clientCertificates.TryFindClientCertificate(issuerNames, out certificate, out chain))
63+
else
6164
{
62-
EventSourceTrace("No manual certificate or chain.");
63-
return NoCertificateSet;
65+
EventSourceTrace("Finding the best of {0} certificates", certCount);
66+
if (!_clientCertificates.TryFindClientCertificate(issuerNames, out certificate, out chain))
67+
{
68+
EventSourceTrace("No certificate set.");
69+
return NoCertificateSet;
70+
}
6471
}
72+
EventSourceTrace("Chain built.");
6573
}
6674
else if (!GetAutomaticClientCertificate(issuerNames, out certificate, out chain)) // automatic mode
6775
{

src/System.Net.Http/src/System/Net/Http/Unix/CurlHandler.EasyRequest.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ internal void InitializeCurl()
8787
}
8888
_easyHandle = easyHandle;
8989

90+
EventSourceTrace("Configuring request.");
91+
9092
// Before setting any other options, turn on curl's debug tracing
9193
// if desired. CURLOPT_VERBOSE may also be set subsequently if
9294
// EventSource tracing is enabled.
@@ -109,6 +111,8 @@ internal void InitializeCurl()
109111
SetCookieOption(_requestMessage.RequestUri);
110112
SetRequestHeaders();
111113
SetSslOptions();
114+
115+
EventSourceTrace("Done configuring request.");
112116
}
113117

114118
public void EnsureResponseMessagePublished()

src/System.Net.Http/src/System/Net/Http/Unix/CurlHandler.MultiAgent.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ private void WorkerBodyLoop()
431431
private void HandleIncomingRequests()
432432
{
433433
Debug.Assert(!Monitor.IsEntered(_incomingRequests), "Incoming requests lock should only be held while accessing the queue");
434+
EventSourceTrace(null);
434435

435436
while (true)
436437
{
@@ -499,7 +500,9 @@ private void HandleIncomingRequests()
499500
private void PerformCurlWork()
500501
{
501502
CURLMcode performResult;
503+
EventSourceTrace("Ask libcurl to perform any available work...");
502504
while ((performResult = Interop.Http.MultiPerform(_multiHandle)) == CURLMcode.CURLM_CALL_MULTI_PERFORM) ;
505+
EventSourceTrace("...done performing work: {0}", performResult);
503506
ThrowIfCURLMError(performResult);
504507
}
505508

@@ -542,9 +545,12 @@ private void WaitForWork()
542545
/// <summary>Handle a libcurl message received as part of processing work. This should signal a completed operation.</summary>
543546
private void HandleCurlMessage(Interop.Http.CURLMSG message, IntPtr easyHandle, CURLcode result)
544547
{
545-
Debug.Assert(message == Interop.Http.CURLMSG.CURLMSG_DONE, $"CURLMSG_DONE is supposed to be the only message type, but got {message}");
546548
if (message != Interop.Http.CURLMSG.CURLMSG_DONE)
549+
{
550+
Debug.Fail($"CURLMSG_DONE is supposed to be the only message type, but got {message}");
551+
EventSourceTrace("Unexpected CURLMSG: {0}", message);
547552
return;
553+
}
548554

549555
// Get the GCHandle pointer from the easy handle's state
550556
IntPtr gcHandlePtr;

src/System.Net.Http/src/System/Net/Http/Unix/CurlHandler.SslProvider.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ private static class SslProvider
2727

2828
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption)
2929
{
30+
EventSourceTrace("ClientCertificateOption: {0}", clientCertOption, easy:easy);
3031
Debug.Assert(clientCertOption == ClientCertificateOption.Automatic || clientCertOption == ClientCertificateOption.Manual);
3132

3233
// Create a client certificate provider if client certs may be used.
@@ -38,6 +39,8 @@ internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption cli
3839
IntPtr userPointer = IntPtr.Zero;
3940
if (certProvider != null)
4041
{
42+
EventSourceTrace("Created certificate provider", easy:easy);
43+
4144
// The client cert provider needs to be passed through to the callback, and thus
4245
// we create a GCHandle to keep it rooted. This handle needs to be cleaned up
4346
// when the request has completed, and a simple and pay-for-play way to do that
@@ -67,6 +70,7 @@ internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption cli
6770
private static void SetSslOptionsForSupportedBackend(EasyRequest easy, ClientCertificateProvider certProvider, IntPtr userPointer)
6871
{
6972
CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer);
73+
EventSourceTrace("Callback registration result: {0}", answer, easy: easy);
7074
switch (answer)
7175
{
7276
case CURLcode.CURLE_OK:
@@ -86,7 +90,6 @@ private static void SetSslOptionsForSupportedBackend(EasyRequest easy, ClientCer
8690

8791
case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.38 and prior
8892
case CURLcode.CURLE_NOT_BUILT_IN: // Curl 7.39 and later
89-
EventSourceTrace("CURLOPT_SSL_CTX_FUNCTION not supported: {0}", answer, easy: easy);
9093
SetSslOptionsForUnsupportedBackend(easy, certProvider);
9194
break;
9295

@@ -181,6 +184,7 @@ private static CURLcode SslCtxCallback(IntPtr curl, IntPtr sslCtx, IntPtr userPo
181184
{
182185
return CURLcode.CURLE_ABORTED_BY_CALLBACK;
183186
}
187+
EventSourceTrace(null, easy: easy);
184188

185189
// Configure the SSL protocols allowed.
186190
SslProtocols protocols = easy._handler.SslProtocols;

src/System.Net.Http/src/System/Net/Http/Unix/CurlHandler.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ private static void EventSourceTraceCore(string message, MultiAgent agent, EasyR
720720
}
721721

722722
NetEventSource.Log.HandlerMessage(
723+
agent?.GetHashCode() ?? 0,
723724
(agent?.RunningWorkerId).GetValueOrDefault(),
724725
easy?.Task.Id ?? 0,
725726
memberName,

0 commit comments

Comments
 (0)