diff --git a/src/Opserver.Web/Opserver.Web.csproj b/src/Opserver.Web/Opserver.Web.csproj index 6b7318c7..a4c50632 100644 --- a/src/Opserver.Web/Opserver.Web.csproj +++ b/src/Opserver.Web/Opserver.Web.csproj @@ -5,11 +5,24 @@ net6.0 + + + + + + + + + + + + + diff --git a/src/Opserver.Web/Program.cs b/src/Opserver.Web/Program.cs index 75fbeaa4..854a748e 100644 --- a/src/Opserver.Web/Program.cs +++ b/src/Opserver.Web/Program.cs @@ -3,10 +3,15 @@ using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; + using Opserver.Helpers; +using Serilog; +using Serilog.Enrichers.Sensitive; +using Serilog.Exceptions; namespace Opserver { public static class Program @@ -17,6 +22,7 @@ private static async Task Main(string[] args) { try { + var host = WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration( (_, config) => @@ -40,14 +46,39 @@ private static async Task Main(string[] args) .AddEnvironmentVariables(); } ) - .ConfigureLogging( - (hostingContext, config) => - { - var loggingConfig = hostingContext.Configuration.GetSection("Logging"); - config.AddConfiguration(loggingConfig) - .AddConsole(); - } - ) + .ConfigureLogging( + (hostingContext, config) => + { + config.ClearProviders(); + + var dataDogServiceName = Environment.GetEnvironmentVariable("DD_SERVICE") ?? "opserver"; + var product = hostingContext.Configuration.GetValue("Product"); + var tier = hostingContext.Configuration.GetValue("Tier"); + + var loggerconfig = new LoggerConfiguration() + .ReadFrom.Configuration(hostingContext.Configuration) + .Enrich.FromLogContext() + .Enrich.WithEnvironmentUserName() + .Enrich.WithEnvironmentName() + .Enrich.WithProperty("dd_service", dataDogServiceName) + .Enrich.WithMachineName() + .Enrich.WithThreadId() + .Enrich.WithExceptionDetails() + .Enrich.WithSensitiveDataMasking(options => + { + options.MaskingOperators = new List + { + new EmailAddressMaskingOperator() + }; + }); + + loggerconfig.Filter.ByExcluding("StartsWith(SourceContext, 'StackExchange.Exceptional.')"); + loggerconfig.Filter.ByExcluding("SourceContext='Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware' and @mt='An unhandled exception has occurred while executing the request.'"); + + Log.Logger = loggerconfig.CreateLogger(); + config.AddSerilog(Log.Logger); + } + ) .UseStartup() .Build(); diff --git a/src/Opserver.Web/Startup.cs b/src/Opserver.Web/Startup.cs index d943554b..d55d80ae 100644 --- a/src/Opserver.Web/Startup.cs +++ b/src/Opserver.Web/Startup.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Net; using System.Text.RegularExpressions; @@ -20,6 +21,8 @@ using Opserver.Data; using Opserver.Helpers; using Opserver.Security; +using Serilog; +using StackExchange.Exceptional; using StackExchange.Profiling; namespace Opserver @@ -63,8 +66,9 @@ public void ConfigureServices(IServiceCollection services) _configuration.GetSection("Exceptional"), settings => { - settings.UseExceptionalPageOnThrow = true; + settings.UseExceptionalPageOnThrow = false; settings.DataIncludeRegex = new Regex("^(Redis|Elastic|ErrorLog|Jil)", RegexOptions.Singleline | RegexOptions.Compiled); + settings.OnAfterLog += ExceptionalAfterLog; settings.GetCustomData = (ex, data) => { // everything below needs a context @@ -240,9 +244,18 @@ IEnumerable modules AllowCachingResponses = false, Predicate = _ => false // We don't use any healthchecks for liveliness, just that the app responds - }); + }); NavTab.ConfigureAll(modules); // TODO: UseNavTabs() or something Cache.Configure(settings); } + + private void ExceptionalAfterLog(object sender, ErrorAfterLogEventArgs args) + { + if (args != null) + { + string message = args.Error.Message; + Serilog.Log.Error(args.Error.Exception, "{Message}", message); + } + } } } diff --git a/src/Opserver.Web/appsettings.json b/src/Opserver.Web/appsettings.json new file mode 100644 index 00000000..81a2f1a6 --- /dev/null +++ b/src/Opserver.Web/appsettings.json @@ -0,0 +1,30 @@ +{ + "Serilog": { + "Using": [ "Serilog.Sinks.Console" ], + "Properties": { + "Application": "OpServer" + }, + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "System": "Warning" + } + }, + "WriteTo": [ + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "Console", + "Args": { + "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" + } + } + ] + } + } + ] + } +}