From a6cabcb4482545f1dbd02d5fe69cea4cb6b3833a Mon Sep 17 00:00:00 2001 From: Matt Cole Date: Fri, 10 Sep 2021 11:28:39 +0100 Subject: [PATCH 1/2] Add support for reloading options --- src/Gelf.Extensions.Logging/Debouncer.cs | 30 +++++ src/Gelf.Extensions.Logging/GelfLogger.cs | 14 +-- .../GelfLoggerOptionsSetup.cs | 2 +- .../GelfLoggerProvider.cs | 78 ++++++++---- .../GelfMessageProcessor.cs | 7 +- .../LoggerFactoryExtensions.cs | 40 +++++- .../LoggingBuilderExtensions.cs | 11 +- .../LoggingBuilderExtensionsTests.cs | 117 +++--------------- 8 files changed, 155 insertions(+), 144 deletions(-) create mode 100644 src/Gelf.Extensions.Logging/Debouncer.cs diff --git a/src/Gelf.Extensions.Logging/Debouncer.cs b/src/Gelf.Extensions.Logging/Debouncer.cs new file mode 100644 index 0000000..4271e71 --- /dev/null +++ b/src/Gelf.Extensions.Logging/Debouncer.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Gelf.Extensions.Logging +{ + internal static class Debouncer + { + public static Action Debounce(Action action, TimeSpan delay) + { + CancellationTokenSource? cts = null; + + return parameter => + { + try + { + cts?.Cancel(); + } + catch (ObjectDisposedException) + { + } + + var newCts = cts = new CancellationTokenSource(); + Task.Delay(delay, newCts.Token) + .ContinueWith(_ => action(parameter), newCts.Token) + .ContinueWith(_ => newCts.Dispose(), newCts.Token); + }; + } + } +} diff --git a/src/Gelf.Extensions.Logging/GelfLogger.cs b/src/Gelf.Extensions.Logging/GelfLogger.cs index 944d11b..f082ac4 100644 --- a/src/Gelf.Extensions.Logging/GelfLogger.cs +++ b/src/Gelf.Extensions.Logging/GelfLogger.cs @@ -23,16 +23,16 @@ public class GelfLogger : ILogger private readonly string _name; private readonly GelfMessageProcessor _messageProcessor; - private readonly GelfLoggerOptions _options; public GelfLogger(string name, GelfMessageProcessor messageProcessor, GelfLoggerOptions options) { _name = name; _messageProcessor = messageProcessor; - _options = options; + Options = options; } internal IExternalScopeProvider? ScopeProvider { get; set; } + internal GelfLoggerOptions Options { get; set; } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) @@ -45,7 +45,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, var message = new GelfMessage { ShortMessage = formatter(state, exception), - Host = _options.LogSource, + Host = Options.LogSource, Logger = _name, Exception = exception?.ToString(), Level = GetLevel(logLevel), @@ -93,7 +93,7 @@ private static double GetTimestamp() private IEnumerable> GetAdditionalFields( LogLevel logLevel, EventId eventId, TState state, Exception? exception) { - var additionalFields = _options.AdditionalFields + var additionalFields = Options.AdditionalFields .Concat(GetFactoryAdditionalFields(logLevel, eventId, exception)) .Concat(GetScopeAdditionalFields()) .Concat(GetStateAdditionalFields(state)); @@ -111,7 +111,7 @@ private IEnumerable> GetAdditionalFields( Debug.Fail($"GELF message has additional field with invalid key \"{field.Key}\"."); } } - else if (_options.IncludeMessageTemplates) + else if (Options.IncludeMessageTemplates) { yield return new KeyValuePair("message_template", field.Value); } @@ -121,13 +121,13 @@ private IEnumerable> GetAdditionalFields( private IEnumerable> GetFactoryAdditionalFields( LogLevel logLevel, EventId eventId, Exception? exception) { - return _options.AdditionalFieldsFactory?.Invoke(logLevel, eventId, exception) ?? + return Options.AdditionalFieldsFactory?.Invoke(logLevel, eventId, exception) ?? Enumerable.Empty>(); } private IEnumerable> GetScopeAdditionalFields() { - if (!_options.IncludeScopes) + if (!Options.IncludeScopes) { return Enumerable.Empty>(); } diff --git a/src/Gelf.Extensions.Logging/GelfLoggerOptionsSetup.cs b/src/Gelf.Extensions.Logging/GelfLoggerOptionsSetup.cs index cf8835a..4d5d3d2 100644 --- a/src/Gelf.Extensions.Logging/GelfLoggerOptionsSetup.cs +++ b/src/Gelf.Extensions.Logging/GelfLoggerOptionsSetup.cs @@ -3,7 +3,7 @@ namespace Gelf.Extensions.Logging { - public class GelfLoggerOptionsSetup : ConfigureFromConfigurationOptions + internal class GelfLoggerOptionsSetup : ConfigureFromConfigurationOptions { public GelfLoggerOptionsSetup(ILoggerProviderConfiguration providerConfiguration) : base(providerConfiguration.Configuration) diff --git a/src/Gelf.Extensions.Logging/GelfLoggerProvider.cs b/src/Gelf.Extensions.Logging/GelfLoggerProvider.cs index 5c62bb9..87d1614 100644 --- a/src/Gelf.Extensions.Logging/GelfLoggerProvider.cs +++ b/src/Gelf.Extensions.Logging/GelfLoggerProvider.cs @@ -8,18 +8,44 @@ namespace Gelf.Extensions.Logging [ProviderAlias("GELF")] public class GelfLoggerProvider : ILoggerProvider, ISupportExternalScope { - private readonly GelfLoggerOptions _options; - private readonly GelfMessageProcessor _messageProcessor; - private readonly IGelfClient _gelfClient; + private readonly IOptionsMonitor _options; private readonly ConcurrentDictionary _loggers; + private readonly IDisposable _optionsReloadToken; + private IGelfClient? _gelfClient; + private GelfMessageProcessor? _messageProcessor; private IExternalScopeProvider? _scopeProvider; - public GelfLoggerProvider(IOptions options) : this(options.Value) + public GelfLoggerProvider(IOptionsMonitor options) { + _options = options; + _loggers = new ConcurrentDictionary(); + + LoadLoggerOptions(options.CurrentValue); + + var onOptionsChanged = Debouncer.Debounce(LoadLoggerOptions, TimeSpan.FromSeconds(1)); + _optionsReloadToken = options.OnChange(onOptionsChanged); + } + + public ILogger CreateLogger(string name) + { + return _loggers.GetOrAdd(name, newName => new GelfLogger( + newName, _messageProcessor!, _options.CurrentValue) + { + ScopeProvider = _scopeProvider + }); } - public GelfLoggerProvider(GelfLoggerOptions options) + public void SetScopeProvider(IExternalScopeProvider scopeProvider) + { + _scopeProvider = scopeProvider; + foreach (var logger in _loggers) + { + logger.Value.ScopeProvider = _scopeProvider; + } + } + + private void LoadLoggerOptions(GelfLoggerOptions options) { if (string.IsNullOrEmpty(options.Host)) { @@ -31,19 +57,25 @@ public GelfLoggerProvider(GelfLoggerOptions options) throw new ArgumentException("GELF log source is required.", nameof(options)); } - _options = options; - _gelfClient = CreateGelfClient(_options); - _messageProcessor = new GelfMessageProcessor(_gelfClient); - _messageProcessor.Start(); - _loggers = new ConcurrentDictionary(); - } + var gelfClient = CreateGelfClient(options); - public ILogger CreateLogger(string name) - { - return _loggers.GetOrAdd(name, newName => new GelfLogger(newName, _messageProcessor, _options) + if (_messageProcessor == null) { - ScopeProvider = _scopeProvider - }); + _messageProcessor = new GelfMessageProcessor(gelfClient); + _messageProcessor.Start(); + } + else + { + _messageProcessor.GelfClient = gelfClient; + _gelfClient?.Dispose(); + } + + _gelfClient = gelfClient; + + foreach (var logger in _loggers) + { + logger.Value.Options = options; + } } private static IGelfClient CreateGelfClient(GelfLoggerOptions options) @@ -59,17 +91,9 @@ private static IGelfClient CreateGelfClient(GelfLoggerOptions options) public void Dispose() { - _messageProcessor.Stop(); - _gelfClient.Dispose(); - } - - public void SetScopeProvider(IExternalScopeProvider scopeProvider) - { - _scopeProvider = scopeProvider; - foreach (var logger in _loggers) - { - logger.Value.ScopeProvider = _scopeProvider; - } + _messageProcessor?.Stop(); + _gelfClient?.Dispose(); + _optionsReloadToken.Dispose(); } } } diff --git a/src/Gelf.Extensions.Logging/GelfMessageProcessor.cs b/src/Gelf.Extensions.Logging/GelfMessageProcessor.cs index 47874aa..d7b3893 100644 --- a/src/Gelf.Extensions.Logging/GelfMessageProcessor.cs +++ b/src/Gelf.Extensions.Logging/GelfMessageProcessor.cs @@ -7,20 +7,21 @@ namespace Gelf.Extensions.Logging { public class GelfMessageProcessor { - private readonly IGelfClient _gelfClient; private readonly BufferBlock _messageBuffer; private Task _processorTask = Task.CompletedTask; public GelfMessageProcessor(IGelfClient gelfClient) { - _gelfClient = gelfClient; + GelfClient = gelfClient; _messageBuffer = new BufferBlock(new DataflowBlockOptions { BoundedCapacity = 10000 }); } + internal IGelfClient GelfClient { get; set; } + public void Start() { _processorTask = Task.Run(StartAsync); @@ -33,7 +34,7 @@ private async Task StartAsync() try { var message = await _messageBuffer.ReceiveAsync(); - await _gelfClient.SendMessageAsync(message); + await GelfClient.SendMessageAsync(message); } catch (InvalidOperationException) { diff --git a/src/Gelf.Extensions.Logging/LoggerFactoryExtensions.cs b/src/Gelf.Extensions.Logging/LoggerFactoryExtensions.cs index d2f4de0..5ed097e 100644 --- a/src/Gelf.Extensions.Logging/LoggerFactoryExtensions.cs +++ b/src/Gelf.Extensions.Logging/LoggerFactoryExtensions.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Logging; +using System; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Gelf.Extensions.Logging { @@ -11,10 +13,44 @@ public static class LoggerFactoryExtensions /// /// /// - public static ILoggerFactory AddGelf(this ILoggerFactory loggerFactory, GelfLoggerOptions options) + public static ILoggerFactory AddGelf( + this ILoggerFactory loggerFactory, IOptionsMonitor options) { loggerFactory.AddProvider(new GelfLoggerProvider(options)); return loggerFactory; } + + /// + /// Adds a to the logger factory with the supplied + /// . + /// + /// + /// + /// + public static ILoggerFactory AddGelf(this ILoggerFactory loggerFactory, GelfLoggerOptions options) + { + return loggerFactory.AddGelf(new OptionsMonitorStub(options)); + } + + private class OptionsMonitorStub : IOptionsMonitor + { + public OptionsMonitorStub(T options) + { + CurrentValue = options; + } + + public T CurrentValue { get; } + + public T Get(string name) => CurrentValue; + + public IDisposable OnChange(Action listener) => new NullDisposable(); + + private class NullDisposable : IDisposable + { + public void Dispose() + { + } + } + } } } diff --git a/src/Gelf.Extensions.Logging/LoggingBuilderExtensions.cs b/src/Gelf.Extensions.Logging/LoggingBuilderExtensions.cs index ae90e37..8485b7d 100644 --- a/src/Gelf.Extensions.Logging/LoggingBuilderExtensions.cs +++ b/src/Gelf.Extensions.Logging/LoggingBuilderExtensions.cs @@ -17,8 +17,15 @@ public static class LoggingBuilderExtensions public static ILoggingBuilder AddGelf(this ILoggingBuilder builder) { builder.AddConfiguration(); - builder.Services.AddSingleton(); - builder.Services.TryAddSingleton, GelfLoggerOptionsSetup>(); + + builder.Services.TryAddEnumerable( + ServiceDescriptor.Singleton()); + builder.Services.TryAddEnumerable( + ServiceDescriptor.Singleton, GelfLoggerOptionsSetup>()); + builder.Services.TryAddEnumerable( + ServiceDescriptor.Singleton< + IOptionsChangeTokenSource, + LoggerProviderOptionsChangeTokenSource>()); return builder; } diff --git a/test/Gelf.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs b/test/Gelf.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs index c25e064..4961734 100644 --- a/test/Gelf.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs +++ b/test/Gelf.Extensions.Logging.Tests/LoggingBuilderExtensionsTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Memory; using Microsoft.Extensions.DependencyInjection; @@ -11,7 +12,7 @@ namespace Gelf.Extensions.Logging.Tests public class LoggingBuilderExtensionsTests { [Fact] - public void Reads_GELF_logger_options_from_logging_configuration_section_by_default() + public void Reads_GELF_logger_options_from_logging_configuration_section() { var configuration = new ConfigurationBuilder().Add(new MemoryConfigurationSource { @@ -19,7 +20,7 @@ public void Reads_GELF_logger_options_from_logging_configuration_section_by_defa { ["Logging:GELF:IncludeScopes"] = "false", ["Logging:GELF:Protocol"] = "HTTP", - ["Logging:GELF:Host"] = "graylog-host-1" + ["Logging:GELF:Host"] = "graylog-host" } }).Build(); @@ -33,83 +34,14 @@ public void Reads_GELF_logger_options_from_logging_configuration_section_by_defa Assert.False(options.Value.IncludeScopes); Assert.Equal(GelfProtocol.Http, options.Value.Protocol); - Assert.Equal("graylog-host-1", options.Value.Host); + Assert.Equal("graylog-host", options.Value.Host); Assert.Equal("post-configured-log-source", options.Value.LogSource); } [Fact] - public void Reads_GELF_logger_options_from_custom_configuration_section() + public void Reads_GELF_logger_options_default_values() { - var configuration = new ConfigurationBuilder().Add(new MemoryConfigurationSource - { - InitialData = new Dictionary - { - ["Logging:GELF:IncludeScopes"] = "true", - ["Logging:GELF:Protocol"] = "HTTP", - ["Logging:GELF:Host"] = "graylog-host-1", - ["Graylog:IncludeScopes"] = "false", - ["Graylog:Protocol"] = "HTTPS", - ["Graylog:Host"] = "graylog-host-2" - } - }).Build(); - - var serviceCollection = new ServiceCollection() - .Configure(configuration.GetSection("Graylog")) - .PostConfigure(o => o.LogSource = "post-configured-log-source") - .AddLogging(loggingBuilder => loggingBuilder - .AddConfiguration(configuration.GetSection("Logging")) - .AddGelf(o => o.LogSource = "post-configured-log-source")); - - using var provider = serviceCollection.BuildServiceProvider(); - var options = provider.GetRequiredService>(); - - Assert.False(options.Value.IncludeScopes); - Assert.Equal(GelfProtocol.Https, options.Value.Protocol); - Assert.Equal("graylog-host-2", options.Value.Host); - Assert.Equal("post-configured-log-source", options.Value.LogSource); - } - - [Fact] - public void Reads_GELF_logger_options_with_default_udpmaxchunksize() - { - var defaultMaxChunkSize = 8192; - - var configuration = new ConfigurationBuilder().Add(new MemoryConfigurationSource - { - InitialData = new Dictionary - { - ["Logging:GELF:IncludeScopes"] = "false", - ["Logging:GELF:Protocol"] = "HTTP", - ["Logging:GELF:Host"] = "graylog-host-1" - } - }).Build(); - - var serviceCollection = new ServiceCollection() - .AddLogging(loggingBuilder => loggingBuilder - .AddConfiguration(configuration.GetSection("Logging")) - .AddGelf()); - - using var provider = serviceCollection.BuildServiceProvider(); - var options = provider.GetRequiredService>(); - - Assert.Equal(options.Value.UdpMaxChunkSize, defaultMaxChunkSize); - } - - [Fact] - public void Reads_GELF_logger_options_with_custom_udpmaxchunksize() - { - var customChunkSize = 1024; - - var configuration = new ConfigurationBuilder().Add(new MemoryConfigurationSource - { - InitialData = new Dictionary - { - ["Logging:GELF:IncludeScopes"] = "false", - ["Logging:GELF:Protocol"] = "HTTP", - ["Logging:GELF:Host"] = "graylog-host-1", - ["Logging:GELF:UdpMaxChunkSize"] = customChunkSize.ToString() - } - }).Build(); + var configuration = new ConfigurationBuilder().Build(); var serviceCollection = new ServiceCollection() .AddLogging(loggingBuilder => loggingBuilder @@ -119,33 +51,14 @@ public void Reads_GELF_logger_options_with_custom_udpmaxchunksize() using var provider = serviceCollection.BuildServiceProvider(); var options = provider.GetRequiredService>(); - Assert.Equal(options.Value.UdpMaxChunkSize, customChunkSize); - } - - [Fact] - public void Reads_GELF_logger_options_with_custom_udpmaxchunksize_post_configuration() - { - var customChunkSize = 1024; - - var configuration = new ConfigurationBuilder().Add(new MemoryConfigurationSource - { - InitialData = new Dictionary - { - ["Logging:GELF:IncludeScopes"] = "false", - ["Logging:GELF:Protocol"] = "HTTP", - ["Logging:GELF:Host"] = "graylog-host-1" - } - }).Build(); - - var serviceCollection = new ServiceCollection() - .AddLogging(loggingBuilder => loggingBuilder - .AddConfiguration(configuration.GetSection("Logging")) - .AddGelf(o => o.UdpMaxChunkSize = customChunkSize)); - - using var provider = serviceCollection.BuildServiceProvider(); - var options = provider.GetRequiredService>(); - - Assert.Equal(options.Value.UdpMaxChunkSize, customChunkSize); + Assert.Equal(GelfProtocol.Udp, options.Value.Protocol); + Assert.Equal(12201, options.Value.Port); + Assert.Equal(512, options.Value.UdpCompressionThreshold); + Assert.Equal(8192, options.Value.UdpMaxChunkSize); + Assert.Equal(TimeSpan.FromSeconds(30), options.Value.HttpTimeout); + Assert.True(options.Value.IncludeScopes); + Assert.True(options.Value.CompressUdp); + Assert.False(options.Value.IncludeMessageTemplates); } } } From ee3d9fc337df281b899d5972f9805032468cd6df Mon Sep 17 00:00:00 2001 From: Matt Cole Date: Mon, 22 Nov 2021 16:22:27 +0000 Subject: [PATCH 2/2] Add .Net 5 AspNet sample project --- Gelf.Extensions.Logging.sln | 7 +++ README.md | 4 ++ .../Controllers/WeatherForecastController.cs | 40 +++++++++++++++ ...ensions.Logging.Samples.AspNetCore5.csproj | 15 ++++++ .../Program.cs | 29 +++++++++++ .../Properties/launchSettings.json | 31 ++++++++++++ .../Startup.cs | 50 +++++++++++++++++++ .../WeatherForecast.cs | 15 ++++++ .../appsettings.Development.json | 9 ++++ .../appsettings.json | 21 ++++++++ 10 files changed, 221 insertions(+) create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Controllers/WeatherForecastController.cs create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Gelf.Extensions.Logging.Samples.AspNetCore5.csproj create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Program.cs create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Properties/launchSettings.json create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Startup.cs create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/WeatherForecast.cs create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.Development.json create mode 100644 samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.json diff --git a/Gelf.Extensions.Logging.sln b/Gelf.Extensions.Logging.sln index b0f2c21..03ea581 100644 --- a/Gelf.Extensions.Logging.sln +++ b/Gelf.Extensions.Logging.sln @@ -34,6 +34,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gelf.Extensions.Logging.Sam EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gelf.Extensions.Logging.Samples.AspNetCore2", "samples\Gelf.Extensions.Logging.Samples.AspNetCore2\Gelf.Extensions.Logging.Samples.AspNetCore2.csproj", "{C3D38DAC-25E5-4590-A47D-08A97520C4CB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gelf.Extensions.Logging.Samples.AspNetCore5", "samples\Gelf.Extensions.Logging.Samples.AspNetCore5\Gelf.Extensions.Logging.Samples.AspNetCore5.csproj", "{5F202815-647E-488A-9B2C-A746775DBF6B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -64,6 +66,10 @@ Global {C3D38DAC-25E5-4590-A47D-08A97520C4CB}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3D38DAC-25E5-4590-A47D-08A97520C4CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3D38DAC-25E5-4590-A47D-08A97520C4CB}.Release|Any CPU.Build.0 = Release|Any CPU + {5F202815-647E-488A-9B2C-A746775DBF6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F202815-647E-488A-9B2C-A746775DBF6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F202815-647E-488A-9B2C-A746775DBF6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F202815-647E-488A-9B2C-A746775DBF6B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -75,6 +81,7 @@ Global {C55B368D-E4C1-42D0-97C2-4AD2F443743B} = {7D9416E1-13A5-4A86-A3F1-2289369D7193} {7599B625-DD65-4B68-ACF3-6E9400C0A99B} = {7D9416E1-13A5-4A86-A3F1-2289369D7193} {C3D38DAC-25E5-4590-A47D-08A97520C4CB} = {7D9416E1-13A5-4A86-A3F1-2289369D7193} + {5F202815-647E-488A-9B2C-A746775DBF6B} = {7D9416E1-13A5-4A86-A3F1-2289369D7193} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C6D74A71-1746-4865-AAE2-77625B3E8935} diff --git a/README.md b/README.md index 13bc4c7..7e80c6a 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ Logger options are taken from the "GELF" provider section in `appsettings.json` For a full list of options e.g. UDP/HTTP(S) settings, see [`GelfLoggerOptions`](src/Gelf.Extensions.Logging/GelfLoggerOptions.cs). See the [samples](/samples) directory full examples. For more information on providers and logging in general, see the aspnetcore [logging documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging). +### Auto Reloading Config + +Settings can be changed at runtime and will be applied without the need for restarting your app. In the case of invalid config (e.g. missing hostname) the change will be ignored. + ### Additional Fields By default, `logger` and `exception` fields are included on all messages (the `exception` field is only added when an exception is passed to the logger). There are a number of other ways to attach data to logs. diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Controllers/WeatherForecastController.cs b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..caced98 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Controllers/WeatherForecastController.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace Gelf.Extensions.Logging.Samples.AspNetCore5.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + _logger.LogInformation("Getting weather at {weather_time}", DateTime.Now); + _logger.LogDebug("A debug level log"); + + var rng = new Random(); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = rng.Next(-20, 55), + Summary = Summaries[rng.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Gelf.Extensions.Logging.Samples.AspNetCore5.csproj b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Gelf.Extensions.Logging.Samples.AspNetCore5.csproj new file mode 100644 index 0000000..7e28cf6 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Gelf.Extensions.Logging.Samples.AspNetCore5.csproj @@ -0,0 +1,15 @@ + + + + net5.0 + + + + + + + + + + + diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Program.cs b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Program.cs new file mode 100644 index 0000000..3d8d0e4 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Program.cs @@ -0,0 +1,29 @@ +using System; +using System.Reflection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace Gelf.Extensions.Logging.Samples.AspNetCore5 +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => webBuilder + .UseStartup() + .ConfigureLogging((context, loggingBuilder) => loggingBuilder + .AddGelf(options => + { + options.LogSource = context.HostingEnvironment.ApplicationName; + options.AdditionalFields["machine_name"] = Environment.MachineName; + options.AdditionalFields["app_version"] = Assembly.GetEntryAssembly() + !.GetCustomAttribute() + !.InformationalVersion; + }))); + } +} diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Properties/launchSettings.json b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Properties/launchSettings.json new file mode 100644 index 0000000..30762c8 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:49923", + "sslPort": 44374 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Gelf.Extensions.Logging.Samples.AspNetCore5": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Startup.cs b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Startup.cs new file mode 100644 index 0000000..48e7151 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/Startup.cs @@ -0,0 +1,50 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; + +namespace Gelf.Extensions.Logging.Samples.AspNetCore5 +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", + new OpenApiInfo {Title = "Gelf.Extensions.Logging.Samples.AspNetCore5", Version = "v1"}); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseSwagger(); + app.UseSwaggerUI(c => + c.SwaggerEndpoint("/swagger/v1/swagger.json", "Gelf.Extensions.Logging.Samples.AspNetCore5 v1")); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); + } + } +} diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/WeatherForecast.cs b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/WeatherForecast.cs new file mode 100644 index 0000000..6aab9e2 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/WeatherForecast.cs @@ -0,0 +1,15 @@ +using System; + +namespace Gelf.Extensions.Logging.Samples.AspNetCore5 +{ + public class WeatherForecast + { + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int) (TemperatureC / 0.5556); + + public string Summary { get; set; } + } +} diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.Development.json b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.Development.json new file mode 100644 index 0000000..8983e0f --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.json b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.json new file mode 100644 index 0000000..7c89829 --- /dev/null +++ b/samples/Gelf.Extensions.Logging.Samples.AspNetCore5/appsettings.json @@ -0,0 +1,21 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + }, + "GELF": { + "Host": "localhost", + "Protocol": "HTTP", + "Port": "12202", + "AdditionalFields": { + "protocol": "http" + }, + "LogLevel": { + "Gelf.Extensions.Logging.Samples.AspNetCore5.Controllers": "Debug" + } + } + }, + "AllowedHosts": "*" +}