From 0da7b96fd6dc2e2c5d3b9e904b518ef9466343fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Tue, 15 Oct 2019 00:01:13 +0300 Subject: [PATCH 1/2] Adds ILoggingBuilder extension for LanguageServer logging. --- sample/SampleServer/Program.cs | 13 +++++--- sample/SampleServer/TextDocumentHandler.cs | 3 ++ src/Server/LanguageServer.cs | 31 +++++++------------ src/Server/LanguageServerOptions.cs | 1 - src/Server/LanguageServerOptionsExtensions.cs | 7 ----- .../{ => Logging}/LanguageServerLogger.cs | 6 ++-- .../Logging/LanguageServerLoggerExtensions.cs | 17 ++++++++++ .../LanguageServerLoggerProvider.cs | 8 +++-- .../Logging/LanguageServerLoggerSettings.cs | 9 ++++++ 9 files changed, 55 insertions(+), 40 deletions(-) rename src/Server/{ => Logging}/LanguageServerLogger.cs (89%) create mode 100644 src/Server/Logging/LanguageServerLoggerExtensions.cs rename src/Server/{ => Logging}/LanguageServerLoggerProvider.cs (59%) create mode 100644 src/Server/Logging/LanguageServerLoggerSettings.cs diff --git a/sample/SampleServer/Program.cs b/sample/SampleServer/Program.cs index 6d83b6e92..1a52ff60e 100644 --- a/sample/SampleServer/Program.cs +++ b/sample/SampleServer/Program.cs @@ -19,10 +19,11 @@ static void Main(string[] args) static async Task MainAsync(string[] args) { - // while (!System.Diagnostics.Debugger.IsAttached) - // { + Debugger.Launch(); + //while (!System.Diagnostics.Debugger.IsAttached) + //{ // await Task.Delay(100); - // } + //} Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() @@ -35,8 +36,10 @@ static async Task MainAsync(string[] args) options .WithInput(Console.OpenStandardInput()) .WithOutput(Console.OpenStandardOutput()) - .ConfigureLogging(x => x.AddSerilog()) - .AddDefaultLoggingProvider() + .ConfigureLogging(x => x + .AddSerilog() + .AddLanguageServer(LogLevel.Critical) + .SetMinimumLevel(LogLevel.Trace)) .WithHandler() .WithHandler() .WithHandler() diff --git a/sample/SampleServer/TextDocumentHandler.cs b/sample/SampleServer/TextDocumentHandler.cs index c9bb28941..2c4b32328 100644 --- a/sample/SampleServer/TextDocumentHandler.cs +++ b/sample/SampleServer/TextDocumentHandler.cs @@ -36,6 +36,9 @@ public TextDocumentHandler(ILogger logger, Foo foo) public Task Handle(DidChangeTextDocumentParams notification, CancellationToken token) { + _logger.LogCritical("Critical"); + _logger.LogDebug("Debug"); + _logger.LogTrace("Trace"); _logger.LogInformation("Hello world!"); return Unit.Task; } diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index 21b904c50..09851c8bc 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -26,6 +26,7 @@ using OmniSharp.Extensions.LanguageServer.Server.Pipelines; using ISerializer = OmniSharp.Extensions.LanguageServer.Protocol.Serialization.ISerializer; using System.Reactive.Disposables; +using Microsoft.Extensions.Options; namespace OmniSharp.Extensions.LanguageServer.Server { @@ -106,8 +107,7 @@ public static ILanguageServer PreInit(LanguageServerOptions options) options.TextDocumentIdentifierTypes, options.InitializeDelegates, options.InitializedDelegates, - options.LoggingBuilderAction, - options.AddDefaultLoggingProvider + options.LoggingBuilderAction ); } @@ -127,20 +127,11 @@ internal LanguageServer( IEnumerable textDocumentIdentifierTypes, IEnumerable initializeDelegates, IEnumerable initializedDelegates, - Action loggingBuilderAction, - bool addDefaultLoggingProvider) + Action loggingBuilderAction) { var outputHandler = new OutputHandler(output, serializer); - services.AddLogging(builder => - { - loggingBuilderAction(builder); - - if (addDefaultLoggingProvider) - { - builder.AddProvider(new LanguageServerLoggerProvider(this)); - } - }); + services.AddLogging(builder => loggingBuilderAction(builder)); _reciever = reciever; _serializer = serializer; @@ -248,11 +239,6 @@ internal LanguageServer( public InitializeParams ClientSettings { get; private set; } public InitializeResult ServerSettings { get; private set; } - /// - /// The minimum level for the server's default logger. - /// - public LogLevel MinimumLogLevel { get; set; } - public IServiceProvider Services => _serviceProvider; public IDisposable AddHandler(string method, IJsonRpcHandler handler) @@ -357,9 +343,14 @@ async Task IRequestHandler { ClientSettings = request; - if (request.Trace == InitializeTrace.Verbose && MinimumLogLevel >= LogLevel.Information) + if (request.Trace == InitializeTrace.Verbose) { - MinimumLogLevel = LogLevel.Trace; + var loggerSettings = _serviceProvider.GetService(); + + if (loggerSettings?.MinimumLogLevel >= LogLevel.Information) + { + loggerSettings.MinimumLogLevel = LogLevel.Trace; + } } _clientVersion = request.Capabilities?.GetClientVersion() ?? ClientVersion.Lsp2; diff --git a/src/Server/LanguageServerOptions.cs b/src/Server/LanguageServerOptions.cs index c5a190dc6..8ddaab941 100644 --- a/src/Server/LanguageServerOptions.cs +++ b/src/Server/LanguageServerOptions.cs @@ -33,7 +33,6 @@ public LanguageServerOptions() internal List HandlerTypes { get; set; } = new List(); internal List TextDocumentIdentifierTypes { get; set; } = new List(); internal List HandlerAssemblies { get; set; } = new List(); - internal bool AddDefaultLoggingProvider { get; set; } internal Action LoggingBuilderAction { get; set; } = new Action(_ => { }); internal readonly List InitializeDelegates = new List(); diff --git a/src/Server/LanguageServerOptionsExtensions.cs b/src/Server/LanguageServerOptionsExtensions.cs index 1113fdc9d..c8280c59f 100644 --- a/src/Server/LanguageServerOptionsExtensions.cs +++ b/src/Server/LanguageServerOptionsExtensions.cs @@ -78,13 +78,6 @@ public static LanguageServerOptions WithServices(this LanguageServerOptions opti return options; } - public static LanguageServerOptions AddDefaultLoggingProvider(this LanguageServerOptions options) - { - options.AddDefaultLoggingProvider = true; - return options; - } - - public static LanguageServerOptions OnInitialize(this LanguageServerOptions options, InitializeDelegate @delegate) { options.InitializeDelegates.Add(@delegate); diff --git a/src/Server/LanguageServerLogger.cs b/src/Server/Logging/LanguageServerLogger.cs similarity index 89% rename from src/Server/LanguageServerLogger.cs rename to src/Server/Logging/LanguageServerLogger.cs index 343de6eef..d46be50a3 100644 --- a/src/Server/LanguageServerLogger.cs +++ b/src/Server/Logging/LanguageServerLogger.cs @@ -1,7 +1,5 @@ using System; using Microsoft.Extensions.Logging; -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; @@ -9,10 +7,10 @@ namespace OmniSharp.Extensions.LanguageServer.Server { class LanguageServerLogger : ILogger { - private readonly LanguageServer _responseRouter; + private readonly ILanguageServer _responseRouter; private readonly Func _logLevelGetter; - public LanguageServerLogger(LanguageServer responseRouter, Func logLevelGetter) + public LanguageServerLogger(ILanguageServer responseRouter, Func logLevelGetter) { _logLevelGetter = logLevelGetter; _responseRouter = responseRouter; diff --git a/src/Server/Logging/LanguageServerLoggerExtensions.cs b/src/Server/Logging/LanguageServerLoggerExtensions.cs new file mode 100644 index 000000000..e25b2d446 --- /dev/null +++ b/src/Server/Logging/LanguageServerLoggerExtensions.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace OmniSharp.Extensions.LanguageServer.Server +{ + public static class LanguageServerLoggerExtensions + { + public static ILoggingBuilder AddLanguageServer(this ILoggingBuilder builder, LogLevel minLevel = LogLevel.Information) + { + builder.Services.AddSingleton(_ => new LanguageServerLoggerSettings { MinimumLogLevel = minLevel }); + builder.Services.AddSingleton(); + + return builder; + } + } +} diff --git a/src/Server/LanguageServerLoggerProvider.cs b/src/Server/Logging/LanguageServerLoggerProvider.cs similarity index 59% rename from src/Server/LanguageServerLoggerProvider.cs rename to src/Server/Logging/LanguageServerLoggerProvider.cs index e189e39cd..218b96032 100644 --- a/src/Server/LanguageServerLoggerProvider.cs +++ b/src/Server/Logging/LanguageServerLoggerProvider.cs @@ -5,16 +5,18 @@ namespace OmniSharp.Extensions.LanguageServer.Server { class LanguageServerLoggerProvider : ILoggerProvider { - private readonly LanguageServer _languageServer; + private readonly ILanguageServer _languageServer; + private readonly LanguageServerLoggerSettings _settings; - public LanguageServerLoggerProvider(LanguageServer languageServer) + public LanguageServerLoggerProvider(ILanguageServer languageServer, LanguageServerLoggerSettings settings) { _languageServer = languageServer; + _settings = settings; } public ILogger CreateLogger(string categoryName) { - return new LanguageServerLogger(_languageServer, () => _languageServer.MinimumLogLevel); + return new LanguageServerLogger(_languageServer, () => _settings.MinimumLogLevel); } public void Dispose() diff --git a/src/Server/Logging/LanguageServerLoggerSettings.cs b/src/Server/Logging/LanguageServerLoggerSettings.cs new file mode 100644 index 000000000..9aad71435 --- /dev/null +++ b/src/Server/Logging/LanguageServerLoggerSettings.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Logging; + +namespace OmniSharp.Extensions.LanguageServer.Server +{ + internal class LanguageServerLoggerSettings + { + public LogLevel MinimumLogLevel { get; set; } + } +} From 0721cbfcf4be53b14d91968cd9c0c2329176071f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Sun, 20 Oct 2019 00:59:43 +0300 Subject: [PATCH 2/2] Make loggerfactory react on loglevel changes. --- sample/SampleServer/Program.cs | 6 +- src/Server/LanguageServer.cs | 12 +++- .../LanguageServerLoggerFilterOptions.cs | 61 +++++++++++++++++++ 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/Server/Logging/LanguageServerLoggerFilterOptions.cs diff --git a/sample/SampleServer/Program.cs b/sample/SampleServer/Program.cs index 1a52ff60e..38767285e 100644 --- a/sample/SampleServer/Program.cs +++ b/sample/SampleServer/Program.cs @@ -19,7 +19,7 @@ static void Main(string[] args) static async Task MainAsync(string[] args) { - Debugger.Launch(); + //Debugger.Launch(); //while (!System.Diagnostics.Debugger.IsAttached) //{ // await Task.Delay(100); @@ -38,8 +38,8 @@ static async Task MainAsync(string[] args) .WithOutput(Console.OpenStandardOutput()) .ConfigureLogging(x => x .AddSerilog() - .AddLanguageServer(LogLevel.Critical) - .SetMinimumLevel(LogLevel.Trace)) + .AddLanguageServer(LogLevel.Error) + .SetMinimumLevel(LogLevel.Error)) .WithHandler() .WithHandler() .WithHandler() diff --git a/src/Server/LanguageServer.cs b/src/Server/LanguageServer.cs index 09851c8bc..e67798a1f 100644 --- a/src/Server/LanguageServer.cs +++ b/src/Server/LanguageServer.cs @@ -27,6 +27,7 @@ using ISerializer = OmniSharp.Extensions.LanguageServer.Protocol.Serialization.ISerializer; using System.Reactive.Disposables; using Microsoft.Extensions.Options; +using OmniSharp.Extensions.LanguageServer.Server.Logging; namespace OmniSharp.Extensions.LanguageServer.Server { @@ -132,6 +133,7 @@ internal LanguageServer( var outputHandler = new OutputHandler(output, serializer); services.AddLogging(builder => loggingBuilderAction(builder)); + services.AddSingleton, LanguageServerLoggerFilterOptions>(); _reciever = reciever; _serializer = serializer; @@ -347,10 +349,18 @@ async Task IRequestHandler { var loggerSettings = _serviceProvider.GetService(); - if (loggerSettings?.MinimumLogLevel >= LogLevel.Information) + if (loggerSettings?.MinimumLogLevel <= LogLevel.Information) { loggerSettings.MinimumLogLevel = LogLevel.Trace; } + + var optionsMonitor = _serviceProvider.GetService>() as LanguageServerLoggerFilterOptions; + + if (optionsMonitor?.CurrentValue.MinLevel <= LogLevel.Information) + { + optionsMonitor.CurrentValue.MinLevel = LogLevel.Trace; + optionsMonitor.Set(optionsMonitor.CurrentValue); + } } _clientVersion = request.Capabilities?.GetClientVersion() ?? ClientVersion.Lsp2; diff --git a/src/Server/Logging/LanguageServerLoggerFilterOptions.cs b/src/Server/Logging/LanguageServerLoggerFilterOptions.cs new file mode 100644 index 000000000..141d8227d --- /dev/null +++ b/src/Server/Logging/LanguageServerLoggerFilterOptions.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace OmniSharp.Extensions.LanguageServer.Server.Logging +{ + internal class LanguageServerLoggerFilterOptions : IOptionsMonitor, IDisposable + { + private readonly List _registrations = new List(); + private event Action _onChange; + + public LanguageServerLoggerFilterOptions(IOptions options) + { + CurrentValue = options.Value; + } + + public LoggerFilterOptions CurrentValue { get; private set; } + + public LoggerFilterOptions Get(string _) => CurrentValue; + + public IDisposable OnChange(Action listener) + { + var disposable = new ChangeTrackerDisposable(this, listener); + _onChange += disposable.OnChange; + return disposable; + } + + public void Dispose() + { + foreach (var registration in _registrations) + { + registration.Dispose(); + } + + _registrations.Clear(); + } + + internal void Set(LoggerFilterOptions options) + { + CurrentValue = options; + _onChange?.Invoke(options, Options.DefaultName); + } + + private class ChangeTrackerDisposable : IDisposable + { + private readonly Action _listener; + private readonly LanguageServerLoggerFilterOptions _monitor; + + public ChangeTrackerDisposable(LanguageServerLoggerFilterOptions monitor, Action listener) + { + _listener = listener; + _monitor = monitor; + } + + public void OnChange(LoggerFilterOptions options, string name) => _listener.Invoke(options, name); + + public void Dispose() => _monitor._onChange -= OnChange; + } + } +}