Skip to content

Commit

Permalink
Add logging
Browse files Browse the repository at this point in the history
  • Loading branch information
sharwell committed Oct 2, 2020
1 parent 9de2d24 commit bea58be
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 12 deletions.
67 changes: 56 additions & 11 deletions src/Workspaces/CoreTestUtilities/Remote/InProcRemostHostClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,20 @@
using System.Diagnostics;
using System.IO;
using System.IO.Pipelines;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.Remoting;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Experiments;
using Microsoft.CodeAnalysis.Extensions;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Serialization;
using Microsoft.CodeAnalysis.TodoComments;
using Microsoft.ServiceHub.Framework;
using Microsoft.VisualStudio.Threading;
using Nerdbank.Streams;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using StreamJsonRpc;
using Xunit.Abstractions;

namespace Microsoft.CodeAnalysis.Remote.Testing
{
Expand All @@ -41,7 +39,7 @@ public static async Task<RemoteHostClient> CreateAsync(HostWorkspaceServices ser

var remoteHostStream = await inprocServices.RequestServiceAsync(WellKnownServiceHubService.RemoteHost).ConfigureAwait(false);

var instance = new InProcRemoteHostClient(services, inprocServices, remoteHostStream);
var instance = new InProcRemoteHostClient(services, inprocServices, traceListener, remoteHostStream);

// make sure connection is done right
var uiCultureLCIDE = 0;
Expand All @@ -61,10 +59,19 @@ await instance._endPoint.InvokeAsync(
private InProcRemoteHostClient(
HostWorkspaceServices services,
InProcRemoteServices inprocServices,
TraceListener? traceListener,
Stream stream)
{
_workspaceServices = services;
_logger = new TraceSource("Default");
_logger = new TraceSource("Default")
{
Switch = { Level = SourceLevels.Information },
};

if (traceListener != null)
{
_logger.Listeners.Add(traceListener);
}

_inprocServices = inprocServices;

Expand Down Expand Up @@ -147,7 +154,10 @@ public override void Dispose()
}

private void OnDisconnected(JsonRpcDisconnectedEventArgs e)
=> Dispose();
{
_logger?.TraceInformation($"Closing InProcRemoteHostClient ({e.Reason}) Exception: {e.Exception})");
Dispose();
}

public sealed class ServiceProvider : IServiceProvider
{
Expand Down Expand Up @@ -193,7 +203,21 @@ public event EventHandler<BrokeredServicesChangedEventArgs>? AvailabilityChanged

public ValueTask<T?> GetProxyAsync<T>(ServiceRpcDescriptor descriptor, ServiceActivationOptions options, CancellationToken cancellationToken) where T : class
{
var pipePair = FullDuplexStream.CreatePipePair();
var fullDuplexStreams = FullDuplexStream.CreatePair();

if (descriptor.Moniker == SolutionAssetProvider.ServiceDescriptor.Moniker)
{
//MonitorForDisposal(ref fullDuplexStreams.Item1, descriptor, 1, _services.ServiceProvider.TraceSource);
//MonitorForDisposal(ref fullDuplexStreams.Item2, descriptor, 2, _services.ServiceProvider.TraceSource);
}

var pipePair = (fullDuplexStreams.Item1.UsePipe(), fullDuplexStreams.Item2.UsePipe());

if (((ServiceJsonRpcDescriptor)descriptor).MultiplexingStreamOptions is { } multiplexingStreamOptions && _services.ServiceProvider.TraceSource is { } traceSource)
{
descriptor = (ServiceDescriptor)((ServiceDescriptor)descriptor).WithMultiplexingStream(
new MultiplexingStream.Options(multiplexingStreamOptions) { TraceSource = traceSource });
}

var clientConnection = descriptor
.WithTraceSource(_services.ServiceProvider.TraceSource)
Expand All @@ -214,11 +238,26 @@ public event EventHandler<BrokeredServicesChangedEventArgs>? AvailabilityChanged

// Creates service instance and connects it to the pipe.
// We don't need to store the instance anywhere.
_ = _services.CreateBrokeredService(descriptor, pipePair.Item1, options);
_ = _services.CreateBrokeredService((ServiceDescriptor)descriptor, pipePair.Item1, options);

clientConnection.StartListening();

return new ValueTask<T?>(clientConnection.ConstructRpcClient<T>());

//static void MonitorForDisposal(ref Stream stream, ServiceRpcDescriptor descriptor, int item, TraceSource traceSource)
//{
// if (traceSource is null)
// return;

// var wrappedStream = new MonitoringStream(stream);
// wrappedStream.Disposed +=
// delegate
// {
// traceSource?.TraceInformation($"Disposing pipe {item} for '{descriptor.Moniker}': {new StackTrace()}");
// //Debugger.Launch();
// };
// stream = wrappedStream;
//}
}
}

Expand All @@ -236,7 +275,7 @@ public InProcRemoteServices(HostWorkspaceServices workspaceServices, TraceListen
{
var remoteLogger = new TraceSource("InProcRemoteClient")
{
Switch = { Level = SourceLevels.Verbose },
Switch = { Level = SourceLevels.Information },
};

if (traceListener != null)
Expand Down Expand Up @@ -298,14 +337,20 @@ public void RegisterRemoteBrokeredService(BrokeredServiceBase.IFactory serviceFa
_remoteBrokeredServicesMap.Add(moniker, serviceFactory);
}

public object CreateBrokeredService(ServiceRpcDescriptor descriptor, IDuplexPipe pipe, ServiceActivationOptions options)
public object CreateBrokeredService(ServiceJsonRpcDescriptor descriptor, IDuplexPipe pipe, ServiceActivationOptions options)
{
if (_inProcBrokeredServicesMap.TryGetValue(descriptor.Moniker, out var inProcFactory))
{
// This code is similar to service creation implemented in BrokeredServiceBase.FactoryBase.
// Currently don't support callback creation as we don't have in-proc service with callbacks yet.
Contract.ThrowIfFalse(descriptor.ClientInterface == null);

if (descriptor.MultiplexingStreamOptions is not null && ServiceProvider.TraceSource is { } traceSource)
{
descriptor = ((ServiceDescriptor)descriptor).WithMultiplexingStream(
new MultiplexingStream.Options(descriptor.MultiplexingStreamOptions) { TraceSource = traceSource });
}

var serviceConnection = descriptor.WithTraceSource(ServiceProvider.TraceSource).ConstructRpcConnection(pipe);
var service = inProcFactory();

Expand Down
24 changes: 24 additions & 0 deletions src/Workspaces/Remote/Core/ServiceDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#nullable enable

using System;
using System.Diagnostics;
using System.IO.Pipelines;
using System.Reflection;
using MessagePack;
Expand Down Expand Up @@ -73,6 +74,16 @@ private static MessagePackFormatter ConfigureFormatter(MessagePackFormatter form

protected override JsonRpcConnection CreateConnection(JsonRpc jsonRpc)
{
//if (Moniker == SolutionAssetProvider.ServiceDescriptor.Moniker)
//{
// jsonRpc.Disconnected +=
// delegate
// {
// jsonRpc.TraceSource?.TraceInformation($"Disconnected '{Moniker}': {new StackTrace()}");
// //Debugger.Launch();
// };
//}

jsonRpc.CancelLocallyInvokedMethodsWhenConnectionIsClosed = true;
var connection = base.CreateConnection(jsonRpc);
connection.LocalRpcTargetOptions = s_jsonRpcTargetOptions;
Expand All @@ -99,6 +110,19 @@ public override ServiceRpcDescriptor WithMultiplexingStream(MultiplexingStream?
return result;
}

public new ServiceDescriptor WithMultiplexingStream(MultiplexingStream.Options multiplexingStreamOptions)
{
var baseResult = base.WithMultiplexingStream(multiplexingStreamOptions);
if (baseResult is ServiceDescriptor serviceDescriptor)
return serviceDescriptor;

// Work around incorrect implementation in 16.8 Preview 2
var result = (ServiceDescriptor)WithMultiplexingStream((MultiplexingStream?)null);
result = (ServiceDescriptor)result.Clone();
typeof(ServiceJsonRpcDescriptor).GetProperty(nameof(MultiplexingStreamOptions))!.SetValue(result, value: multiplexingStreamOptions?.GetFrozenCopy());
return result;
}

internal static class TestAccessor
{
public static MessagePackSerializerOptions Options => s_options;
Expand Down
2 changes: 1 addition & 1 deletion src/Workspaces/Remote/Core/ServiceDescriptors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ internal static string GetQualifiedServiceName(Type serviceInterface)
return new(serviceInterface, (descriptor32, descriptor64));
}

public static ServiceRpcDescriptor GetServiceDescriptor(Type serviceType, bool isRemoteHost64Bit)
public static ServiceJsonRpcDescriptor GetServiceDescriptor(Type serviceType, bool isRemoteHost64Bit)
{
var (descriptor32, descriptor64) = Descriptors[serviceType];
return isRemoteHost64Bit ? descriptor64 : descriptor32;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ internal TService Create(
{
var descriptor = ServiceDescriptors.GetServiceDescriptor(typeof(TService), isRemoteHost64Bit: IntPtr.Size == 8);
var serviceHubTraceSource = (TraceSource)hostProvidedServices.GetService(typeof(TraceSource));

if (descriptor.MultiplexingStreamOptions is not null && serviceHubTraceSource is not null)
{
descriptor = ((ServiceDescriptor)descriptor).WithMultiplexingStream(
new MultiplexingStream.Options(descriptor.MultiplexingStreamOptions) { TraceSource = serviceHubTraceSource });
}

var serverConnection = descriptor.WithTraceSource(serviceHubTraceSource).ConstructRpcConnection(pipe);

var args = new ServiceConstructionArguments(hostProvidedServices, serviceBroker);
Expand Down

0 comments on commit bea58be

Please sign in to comment.