Skip to content

Commit e3ab388

Browse files
Merge pull request #187 from OmniSharp/feature/enchance-logging
Adds ILoggingBuilder extension for LanguageServer logging.
2 parents 3dd94c7 + 0721cbf commit e3ab388

10 files changed

+126
-40
lines changed

sample/SampleServer/Program.cs

+8-5
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ static void Main(string[] args)
1919

2020
static async Task MainAsync(string[] args)
2121
{
22-
// while (!System.Diagnostics.Debugger.IsAttached)
23-
// {
22+
//Debugger.Launch();
23+
//while (!System.Diagnostics.Debugger.IsAttached)
24+
//{
2425
// await Task.Delay(100);
25-
// }
26+
//}
2627

2728
Log.Logger = new LoggerConfiguration()
2829
.Enrich.FromLogContext()
@@ -35,8 +36,10 @@ static async Task MainAsync(string[] args)
3536
options
3637
.WithInput(Console.OpenStandardInput())
3738
.WithOutput(Console.OpenStandardOutput())
38-
.ConfigureLogging(x => x.AddSerilog())
39-
.AddDefaultLoggingProvider()
39+
.ConfigureLogging(x => x
40+
.AddSerilog()
41+
.AddLanguageServer(LogLevel.Error)
42+
.SetMinimumLevel(LogLevel.Error))
4043
.WithHandler<TextDocumentHandler>()
4144
.WithHandler<DidChangeWatchedFilesHandler>()
4245
.WithHandler<FoldingRangeHandler>()

sample/SampleServer/TextDocumentHandler.cs

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ public TextDocumentHandler(ILogger<TextDocumentHandler> logger, Foo foo)
3636

3737
public Task<Unit> Handle(DidChangeTextDocumentParams notification, CancellationToken token)
3838
{
39+
_logger.LogCritical("Critical");
40+
_logger.LogDebug("Debug");
41+
_logger.LogTrace("Trace");
3942
_logger.LogInformation("Hello world!");
4043
return Unit.Task;
4144
}

src/Server/LanguageServer.cs

+21-20
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
using OmniSharp.Extensions.LanguageServer.Server.Pipelines;
2727
using ISerializer = OmniSharp.Extensions.LanguageServer.Protocol.Serialization.ISerializer;
2828
using System.Reactive.Disposables;
29+
using Microsoft.Extensions.Options;
30+
using OmniSharp.Extensions.LanguageServer.Server.Logging;
2931

3032
namespace OmniSharp.Extensions.LanguageServer.Server
3133
{
@@ -106,8 +108,7 @@ public static ILanguageServer PreInit(LanguageServerOptions options)
106108
options.TextDocumentIdentifierTypes,
107109
options.InitializeDelegates,
108110
options.InitializedDelegates,
109-
options.LoggingBuilderAction,
110-
options.AddDefaultLoggingProvider
111+
options.LoggingBuilderAction
111112
);
112113
}
113114

@@ -127,20 +128,12 @@ internal LanguageServer(
127128
IEnumerable<Type> textDocumentIdentifierTypes,
128129
IEnumerable<InitializeDelegate> initializeDelegates,
129130
IEnumerable<InitializedDelegate> initializedDelegates,
130-
Action<ILoggingBuilder> loggingBuilderAction,
131-
bool addDefaultLoggingProvider)
131+
Action<ILoggingBuilder> loggingBuilderAction)
132132
{
133133
var outputHandler = new OutputHandler(output, serializer);
134134

135-
services.AddLogging(builder =>
136-
{
137-
loggingBuilderAction(builder);
138-
139-
if (addDefaultLoggingProvider)
140-
{
141-
builder.AddProvider(new LanguageServerLoggerProvider(this));
142-
}
143-
});
135+
services.AddLogging(builder => loggingBuilderAction(builder));
136+
services.AddSingleton<IOptionsMonitor<LoggerFilterOptions>, LanguageServerLoggerFilterOptions>();
144137

145138
_reciever = reciever;
146139
_serializer = serializer;
@@ -248,11 +241,6 @@ internal LanguageServer(
248241
public InitializeParams ClientSettings { get; private set; }
249242
public InitializeResult ServerSettings { get; private set; }
250243

251-
/// <summary>
252-
/// The minimum level for the server's default logger.
253-
/// </summary>
254-
public LogLevel MinimumLogLevel { get; set; }
255-
256244
public IServiceProvider Services => _serviceProvider;
257245

258246
public IDisposable AddHandler(string method, IJsonRpcHandler handler)
@@ -357,9 +345,22 @@ async Task<InitializeResult> IRequestHandler<InitializeParams, InitializeResult>
357345
{
358346
ClientSettings = request;
359347

360-
if (request.Trace == InitializeTrace.Verbose && MinimumLogLevel >= LogLevel.Information)
348+
if (request.Trace == InitializeTrace.Verbose)
361349
{
362-
MinimumLogLevel = LogLevel.Trace;
350+
var loggerSettings = _serviceProvider.GetService<LanguageServerLoggerSettings>();
351+
352+
if (loggerSettings?.MinimumLogLevel <= LogLevel.Information)
353+
{
354+
loggerSettings.MinimumLogLevel = LogLevel.Trace;
355+
}
356+
357+
var optionsMonitor = _serviceProvider.GetService<IOptionsMonitor<LoggerFilterOptions>>() as LanguageServerLoggerFilterOptions;
358+
359+
if (optionsMonitor?.CurrentValue.MinLevel <= LogLevel.Information)
360+
{
361+
optionsMonitor.CurrentValue.MinLevel = LogLevel.Trace;
362+
optionsMonitor.Set(optionsMonitor.CurrentValue);
363+
}
363364
}
364365

365366
_clientVersion = request.Capabilities?.GetClientVersion() ?? ClientVersion.Lsp2;

src/Server/LanguageServerOptions.cs

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public LanguageServerOptions()
3333
internal List<Type> HandlerTypes { get; set; } = new List<Type>();
3434
internal List<Type> TextDocumentIdentifierTypes { get; set; } = new List<Type>();
3535
internal List<Assembly> HandlerAssemblies { get; set; } = new List<Assembly>();
36-
internal bool AddDefaultLoggingProvider { get; set; }
3736
internal Action<ILoggingBuilder> LoggingBuilderAction { get; set; } = new Action<ILoggingBuilder>(_ => { });
3837

3938
internal readonly List<InitializeDelegate> InitializeDelegates = new List<InitializeDelegate>();

src/Server/LanguageServerOptionsExtensions.cs

-7
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,6 @@ public static LanguageServerOptions WithServices(this LanguageServerOptions opti
7878
return options;
7979
}
8080

81-
public static LanguageServerOptions AddDefaultLoggingProvider(this LanguageServerOptions options)
82-
{
83-
options.AddDefaultLoggingProvider = true;
84-
return options;
85-
}
86-
87-
8881
public static LanguageServerOptions OnInitialize(this LanguageServerOptions options, InitializeDelegate @delegate)
8982
{
9083
options.InitializeDelegates.Add(@delegate);

src/Server/LanguageServerLogger.cs renamed to src/Server/Logging/LanguageServerLogger.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
using System;
22
using Microsoft.Extensions.Logging;
3-
using OmniSharp.Extensions.JsonRpc;
4-
using OmniSharp.Extensions.LanguageServer.Protocol;
53
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
64
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
75

86
namespace OmniSharp.Extensions.LanguageServer.Server
97
{
108
class LanguageServerLogger : ILogger
119
{
12-
private readonly LanguageServer _responseRouter;
10+
private readonly ILanguageServer _responseRouter;
1311
private readonly Func<LogLevel> _logLevelGetter;
1412

15-
public LanguageServerLogger(LanguageServer responseRouter, Func<LogLevel> logLevelGetter)
13+
public LanguageServerLogger(ILanguageServer responseRouter, Func<LogLevel> logLevelGetter)
1614
{
1715
_logLevelGetter = logLevelGetter;
1816
_responseRouter = responseRouter;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
using Microsoft.Extensions.Options;
4+
5+
namespace OmniSharp.Extensions.LanguageServer.Server
6+
{
7+
public static class LanguageServerLoggerExtensions
8+
{
9+
public static ILoggingBuilder AddLanguageServer(this ILoggingBuilder builder, LogLevel minLevel = LogLevel.Information)
10+
{
11+
builder.Services.AddSingleton<LanguageServerLoggerSettings>(_ => new LanguageServerLoggerSettings { MinimumLogLevel = minLevel });
12+
builder.Services.AddSingleton<ILoggerProvider, LanguageServerLoggerProvider>();
13+
14+
return builder;
15+
}
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.Extensions.Logging;
4+
using Microsoft.Extensions.Options;
5+
6+
namespace OmniSharp.Extensions.LanguageServer.Server.Logging
7+
{
8+
internal class LanguageServerLoggerFilterOptions : IOptionsMonitor<LoggerFilterOptions>, IDisposable
9+
{
10+
private readonly List<IDisposable> _registrations = new List<IDisposable>();
11+
private event Action<LoggerFilterOptions, string> _onChange;
12+
13+
public LanguageServerLoggerFilterOptions(IOptions<LoggerFilterOptions> options)
14+
{
15+
CurrentValue = options.Value;
16+
}
17+
18+
public LoggerFilterOptions CurrentValue { get; private set; }
19+
20+
public LoggerFilterOptions Get(string _) => CurrentValue;
21+
22+
public IDisposable OnChange(Action<LoggerFilterOptions, string> listener)
23+
{
24+
var disposable = new ChangeTrackerDisposable(this, listener);
25+
_onChange += disposable.OnChange;
26+
return disposable;
27+
}
28+
29+
public void Dispose()
30+
{
31+
foreach (var registration in _registrations)
32+
{
33+
registration.Dispose();
34+
}
35+
36+
_registrations.Clear();
37+
}
38+
39+
internal void Set(LoggerFilterOptions options)
40+
{
41+
CurrentValue = options;
42+
_onChange?.Invoke(options, Options.DefaultName);
43+
}
44+
45+
private class ChangeTrackerDisposable : IDisposable
46+
{
47+
private readonly Action<LoggerFilterOptions, string> _listener;
48+
private readonly LanguageServerLoggerFilterOptions _monitor;
49+
50+
public ChangeTrackerDisposable(LanguageServerLoggerFilterOptions monitor, Action<LoggerFilterOptions, string> listener)
51+
{
52+
_listener = listener;
53+
_monitor = monitor;
54+
}
55+
56+
public void OnChange(LoggerFilterOptions options, string name) => _listener.Invoke(options, name);
57+
58+
public void Dispose() => _monitor._onChange -= OnChange;
59+
}
60+
}
61+
}

src/Server/LanguageServerLoggerProvider.cs renamed to src/Server/Logging/LanguageServerLoggerProvider.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@ namespace OmniSharp.Extensions.LanguageServer.Server
55
{
66
class LanguageServerLoggerProvider : ILoggerProvider
77
{
8-
private readonly LanguageServer _languageServer;
8+
private readonly ILanguageServer _languageServer;
9+
private readonly LanguageServerLoggerSettings _settings;
910

10-
public LanguageServerLoggerProvider(LanguageServer languageServer)
11+
public LanguageServerLoggerProvider(ILanguageServer languageServer, LanguageServerLoggerSettings settings)
1112
{
1213
_languageServer = languageServer;
14+
_settings = settings;
1315
}
1416

1517
public ILogger CreateLogger(string categoryName)
1618
{
17-
return new LanguageServerLogger(_languageServer, () => _languageServer.MinimumLogLevel);
19+
return new LanguageServerLogger(_languageServer, () => _settings.MinimumLogLevel);
1820
}
1921

2022
public void Dispose()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
namespace OmniSharp.Extensions.LanguageServer.Server
4+
{
5+
internal class LanguageServerLoggerSettings
6+
{
7+
public LogLevel MinimumLogLevel { get; set; }
8+
}
9+
}

0 commit comments

Comments
 (0)