зеркало из https://github.com/mono/corefx.git
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.
This commit is contained in:
Родитель
29b4e911be
Коммит
e1daed6dac
|
@ -61,19 +61,19 @@ namespace System.Net
|
||||||
WriteEvent(HeadersInvalidValueId, name, rawValue);
|
WriteEvent(HeadersInvalidValueId, name, rawValue);
|
||||||
|
|
||||||
[Event(HandlerMessageId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
|
[Event(HandlerMessageId, Keywords = Keywords.Debug, Level = EventLevel.Verbose)]
|
||||||
public void HandlerMessage(int workerId, int requestId, string memberName, string message) =>
|
public void HandlerMessage(int handlerId, int workerId, int requestId, string memberName, string message) =>
|
||||||
WriteEvent(HandlerMessageId, workerId, requestId, memberName, message);
|
WriteEvent(HandlerMessageId, handlerId, workerId, requestId, memberName, message);
|
||||||
|
|
||||||
[NonEvent]
|
[NonEvent]
|
||||||
private unsafe void WriteEvent(int eventId, int arg1, int arg2, string arg3, string arg4)
|
private unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3, string arg4, string arg5)
|
||||||
{
|
{
|
||||||
if (IsEnabled())
|
if (IsEnabled())
|
||||||
{
|
{
|
||||||
if (arg3 == null) arg3 = "";
|
|
||||||
if (arg4 == null) arg4 = "";
|
if (arg4 == null) arg4 = "";
|
||||||
|
if (arg5 == null) arg5 = "";
|
||||||
|
|
||||||
fixed (char* string3Bytes = arg3)
|
|
||||||
fixed (char* string4Bytes = arg4)
|
fixed (char* string4Bytes = arg4)
|
||||||
|
fixed (char* string5Bytes = arg5)
|
||||||
{
|
{
|
||||||
const int NumEventDatas = 4;
|
const int NumEventDatas = 4;
|
||||||
var descrs = stackalloc EventData[NumEventDatas];
|
var descrs = stackalloc EventData[NumEventDatas];
|
||||||
|
@ -84,12 +84,15 @@ namespace System.Net
|
||||||
descrs[1].DataPointer = (IntPtr)(&arg2);
|
descrs[1].DataPointer = (IntPtr)(&arg2);
|
||||||
descrs[1].Size = sizeof(int);
|
descrs[1].Size = sizeof(int);
|
||||||
|
|
||||||
descrs[2].DataPointer = (IntPtr)string3Bytes;
|
descrs[2].DataPointer = (IntPtr)(&arg3);
|
||||||
descrs[2].Size = ((arg3.Length + 1) * 2);
|
descrs[2].Size = sizeof(int);
|
||||||
|
|
||||||
descrs[3].DataPointer = (IntPtr)string4Bytes;
|
descrs[3].DataPointer = (IntPtr)string4Bytes;
|
||||||
descrs[3].Size = ((arg4.Length + 1) * 2);
|
descrs[3].Size = ((arg4.Length + 1) * 2);
|
||||||
|
|
||||||
|
descrs[4].DataPointer = (IntPtr)string5Bytes;
|
||||||
|
descrs[4].Size = ((arg5.Length + 1) * 2);
|
||||||
|
|
||||||
WriteEventCore(eventId, NumEventDatas, descrs);
|
WriteEventCore(eventId, NumEventDatas, descrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace System.Net.Http
|
||||||
|
|
||||||
private int TlsClientCertCallback(IntPtr ssl, out IntPtr certHandle, out IntPtr privateKeyHandle)
|
private int TlsClientCertCallback(IntPtr ssl, out IntPtr certHandle, out IntPtr privateKeyHandle)
|
||||||
{
|
{
|
||||||
|
EventSourceTrace("SSL: {0}", ssl);
|
||||||
const int CertificateSet = 1, NoCertificateSet = 0, SuspendHandshake = -1;
|
const int CertificateSet = 1, NoCertificateSet = 0, SuspendHandshake = -1;
|
||||||
|
|
||||||
certHandle = IntPtr.Zero;
|
certHandle = IntPtr.Zero;
|
||||||
|
@ -52,17 +53,24 @@ namespace System.Net.Http
|
||||||
if (_clientCertificates != null) // manual mode
|
if (_clientCertificates != null) // manual mode
|
||||||
{
|
{
|
||||||
// If there's one certificate, just use it. Otherwise, try to find the best one.
|
// If there's one certificate, just use it. Otherwise, try to find the best one.
|
||||||
if (_clientCertificates.Count == 1)
|
int certCount = _clientCertificates.Count;
|
||||||
|
if (certCount == 1)
|
||||||
{
|
{
|
||||||
|
EventSourceTrace("Single certificate. Building chain.");
|
||||||
certificate = _clientCertificates[0];
|
certificate = _clientCertificates[0];
|
||||||
chain = TLSCertificateExtensions.BuildNewChain(certificate, includeClientApplicationPolicy: false);
|
chain = TLSCertificateExtensions.BuildNewChain(certificate, includeClientApplicationPolicy: false);
|
||||||
}
|
}
|
||||||
else if (!_clientCertificates.TryFindClientCertificate(issuerNames, out certificate, out chain))
|
else
|
||||||
{
|
{
|
||||||
EventSourceTrace("No manual certificate or chain.");
|
EventSourceTrace("Finding the best of {0} certificates", certCount);
|
||||||
|
if (!_clientCertificates.TryFindClientCertificate(issuerNames, out certificate, out chain))
|
||||||
|
{
|
||||||
|
EventSourceTrace("No certificate set.");
|
||||||
return NoCertificateSet;
|
return NoCertificateSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EventSourceTrace("Chain built.");
|
||||||
|
}
|
||||||
else if (!GetAutomaticClientCertificate(issuerNames, out certificate, out chain)) // automatic mode
|
else if (!GetAutomaticClientCertificate(issuerNames, out certificate, out chain)) // automatic mode
|
||||||
{
|
{
|
||||||
EventSourceTrace("No automatic certificate or chain.");
|
EventSourceTrace("No automatic certificate or chain.");
|
||||||
|
|
|
@ -87,6 +87,8 @@ namespace System.Net.Http
|
||||||
}
|
}
|
||||||
_easyHandle = easyHandle;
|
_easyHandle = easyHandle;
|
||||||
|
|
||||||
|
EventSourceTrace("Configuring request.");
|
||||||
|
|
||||||
// Before setting any other options, turn on curl's debug tracing
|
// Before setting any other options, turn on curl's debug tracing
|
||||||
// if desired. CURLOPT_VERBOSE may also be set subsequently if
|
// if desired. CURLOPT_VERBOSE may also be set subsequently if
|
||||||
// EventSource tracing is enabled.
|
// EventSource tracing is enabled.
|
||||||
|
@ -109,6 +111,8 @@ namespace System.Net.Http
|
||||||
SetCookieOption(_requestMessage.RequestUri);
|
SetCookieOption(_requestMessage.RequestUri);
|
||||||
SetRequestHeaders();
|
SetRequestHeaders();
|
||||||
SetSslOptions();
|
SetSslOptions();
|
||||||
|
|
||||||
|
EventSourceTrace("Done configuring request.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureResponseMessagePublished()
|
public void EnsureResponseMessagePublished()
|
||||||
|
|
|
@ -431,6 +431,7 @@ namespace System.Net.Http
|
||||||
private void HandleIncomingRequests()
|
private void HandleIncomingRequests()
|
||||||
{
|
{
|
||||||
Debug.Assert(!Monitor.IsEntered(_incomingRequests), "Incoming requests lock should only be held while accessing the queue");
|
Debug.Assert(!Monitor.IsEntered(_incomingRequests), "Incoming requests lock should only be held while accessing the queue");
|
||||||
|
EventSourceTrace(null);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -499,7 +500,9 @@ namespace System.Net.Http
|
||||||
private void PerformCurlWork()
|
private void PerformCurlWork()
|
||||||
{
|
{
|
||||||
CURLMcode performResult;
|
CURLMcode performResult;
|
||||||
|
EventSourceTrace("Ask libcurl to perform any available work...");
|
||||||
while ((performResult = Interop.Http.MultiPerform(_multiHandle)) == CURLMcode.CURLM_CALL_MULTI_PERFORM) ;
|
while ((performResult = Interop.Http.MultiPerform(_multiHandle)) == CURLMcode.CURLM_CALL_MULTI_PERFORM) ;
|
||||||
|
EventSourceTrace("...done performing work: {0}", performResult);
|
||||||
ThrowIfCURLMError(performResult);
|
ThrowIfCURLMError(performResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,9 +545,12 @@ namespace System.Net.Http
|
||||||
/// <summary>Handle a libcurl message received as part of processing work. This should signal a completed operation.</summary>
|
/// <summary>Handle a libcurl message received as part of processing work. This should signal a completed operation.</summary>
|
||||||
private void HandleCurlMessage(Interop.Http.CURLMSG message, IntPtr easyHandle, CURLcode result)
|
private void HandleCurlMessage(Interop.Http.CURLMSG message, IntPtr easyHandle, CURLcode result)
|
||||||
{
|
{
|
||||||
Debug.Assert(message == Interop.Http.CURLMSG.CURLMSG_DONE, $"CURLMSG_DONE is supposed to be the only message type, but got {message}");
|
|
||||||
if (message != Interop.Http.CURLMSG.CURLMSG_DONE)
|
if (message != Interop.Http.CURLMSG.CURLMSG_DONE)
|
||||||
|
{
|
||||||
|
Debug.Fail($"CURLMSG_DONE is supposed to be the only message type, but got {message}");
|
||||||
|
EventSourceTrace("Unexpected CURLMSG: {0}", message);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the GCHandle pointer from the easy handle's state
|
// Get the GCHandle pointer from the easy handle's state
|
||||||
IntPtr gcHandlePtr;
|
IntPtr gcHandlePtr;
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace System.Net.Http
|
||||||
|
|
||||||
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption)
|
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption)
|
||||||
{
|
{
|
||||||
|
EventSourceTrace("ClientCertificateOption: {0}", clientCertOption, easy:easy);
|
||||||
Debug.Assert(clientCertOption == ClientCertificateOption.Automatic || clientCertOption == ClientCertificateOption.Manual);
|
Debug.Assert(clientCertOption == ClientCertificateOption.Automatic || clientCertOption == ClientCertificateOption.Manual);
|
||||||
|
|
||||||
// Create a client certificate provider if client certs may be used.
|
// Create a client certificate provider if client certs may be used.
|
||||||
|
@ -38,6 +39,8 @@ namespace System.Net.Http
|
||||||
IntPtr userPointer = IntPtr.Zero;
|
IntPtr userPointer = IntPtr.Zero;
|
||||||
if (certProvider != null)
|
if (certProvider != null)
|
||||||
{
|
{
|
||||||
|
EventSourceTrace("Created certificate provider", easy:easy);
|
||||||
|
|
||||||
// The client cert provider needs to be passed through to the callback, and thus
|
// The client cert provider needs to be passed through to the callback, and thus
|
||||||
// we create a GCHandle to keep it rooted. This handle needs to be cleaned up
|
// we create a GCHandle to keep it rooted. This handle needs to be cleaned up
|
||||||
// when the request has completed, and a simple and pay-for-play way to do that
|
// when the request has completed, and a simple and pay-for-play way to do that
|
||||||
|
@ -67,6 +70,7 @@ namespace System.Net.Http
|
||||||
private static void SetSslOptionsForSupportedBackend(EasyRequest easy, ClientCertificateProvider certProvider, IntPtr userPointer)
|
private static void SetSslOptionsForSupportedBackend(EasyRequest easy, ClientCertificateProvider certProvider, IntPtr userPointer)
|
||||||
{
|
{
|
||||||
CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer);
|
CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer);
|
||||||
|
EventSourceTrace("Callback registration result: {0}", answer, easy: easy);
|
||||||
switch (answer)
|
switch (answer)
|
||||||
{
|
{
|
||||||
case CURLcode.CURLE_OK:
|
case CURLcode.CURLE_OK:
|
||||||
|
@ -86,7 +90,6 @@ namespace System.Net.Http
|
||||||
|
|
||||||
case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.38 and prior
|
case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.38 and prior
|
||||||
case CURLcode.CURLE_NOT_BUILT_IN: // Curl 7.39 and later
|
case CURLcode.CURLE_NOT_BUILT_IN: // Curl 7.39 and later
|
||||||
EventSourceTrace("CURLOPT_SSL_CTX_FUNCTION not supported: {0}", answer, easy: easy);
|
|
||||||
SetSslOptionsForUnsupportedBackend(easy, certProvider);
|
SetSslOptionsForUnsupportedBackend(easy, certProvider);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -181,6 +184,7 @@ namespace System.Net.Http
|
||||||
{
|
{
|
||||||
return CURLcode.CURLE_ABORTED_BY_CALLBACK;
|
return CURLcode.CURLE_ABORTED_BY_CALLBACK;
|
||||||
}
|
}
|
||||||
|
EventSourceTrace(null, easy: easy);
|
||||||
|
|
||||||
// Configure the SSL protocols allowed.
|
// Configure the SSL protocols allowed.
|
||||||
SslProtocols protocols = easy._handler.SslProtocols;
|
SslProtocols protocols = easy._handler.SslProtocols;
|
||||||
|
|
|
@ -720,6 +720,7 @@ namespace System.Net.Http
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEventSource.Log.HandlerMessage(
|
NetEventSource.Log.HandlerMessage(
|
||||||
|
agent?.GetHashCode() ?? 0,
|
||||||
(agent?.RunningWorkerId).GetValueOrDefault(),
|
(agent?.RunningWorkerId).GetValueOrDefault(),
|
||||||
easy?.Task.Id ?? 0,
|
easy?.Task.Id ?? 0,
|
||||||
memberName,
|
memberName,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче