Skip to content

Commit 9134c7d

Browse files
committed
Remove Serilog and adjust factor for HostLogger injection
1 parent 7e2d864 commit 9134c7d

12 files changed

+51
-544
lines changed

.pipelines/PowerShellEditorServices-Official.yml

-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ extends:
132132
**/Nerdbank.Streams.dll;
133133
**/Newtonsoft.Json.dll;
134134
**/OmniSharp.Extensions*.dll;
135-
**/Serilog*.dll;
136135
**/System.Reactive.dll;
137136
- task: ArchiveFiles@2
138137
displayName: Zip signed artifacts

Directory.Packages.props

-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212
<PackageVersion Include="OmniSharp.Extensions.LanguageClient" Version="0.19.9" />
1313
<PackageVersion Include="OmniSharp.Extensions.LanguageServer" Version="0.19.9" />
1414
<PackageVersion Include="PowerShellStandard.Library" Version="5.1.1" />
15-
<PackageVersion Include="Serilog" Version="4.0.0" />
16-
<PackageVersion Include="Serilog.Extensions.Logging" Version="8.0.0" />
17-
<PackageVersion Include="Serilog.Sinks.Async" Version="2.0.0" />
18-
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
1915
<PackageVersion Include="System.IO.Pipes.AccessControl" Version="5.0.0" />
2016
<PackageVersion Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" />
2117
<PackageVersion Include="System.Security.Principal" Version="4.3.0" />

NOTICE.txt

-427
Large diffs are not rendered by default.

src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs

-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ protected override void BeginProcessing()
219219
protected override void EndProcessing()
220220
{
221221
_logger.Log(PsesLogLevel.Diagnostic, "Beginning EndProcessing block");
222-
223222
try
224223
{
225224
// First try to remove PSReadLine to decomplicate startup

src/PowerShellEditorServices.Hosting/Configuration/HostLogger.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ namespace Microsoft.PowerShell.EditorServices.Hosting
1515
/// User-facing log level for editor services configuration.
1616
/// </summary>
1717
/// <remarks>
18-
/// The underlying values of this enum attempt to align to both
19-
/// <see cref="Microsoft.Extensions.Logging.LogLevel" /> and
20-
/// <see cref="Serilog.Events.LogEventLevel" />.
18+
/// The underlying values of this enum attempt to align to
19+
/// <see cref="Microsoft.Extensions.Logging.LogLevel" />
2120
/// </remarks>
2221
public enum PsesLogLevel
2322
{

src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public EditorServicesRunner(
4242
_config = config;
4343
_sessionFileWriter = sessionFileWriter;
4444
// NOTE: This factory helps to isolate `Microsoft.Extensions.Logging/DependencyInjection`.
45-
_serverFactory = EditorServicesServerFactory.Create(_config.LogPath, (int)_config.LogLevel, logger);
45+
_serverFactory = new(logger);
4646
_alreadySubscribedDebug = false;
4747
_loggersToUnsubscribe = loggersToUnsubscribe;
4848
}

src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs

+16-77
Original file line numberDiff line numberDiff line change
@@ -2,81 +2,31 @@
22
// Licensed under the MIT License.
33

44
using System;
5-
using System.Diagnostics;
65
using System.IO;
76
using Microsoft.Extensions.DependencyInjection;
87
using Microsoft.Extensions.Logging;
9-
using Microsoft.PowerShell.EditorServices.Logging;
108
using Microsoft.PowerShell.EditorServices.Server;
11-
using Serilog;
12-
using Serilog.Events;
139
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
1410
using Microsoft.PowerShell.EditorServices.Services.Extension;
11+
using OmniSharp.Extensions.LanguageServer.Server;
1512

16-
#if DEBUG
17-
using Serilog.Debugging;
18-
#endif
13+
// The HostLogger type isn't directly referenced from this assembly, however it uses a common IObservable interface and this alias helps make it more clear the purpose. We can use Microsoft.Extensions.Logging from this point because the ALC should be loaded, but we need to only expose the IObservable to the Hosting assembly so it doesn't try to load MEL before the ALC is ready.
14+
using HostLogger = System.IObservable<(int logLevel, string message)>;
1915

2016
namespace Microsoft.PowerShell.EditorServices.Hosting
2117
{
2218
/// <summary>
23-
/// Factory class for hiding dependencies of Editor Services.
19+
/// Factory for creating the LSP server and debug server instances.
2420
/// </summary>
25-
/// <remarks>
26-
/// Dependency injection and logging are wrapped by factory methods on this class so that the
27-
/// host assembly can construct the LSP and debug servers without directly depending on <see
28-
/// cref="Microsoft.Extensions.Logging"/> and <see
29-
/// cref="Microsoft.Extensions.DependencyInjection"/>.
30-
/// </remarks>
3121
internal sealed class EditorServicesServerFactory : IDisposable
3222
{
23+
private readonly HostLogger _hostLogger;
24+
3325
/// <summary>
34-
/// Create a new Editor Services factory. This method will instantiate logging.
26+
/// Creates a loggerfactory for this instance
3527
/// </summary>
36-
/// <remarks>
37-
/// <para>
38-
/// This can only be called once because it sets global state (the logger) and that call is
39-
/// in <see cref="Hosting.EditorServicesRunner" />.
40-
/// </para>
41-
/// <para>
42-
/// TODO: Why is this a static function wrapping a constructor instead of just a
43-
/// constructor? In the end it returns an instance (albeit a "singleton").
44-
/// </para>
45-
/// </remarks>
46-
/// <param name="logDirectoryPath">The path of the log file to use.</param>
47-
/// <param name="minimumLogLevel">The minimum log level to use.</param>
48-
/// <param name="hostLogger">The host logger?</param>
49-
public static EditorServicesServerFactory Create(string logDirectoryPath, int minimumLogLevel, IObservable<(int logLevel, string message)> hostLogger)
50-
{
51-
// NOTE: Ignore the suggestion to use Environment.ProcessId as it doesn't work for
52-
// .NET 4.6.2 (for Windows PowerShell), and this won't be caught in CI.
53-
int currentPID = Process.GetCurrentProcess().Id;
54-
string logPath = Path.Combine(logDirectoryPath, $"PowerShellEditorServices-{currentPID}.log");
55-
Log.Logger = new LoggerConfiguration()
56-
.Enrich.FromLogContext()
57-
.WriteTo.Async(config => config.File(logPath))
58-
.MinimumLevel.Is((LogEventLevel)minimumLogLevel)
59-
.CreateLogger();
60-
61-
#if DEBUG
62-
SelfLog.Enable(msg => Debug.WriteLine(msg));
63-
#endif
64-
65-
LoggerFactory loggerFactory = new();
66-
loggerFactory.AddSerilog();
67-
68-
// Hook up logging from the host so that its recorded in the log file
69-
hostLogger.Subscribe(new HostLoggerAdapter(loggerFactory));
70-
71-
return new EditorServicesServerFactory(loggerFactory);
72-
}
73-
74-
// TODO: Can we somehow refactor this member so the language and debug servers can be
75-
// instantiated using their constructors instead of tying them to this factory with `Create`
76-
// methods?
77-
private readonly ILoggerFactory _loggerFactory;
78-
79-
private EditorServicesServerFactory(ILoggerFactory loggerFactory) => _loggerFactory = loggerFactory;
28+
/// <param name="hostLogger">The hostLogger that will be provided to the language services for logging handoff</param>
29+
internal EditorServicesServerFactory(HostLogger hostLogger) => _hostLogger = hostLogger;
8030

8131
/// <summary>
8232
/// Create the LSP server.
@@ -92,7 +42,7 @@ public static EditorServicesServerFactory Create(string logDirectoryPath, int mi
9242
public PsesLanguageServer CreateLanguageServer(
9343
Stream inputStream,
9444
Stream outputStream,
95-
HostStartupInfo hostStartupInfo) => new(_loggerFactory, inputStream, outputStream, hostStartupInfo);
45+
HostStartupInfo hostStartupInfo) => new(_hostLogger, inputStream, outputStream, hostStartupInfo);
9646

9747
/// <summary>
9848
/// Create the debug server given a language server instance.
@@ -110,7 +60,7 @@ public PsesDebugServer CreateDebugServerWithLanguageServer(
11060
PsesLanguageServer languageServer)
11161
{
11262
return new PsesDebugServer(
113-
_loggerFactory,
63+
_hostLogger,
11464
inputStream,
11565
outputStream,
11666
languageServer.LanguageServer.Services);
@@ -132,7 +82,7 @@ public PsesDebugServer RecreateDebugServer(
13282
PsesDebugServer debugServer)
13383
{
13484
return new PsesDebugServer(
135-
_loggerFactory,
85+
_hostLogger,
13686
inputStream,
13787
outputStream,
13888
debugServer.ServiceProvider);
@@ -153,7 +103,7 @@ public PsesDebugServer CreateDebugServerForTempSession(
153103
ServiceProvider serviceProvider = new ServiceCollection()
154104
.AddLogging(builder => builder
155105
.ClearProviders()
156-
.AddSerilog()
106+
.AddLanguageProtocolLogging()
157107
.SetMinimumLevel(LogLevel.Trace)) // TODO: Why randomly set to trace?
158108
.AddSingleton<ILanguageServerFacade>(_ => null)
159109
// TODO: Why add these for a debug server?!
@@ -171,25 +121,14 @@ public PsesDebugServer CreateDebugServerForTempSession(
171121
serviceProvider.GetService<ExtensionService>();
172122

173123
return new PsesDebugServer(
174-
_loggerFactory,
124+
_hostLogger,
175125
inputStream,
176126
outputStream,
177127
serviceProvider,
178128
isTemp: true);
179129
}
180130

181-
/// <summary>
182-
/// TODO: This class probably should not be <see cref="IDisposable"/> as the primary
183-
/// intention of that interface is to provide cleanup of unmanaged resources, which the
184-
/// logger certainly is not. Nor is this class used with a <see langword="using"/>. Instead,
185-
/// this class should call <see cref="Log.CloseAndFlush()"/> in a finalizer. This
186-
/// could potentially even be done with <see
187-
/// cref="SerilogLoggerFactoryExtensions.AddSerilog"</> by passing <c>dispose=true</c>.
188-
/// </summary>
189-
public void Dispose()
190-
{
191-
Log.CloseAndFlush();
192-
_loggerFactory.Dispose();
193-
}
131+
// TODO: Clean up host logger? Shouldn't matter since we start a new process after shutdown.
132+
public void Dispose() { }
194133
}
195134
}

src/PowerShellEditorServices/Hosting/HostStartupInfo.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,8 @@ public sealed class HostStartupInfo
107107
/// The minimum log level of log events to be logged.
108108
/// </summary>
109109
/// <remarks>
110-
/// This is cast to all of <see cref="Hosting.PsesLogLevel"/>, <see
111-
/// cref="Microsoft.Extensions.Logging.LogLevel"/>, and <see
112-
/// cref="Serilog.Events.LogEventLevel"/>, hence it is an <c>int</c>.
110+
/// This primitive maps to <see cref="Hosting.PsesLogLevel"/> and <see
111+
/// cref="Microsoft.Extensions.Logging.LogLevel"/>
113112
/// </remarks>
114113
public int LogLevel { get; }
115114

src/PowerShellEditorServices/Logging/HostLoggerAdapter.cs

+3-10
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,16 @@ namespace Microsoft.PowerShell.EditorServices.Logging
99
/// <summary>
1010
/// Adapter class to allow logging events sent by the host to be recorded by PSES' logging infrastructure.
1111
/// </summary>
12-
internal class HostLoggerAdapter : IObserver<(int logLevel, string message)>
12+
internal class HostLoggerAdapter(ILogger logger) : IObserver<(int logLevel, string message)>
1313
{
14-
private readonly ILogger _logger;
14+
public void OnError(Exception error) => logger.LogError(error, "Error in host logger");
1515

16-
/// <summary>
17-
/// Create a new host logger adapter.
18-
/// </summary>
19-
/// <param name="loggerFactory">Factory to create logger instances with.</param>
20-
public HostLoggerAdapter(ILoggerFactory loggerFactory) => _logger = loggerFactory.CreateLogger("HostLogs");
16+
public void OnNext((int logLevel, string message) value) => logger.Log((LogLevel)value.logLevel, value.message);
2117

2218
public void OnCompleted()
2319
{
2420
// Nothing to do; we simply don't send more log messages
2521
}
2622

27-
public void OnError(Exception error) => _logger.LogError(error, "Error in host logger");
28-
29-
public void OnNext((int logLevel, string message) value) => _logger.Log((LogLevel)value.logLevel, value.message);
3023
}
3124
}

src/PowerShellEditorServices/PowerShellEditorServices.csproj

-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@
3636
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" />
3737
<PackageReference Include="Microsoft.Extensions.Logging" />
3838
<PackageReference Include="PowerShellStandard.Library" />
39-
<PackageReference Include="Serilog" />
40-
<PackageReference Include="Serilog.Extensions.Logging" />
41-
<PackageReference Include="Serilog.Sinks.Async" />
42-
<PackageReference Include="Serilog.Sinks.File" />
4339
<PackageReference Include="System.IO.Pipes.AccessControl" />
4440
<PackageReference Include="System.Security.Principal" />
4541
<PackageReference Include="System.Security.Principal.Windows" />

src/PowerShellEditorServices/Server/PsesDebugServer.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
using System.IO;
66
using System.Threading.Tasks;
77
using Microsoft.Extensions.DependencyInjection;
8-
using Microsoft.Extensions.Logging;
98
using Microsoft.PowerShell.EditorServices.Handlers;
109
using Microsoft.PowerShell.EditorServices.Services;
1110
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host;
1211
using OmniSharp.Extensions.DebugAdapter.Server;
1312
using OmniSharp.Extensions.LanguageServer.Server;
1413

14+
// See EditorServicesServerFactory.cs for the explanation of this alias.
15+
using HostLogger = System.IObservable<(int logLevel, string message)>;
16+
1517
namespace Microsoft.PowerShell.EditorServices.Server
1618
{
1719
/// <summary>
@@ -26,16 +28,17 @@ internal class PsesDebugServer : IDisposable
2628
private PsesInternalHost _psesHost;
2729
private bool _startedPses;
2830
private readonly bool _isTemp;
29-
protected readonly ILoggerFactory _loggerFactory;
31+
// FIXME: This was never actually used in the debug server. Since we never have a debug server without an LSP, we could probably remove this and either reuse the MEL from the LSP, or create a new one here. It is probably best to only use this for exceptions that we can't reasonably send via the DAP protocol, which should only be anything before the initialize request.
32+
protected readonly HostLogger _hostLogger;
3033

3134
public PsesDebugServer(
32-
ILoggerFactory factory,
35+
HostLogger hostLogger,
3336
Stream inputStream,
3437
Stream outputStream,
3538
IServiceProvider serviceProvider,
3639
bool isTemp = false)
3740
{
38-
_loggerFactory = factory;
41+
_hostLogger = hostLogger;
3942
_inputStream = inputStream;
4043
_outputStream = outputStream;
4144
ServiceProvider = serviceProvider;
@@ -130,7 +133,6 @@ public void Dispose()
130133
_debugAdapterServer?.Dispose();
131134
_inputStream.Dispose();
132135
_outputStream.Dispose();
133-
_loggerFactory.Dispose();
134136
_serverStopped.SetResult(true);
135137
// TODO: If the debugger has stopped, should we clear the breakpoints?
136138
}

0 commit comments

Comments
 (0)