Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add HTTP requests grid #23

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"microsoft.openapi.kiota": {
"version": "1.10.1",
"version": "1.11.0",
"commands": [
"kiota"
]
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Authors>Alexey Sosnin</Authors>
<PackageTags>ClrMd diagnostics</PackageTags>
<Description>Diagnostics utility to analyze memory dumps of a .NET application</Description>
<Description>Diagnostics utility with web UI to analyze .NET application memory dump</Description>
</PropertyGroup>

<PropertyGroup>
Expand Down
70 changes: 49 additions & 21 deletions src/DebugHost/Program.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,79 @@
using Heartbeat.Domain;
using Heartbeat.Runtime;
using Heartbeat.Runtime.Domain;
using Heartbeat.Runtime.Analyzers;
using Heartbeat.Runtime.Proxies;

using Microsoft.Diagnostics.Runtime;
using Microsoft.Diagnostics.Runtime.Interfaces;

// foreach (var dumpPath in Directory.GetFiles(@"D:\dumps", "*.dmp"))
// {
// ProcessFile(dumpPath);
// }
foreach (var dumpPath in Directory.GetFiles(@"C:\Users\Ne4to\projects\local\HttpRequestDumpSamples", "*.dmp"))
{
ProcessFile(dumpPath);
}

ProcessFile(@"D:\dbg\dump_20230507_155200.dmp");
// ProcessFile(@"D:\dbg\dump_20230507_155200.dmp");
// ProcessFile(@"D:\dbg\user-management\local\dotnet-04.DMP");

static void ProcessFile(string filePath)
{
{
Console.WriteLine();
Console.WriteLine($"Processing dump: {filePath}");

var runtimeContext = new RuntimeContext(filePath);
WriteDictionary(runtimeContext);
// WriteDictionary(runtimeContext);
// WriteWebRequests(runtimeContext);
WriteHttpRequestMessage(runtimeContext);

static void WriteHttpRequestMessage(RuntimeContext runtimeContext)
{
var analyzer = new HttpRequestAnalyzer(runtimeContext);
foreach (HttpRequestInfo httpRequest in analyzer.EnumerateHttpRequests())
{
Console.WriteLine($"{httpRequest.HttpMethod} {httpRequest.Url} {httpRequest.StatusCode}");
Console.WriteLine("\tRequest headers:");
PrintHeaders(httpRequest.RequestHeaders);
Console.WriteLine("\tResponse headers:");
PrintHeaders(httpRequest.ResponseHeaders);
}

static void PrintHeaders(IReadOnlyList<HttpHeader> headers)
{
foreach (HttpHeader header in headers)
{
Console.WriteLine($"\t\t{header.Name}: {header.Value}");
}
}
}

void WriteDictionary(RuntimeContext runtimeContext1)
static void WriteDictionary(RuntimeContext runtimeContext)
{
var obj = runtimeContext.EnumerateObjects(null)
IClrValue obj = runtimeContext.EnumerateObjects(null)
.Where(obj => !obj.IsNull && obj.Type.Name.StartsWith("System.Collections.Generic.Dictionary<System.String"))
.FirstOrDefault();

DictionaryProxy dictionaryProxy = new DictionaryProxy(runtimeContext, obj);
foreach (var kvp in dictionaryProxy.EnumerateItems())
{
Console.WriteLine($"{kvp.Key.Address:x16} = {kvp.Value.Address:x16}");
Console.WriteLine($"{kvp.Key.Value.Address:x16} = {kvp.Value.Value.Address:x16}");
}
}
// WriteWebRequests(runtimeContext);

static void WriteWebRequests(RuntimeContext runtimeContext)
{
var q = from clrObject in runtimeContext.EnumerateObjectsByTypeName("System.Net.HttpWebRequest", null)
let webRequestProxy = new HttpWebRequestProxy(runtimeContext, clrObject)
let requestContentLength = webRequestProxy.ContentLength
let responseContentLength = webRequestProxy.Response?.ContentLength
let totalSize = requestContentLength ?? 0L + responseContentLength ?? 0L
orderby totalSize descending
select $"{webRequestProxy.Method} {webRequestProxy.Address.Value} Request ContentLength: {webRequestProxy.ContentLength} Response ContentLength {webRequestProxy.Response?.ContentLength}";
var q = from IClrValue clrObject in runtimeContext.EnumerateObjectsByTypeName("System.Net.HttpWebRequest", null)
let webRequestProxy = new HttpWebRequestProxy(runtimeContext, clrObject)
let requestContentLength = webRequestProxy.ContentLength
let responseContentLength = webRequestProxy.Response?.ContentLength
let totalSize = requestContentLength ?? 0L + responseContentLength ?? 0L
orderby totalSize descending
select
$"{webRequestProxy.Method} {webRequestProxy.Address.Value} Request ContentLength: {webRequestProxy.ContentLength} Response ContentLength {webRequestProxy.Response?.ContentLength}";

foreach (var msg in q.Take(10))
{
Console.WriteLine(msg);
}
}
}
}



9 changes: 4 additions & 5 deletions src/Heartbeat.Runtime/Analyzers/AsyncStatusMachineAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Heartbeat.Runtime.Proxies;

using Microsoft.Diagnostics.Runtime;
using Microsoft.Diagnostics.Runtime.Interfaces;
using Microsoft.Extensions.Logging;


Expand All @@ -24,7 +25,7 @@ public void Dump(ILogger logger)

logger.LogInformation("State machines");

foreach (var stateMachineBoxObject in EnumerateAsyncStateMachineObjects())
foreach (IClrValue stateMachineBoxObject in EnumerateAsyncStateMachineObjects())
{
var stateMachineBoxProxy = new AsyncStateMachineBoxProxy(Context, stateMachineBoxObject);
logger.LogInformation(stateMachineBoxObject.ToString());
Expand Down Expand Up @@ -67,7 +68,7 @@ where clrObject.Type

var builderValueClass = stateMachineObject.ReadValueTypeField("<>t__builder");

ClrObject taskObject;
IClrValue taskObject;
string? typeName = builderValueClass.Type!.Name;
if (typeName == "System.Runtime.CompilerServices.AsyncTaskMethodBuilder")
{
Expand Down Expand Up @@ -117,9 +118,7 @@ where clrObject.Type
continue;
}



var uTaskObject = uField.ReadObjectField("m_task");
IClrValue uTaskObject = uField.ReadObjectField("m_task");
var statusTask = "NULL";
if (!uTaskObject.IsNull)
{
Expand Down
Loading
Loading