Skip to content

Instantly share code, notes, and snippets.

@christianarg
Last active November 8, 2025 10:26
Show Gist options
  • Select an option

  • Save christianarg/1f01d574fe480ede43c26ac706f9bdd2 to your computer and use it in GitHub Desktop.

Select an option

Save christianarg/1f01d574fe480ede43c26ac706f9bdd2 to your computer and use it in GitHub Desktop.
Debug any LLM HTTP Calls in c# / dotnet. Actually Debug any library HTTP calls
using System.Diagnostics;
/// <summary>
/// Sets up a DiagnosticListener to log HTTP requests made by HttpClient.
/// Created it with the help of ChatGPT some time ago.
/// I wouldn't enable in production at all, but it's useful for debugging purposes.
///
/// Used to debug AI Frameworks HTTP calls since of them don't show exactly what is being sent.
///
/// Usage:
/// // no filter (any request):
/// HttpDiagnosticListener.Initialize();
///
/// // filter by specific URI content:
/// HttpDiagnosticListener.Initialize(filterByUriContent: "generativelanguage.googleapis.com");
/// </summary>
public static class HttpDiagnosticListener
{
public static void Initialize(string filterByUriContent = "")
{
var listener = new HttpClientLoggingListener(filterByUriContent);
DiagnosticListener.AllListeners.Subscribe(new DiagnosticListenerObserver(listener));
}
}
public class DiagnosticListenerObserver : IObserver<DiagnosticListener>
{
private readonly IObserver<KeyValuePair<string, object>> _innerObserver;
public DiagnosticListenerObserver(IObserver<KeyValuePair<string, object>> innerObserver)
{
_innerObserver = innerObserver;
}
public void OnNext(DiagnosticListener diagnosticListener)
{
if (diagnosticListener.Name == "HttpHandlerDiagnosticListener")
{
diagnosticListener.Subscribe(_innerObserver);
}
}
public void OnError(Exception error)
{
// Handle errors here, if needed
}
public void OnCompleted()
{
// Handle completion, if needed
}
}
public class HttpClientLoggingListener : IObserver<KeyValuePair<string, object>>
{
private readonly string _filterByUriContent;
public HttpClientLoggingListener()
{
}
public HttpClientLoggingListener(string filterByUriContent)
{
_filterByUriContent = filterByUriContent;
}
public void OnNext(KeyValuePair<string, object> value)
{
if (value.Key == "System.Net.Http.HttpRequestOut.Start")
{
var request = (HttpRequestMessage)value.Value.GetType().GetProperty("Request")?.GetValue(value.Value);
//Console.WriteLine($"Request: {request?.Method} {request?.RequestUri}");
// && request.RequestUri.ToString().Contains("openai.azure.com")
if (request.Method == HttpMethod.Post)
{
if (!string.IsNullOrEmpty(_filterByUriContent) && !request.RequestUri.ToString().Contains(_filterByUriContent))
{
return;
}
Console.WriteLine($"POST Request to {request.RequestUri}");
if (request.Content != null)
{
// Read the body as a string
var contentTask = request.Content.ReadAsStringAsync();
string requestBody = contentTask.Result; // WARNING! sync-over-async
Console.WriteLine("Request Body:");
Console.WriteLine(requestBody);
}
else
{
Console.WriteLine("Request Body: <No Content>");
}
}
}
}
public void OnError(Exception error) { }
public void OnCompleted() { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment