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

Enhancements to NETCore.Client and dotnet-dump around ports and logging #3877

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
315 changes: 252 additions & 63 deletions documentation/design-docs/ipc-protocol.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Microsoft.Diagnostics.NETCore.Client
/// </summary>
public sealed class DiagnosticsClient
{
private const string DumpOperationName = "Write dump";
private readonly IpcEndpoint _endpoint;

public DiagnosticsClient(int processId) :
Expand Down Expand Up @@ -129,27 +130,59 @@ public void WriteDump(DumpType dumpType, string dumpPath, bool logDumpGeneration
/// Trigger a core dump generation.
/// </summary>
/// <param name="dumpType">Type of the dump to be generated</param>
/// <param name="dumpPath">Full path to the dump to be generated. By default it is /tmp/coredump.{pid}</param>
/// <param name="dumpPath">Full path to the dump to be generated.</param>
/// <param name="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param>
public void WriteDump(DumpType dumpType, string dumpPath, WriteDumpFlags flags)
{
IpcMessage request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump3, dumpType, dumpPath, flags);
WriteDump(dumpType, dumpPath, flags, logPath: null);
}

/// <summary>
/// Trigger a core dump generation.
/// </summary>
/// <param name="dumpType">Type of the dump to be generated</param>
/// <param name="dumpPath">Full path to the dump to be generated.</param>
/// <param name="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param>
/// <param name="logPath">Full path to the log to be generated. If null or empty and flags requests logging - the default behavior is... </param>
public void WriteDump(DumpType dumpType, string dumpPath, WriteDumpFlags flags, string logPath)
{
IpcMessage request = CreateWriteDumpMessageV4(dumpType, dumpPath, flags, logPath);
IpcMessage response = IpcClient.SendMessage(_endpoint, request);
if (!ValidateResponseMessage(response, "Write dump", ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned))

if (ValidateResponseMessage(response, DumpOperationName, ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned))
{
request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump2, dumpType, dumpPath, flags);
response = IpcClient.SendMessage(_endpoint, request);
if (!ValidateResponseMessage(response, "Write dump", ValidateResponseOptions.UnknownCommandReturnsFalse))
{
if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0)
{
throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags));
}
request = CreateWriteDumpMessage(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0);
response = IpcClient.SendMessage(_endpoint, request);
ValidateResponseMessage(response, "Write dump");
}
return;
}

if ((flags & (WriteDumpFlags.LogToFile | WriteDumpFlags.VerboseLoggingEnabled)) != 0)
{
throw new ArgumentException($"{nameof(WriteDumpFlags.LogToFile)} and {nameof(WriteDumpFlags.VerboseLoggingEnabled)} flags are not supported by the current runtime.", nameof(flags));
}

request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump3, dumpType, dumpPath, flags);
response = IpcClient.SendMessage(_endpoint, request);

if (ValidateResponseMessage(response, DumpOperationName, ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned))
{
return;
}

request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump2, dumpType, dumpPath, flags);
response = IpcClient.SendMessage(_endpoint, request);

if (ValidateResponseMessage(response, DumpOperationName, ValidateResponseOptions.UnknownCommandReturnsFalse))
{
return;
}

if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0)
{
throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags));
}

request = CreateWriteDumpMessage(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0);
response = IpcClient.SendMessage(_endpoint, request);
ValidateResponseMessage(response, DumpOperationName);
}

/// <summary>
Expand All @@ -171,25 +204,54 @@ public Task WriteDumpAsync(DumpType dumpType, string dumpPath, bool logDumpGener
/// <param name="dumpPath">Full path to the dump to be generated. By default it is /tmp/coredump.{pid}</param>
/// <param name="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param>
/// <param name="token">The token to monitor for cancellation requests.</param>
public async Task WriteDumpAsync(DumpType dumpType, string dumpPath, WriteDumpFlags flags, CancellationToken token)
public Task WriteDumpAsync(DumpType dumpType, string dumpPath, WriteDumpFlags flags, CancellationToken token)
{
IpcMessage request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump3, dumpType, dumpPath, flags);
return WriteDumpAsync(dumpType, dumpPath, flags, logPath: null, token);
}

/// <summary>
/// Trigger a core dump generation.
/// </summary>
/// <param name="dumpType">Type of the dump to be generated</param>
/// <param name="dumpPath">Full path to the dump to be generated. By default it is /tmp/coredump.{pid}</param>
/// <param name="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param>
/// <param name="logPath">Full path to the log to be generated. If null or empty and flags requests logging - the default behavior is... </param>
/// <param name="token">The token to monitor for cancellation requests.</param>
public async Task WriteDumpAsync(DumpType dumpType, string dumpPath, WriteDumpFlags flags, string logPath, CancellationToken token)
{
IpcMessage request = CreateWriteDumpMessageV4(dumpType, dumpPath, flags, logPath);
IpcMessage response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
if (!ValidateResponseMessage(response, "Write dump", ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned))
if (ValidateResponseMessage(response, DumpOperationName, ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned))
{
request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump2, dumpType, dumpPath, flags);
response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
if (!ValidateResponseMessage(response, "Write dump", ValidateResponseOptions.UnknownCommandReturnsFalse))
{
if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0)
{
throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags));
}
request = CreateWriteDumpMessage(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0);
response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
ValidateResponseMessage(response, "Write dump");
}
return;
}

if ((flags & (WriteDumpFlags.LogToFile | WriteDumpFlags.VerboseLoggingEnabled)) != 0)
{
throw new ArgumentException($"{nameof(WriteDumpFlags.LogToFile)} and {nameof(WriteDumpFlags.VerboseLoggingEnabled)} flags are not supported by the current runtime.", nameof(flags));
}

request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump3, dumpType, dumpPath, flags);
response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
if (ValidateResponseMessage(response, DumpOperationName, ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned))
{
return;
}

request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump2, dumpType, dumpPath, flags);
response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
if (ValidateResponseMessage(response, DumpOperationName, ValidateResponseOptions.UnknownCommandReturnsFalse))
{
return;
}

if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0)
{
throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags));
}
request = CreateWriteDumpMessage(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0);
response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false);
ValidateResponseMessage(response, DumpOperationName);
}

/// <summary>
Expand Down Expand Up @@ -566,6 +628,17 @@ private static IpcMessage CreateWriteDumpMessage(DumpCommandId command, DumpType
return new IpcMessage(DiagnosticsServerCommandSet.Dump, (byte)command, payload);
}

private static IpcMessage CreateWriteDumpMessageV4(DumpType dumpType, string dumpPath, WriteDumpFlags flags, string logPath)
{
if (string.IsNullOrEmpty(dumpPath))
{
throw new ArgumentNullException($"{nameof(dumpPath)} required");
}

byte[] payload = SerializePayload(dumpPath, (uint)dumpType, (uint)flags, logPath);
return new IpcMessage(DiagnosticsServerCommandSet.Dump, (byte)DumpCommandId.GenerateCoreDump4, payload);
}

private static ProcessInfo GetProcessInfoFromResponse(IpcResponse response, string operationName)
{
ValidateResponseMessage(response.Message, operationName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

namespace Microsoft.Diagnostics.NETCore.Client
{
public enum WriteDumpFlags
[System.Flags]
public enum WriteDumpFlags : uint
{
None = 0x00,
LoggingEnabled = 0x01,
VerboseLoggingEnabled = 0x02,
CrashReportEnabled = 0x04
CrashReportEnabled = 0x04,
LogToFile = 0x8
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal enum DumpCommandId : byte
GenerateCoreDump = 0x01,
GenerateCoreDump2 = 0x02,
GenerateCoreDump3 = 0x03,
GenerateCoreDump4 = 0x04,
}

internal enum ProfilerCommandId : byte
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<ItemGroup>
<InternalsVisibleTo Include="dotnet-counters" />
<InternalsVisibleTo Include="dotnet-dsrouter" />
<InternalsVisibleTo Include="dotnet-dump" />
<InternalsVisibleTo Include="dotnet-monitor" />
<InternalsVisibleTo Include="dotnet-trace" />
<InternalsVisibleTo Include="Microsoft.Diagnostics.Monitoring" />
Expand Down
Loading