-
Notifications
You must be signed in to change notification settings - Fork 359
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DiagnosticsClientConnector to support creating a DiagnosticsClien…
…t from a diagnostic port (#5073) Followup of #5070 that introduced a non-viable approach (Comment #5070 (comment)) This PR adds `DiagnosticsClientConnector` that is `IAsyncDisposable` and offers the method `FromDiagnosticPort`.
- Loading branch information
Showing
2 changed files
with
90 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClientConnector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Runtime.InteropServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.Diagnostics.NETCore.Client | ||
{ | ||
/// <summary> | ||
/// A connector that allows to create a <see cref="DiagnosticsClient"/> from a diagnostic port. | ||
/// </summary> | ||
public sealed class DiagnosticsClientConnector : IAsyncDisposable | ||
{ | ||
private bool _disposed; | ||
private readonly IAsyncDisposable _server; | ||
|
||
internal DiagnosticsClientConnector(DiagnosticsClient diagnosticClient, IAsyncDisposable server) | ||
{ | ||
_server = server; | ||
Instance = diagnosticClient; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the <see cref="DiagnosticsClient"/> instance. | ||
/// </summary> | ||
public DiagnosticsClient Instance { get; } | ||
|
||
/// <inheritdoc /> | ||
public async ValueTask DisposeAsync() | ||
{ | ||
if (_disposed) | ||
{ | ||
return; | ||
} | ||
|
||
if (_server != null) | ||
{ | ||
await _server.DisposeAsync().ConfigureAwait(false); | ||
} | ||
|
||
_disposed = true; | ||
} | ||
|
||
/// <summary> | ||
/// Create a new <see cref="DiagnosticsClientConnector"/> instance using the specified diagnostic port. | ||
/// </summary> | ||
/// <param name="diagnosticPort">The diagnostic port.</param> | ||
/// <param name="ct">The token to monitor for cancellation requests.</param> | ||
/// <returns>A <see cref="DiagnosticsClientConnector"/> instance</returns> | ||
public static async Task<DiagnosticsClientConnector> FromDiagnosticPort(string diagnosticPort, CancellationToken ct) | ||
{ | ||
if (diagnosticPort is null) | ||
{ | ||
throw new ArgumentNullException(nameof(diagnosticPort)); | ||
} | ||
|
||
IpcEndpointConfig portConfig = IpcEndpointConfig.Parse(diagnosticPort); | ||
|
||
if (portConfig.IsListenConfig) | ||
{ | ||
string fullPort = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? portConfig.Address : Path.GetFullPath(portConfig.Address); | ||
ReversedDiagnosticsServer server = new(fullPort); | ||
server.Start(); | ||
|
||
try | ||
{ | ||
IpcEndpointInfo endpointInfo = await server.AcceptAsync(ct).ConfigureAwait(false); | ||
return new DiagnosticsClientConnector(new DiagnosticsClient(endpointInfo.Endpoint), server); | ||
} | ||
catch (TaskCanceledException) | ||
{ | ||
//clean up the server | ||
await server.DisposeAsync().ConfigureAwait(false); | ||
if (!ct.IsCancellationRequested) | ||
{ | ||
throw; | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
Debug.Assert(portConfig.IsConnectConfig); | ||
return new DiagnosticsClientConnector(new DiagnosticsClient(portConfig), null); | ||
} | ||
} | ||
} |