diff --git a/src/api/NetworkResurrector.Api/Program.cs b/src/api/NetworkResurrector.Api/Program.cs index 9d755a2..e4f4df1 100644 --- a/src/api/NetworkResurrector.Api/Program.cs +++ b/src/api/NetworkResurrector.Api/Program.cs @@ -31,7 +31,7 @@ namespace NetworkResurrector.Api var exitCode = 0; try { - var urls = builder.Configuration.GetValue("urls"); + var urls = builder.Configuration.GetValue("Urls"); Log.Information("Starting network resurrector API..."); Log.Information($"Network resurrector API listening on {urls}"); Console.WriteLine("Application started. Press Ctrl+C to shut down."); diff --git a/src/server/NetworkResurrector.Server/Extensions/DataTypeExtensions.cs b/src/server/NetworkResurrector.Server/Extensions/DataTypeExtensions.cs new file mode 100644 index 0000000..10dd86b --- /dev/null +++ b/src/server/NetworkResurrector.Server/Extensions/DataTypeExtensions.cs @@ -0,0 +1,8 @@ +namespace NetworkResurrector.Server.Extensions +{ + internal static class DataTypeExtensions + { + public static string Nullify(this string value) + => string.IsNullOrWhiteSpace(value) ? null : value; + } +} diff --git a/src/server/NetworkResurrector.Server/Extensions/LoggingExtensions.cs b/src/server/NetworkResurrector.Server/Extensions/LoggingExtensions.cs new file mode 100644 index 0000000..cef4ba5 --- /dev/null +++ b/src/server/NetworkResurrector.Server/Extensions/LoggingExtensions.cs @@ -0,0 +1,41 @@ +using Microsoft.Extensions.Configuration; +using Serilog; +using Serilog.Configuration; +using Serilog.Sinks.MSSqlServer; +using System; + +namespace NetworkResurrector.Server.Extensions +{ + internal static class LoggingExtensions + { + internal static LoggerSinkConfiguration ConfiguredDestinations(this LoggerSinkConfiguration writeTo, IConfiguration configuration) + { + var sqlServerEnabled = configuration.GetValue("Logs:SqlServer:Enabled"); + var sqlServerConnection = configuration.GetValue("Logs:SqlServer:Connection"); + var seqEnabled = configuration.GetValue("Logs:Seq:Enabled"); + var seqUrl = configuration.GetValue("Logs:Seq:Url"); + var seqApiKey = configuration.GetValue("Logs:Seq:ApiKey"); + + if (sqlServerEnabled && string.IsNullOrWhiteSpace(sqlServerConnection)) + throw new Exception("If SqlServer logging is enabled, the SqlServer connection must be configured."); + if (seqEnabled && string.IsNullOrWhiteSpace(seqUrl)) + throw new Exception("If Seq logging is enabled, the Seq URL must be configured."); + + if (sqlServerEnabled) + { + var columnOptions = new ColumnOptions(); + columnOptions.Store.Remove(StandardColumn.Properties); + columnOptions.Store.Remove(StandardColumn.MessageTemplate); + columnOptions.Store.Add(StandardColumn.LogEvent); + var mssqlSinkOptions = new MSSqlServerSinkOptions() { AutoCreateSqlTable = true, TableName = "__Logs" }; + + writeTo.MSSqlServer(sqlServerConnection, mssqlSinkOptions, columnOptions: columnOptions); + } + + if (seqEnabled) + writeTo.Seq(seqUrl, apiKey: seqApiKey.Nullify()); + + return writeTo; + } + } +} diff --git a/src/server/NetworkResurrector.Server/Startup.cs b/src/server/NetworkResurrector.Server/Extensions/StartupExtensions.cs similarity index 71% rename from src/server/NetworkResurrector.Server/Startup.cs rename to src/server/NetworkResurrector.Server/Extensions/StartupExtensions.cs index 14d9f7e..85c6e44 100644 --- a/src/server/NetworkResurrector.Server/Startup.cs +++ b/src/server/NetworkResurrector.Server/Extensions/StartupExtensions.cs @@ -9,29 +9,20 @@ using Netmash.Extensions.Swagger; using Netmash.Extensions.Swagger.Constants; using Netmash.Security.Authentication.Identity; using NetworkResurrector.Server.Application; -using NetworkResurrector.Server.Extensions; using Newtonsoft.Json; using System.Reflection; -namespace NetworkResurrector.Server +namespace NetworkResurrector.Server.Extensions { - public class Startup + public static class StartupExtensions { - private readonly IConfiguration _configuration; - - public Startup(IConfiguration configuration) - { - _configuration = configuration; - } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) + public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration) { services.AddControllers() .AddNewtonsoftJson(o => o.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc); // Add basic authentication - services.AddIdentityAuthentication(_configuration.GetSection("IdentityServer")["BaseAddress"]); + services.AddIdentityAuthentication(configuration.GetSection("IdentityServer")["BaseAddress"]); services.AddHttpContextAccessor(); @@ -51,11 +42,11 @@ namespace NetworkResurrector.Server services.AddApplicationServices(); // WakeOnLan - services.AddWakeOnLan(_configuration); + services.AddWakeOnLan(configuration); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + public static void Configure(this IApplicationBuilder app) { // global cors policy app.UseCors(x => x @@ -63,11 +54,6 @@ namespace NetworkResurrector.Server .AllowAnyMethod() .AllowAnyHeader()); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); @@ -78,7 +64,7 @@ namespace NetworkResurrector.Server app.ConfigureSwagger("NetworkResurrector Server API"); } - private Assembly[] GetMediatRAssemblies() + private static Assembly[] GetMediatRAssemblies() { var assembly = typeof(Application.CommandHandlers.PingMachineHandler).Assembly; return new Assembly[] { assembly }; diff --git a/src/server/NetworkResurrector.Server/NetworkResurrector.Server.csproj b/src/server/NetworkResurrector.Server/NetworkResurrector.Server.csproj index fcf6f87..1acee02 100644 --- a/src/server/NetworkResurrector.Server/NetworkResurrector.Server.csproj +++ b/src/server/NetworkResurrector.Server/NetworkResurrector.Server.csproj @@ -15,6 +15,7 @@ + diff --git a/src/server/NetworkResurrector.Server/Program.cs b/src/server/NetworkResurrector.Server/Program.cs index ef00d5a..89d21d5 100644 --- a/src/server/NetworkResurrector.Server/Program.cs +++ b/src/server/NetworkResurrector.Server/Program.cs @@ -1,14 +1,10 @@ +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using NetworkResurrector.Server.Extensions; using Serilog; -using Serilog.Core; -using Serilog.Events; -using Serilog.Sinks.MSSqlServer; using System; -using System.Diagnostics; -using System.IO; -using System.Linq; namespace NetworkResurrector.Server { @@ -16,76 +12,46 @@ namespace NetworkResurrector.Server { public static void Main(string[] args) { - var isConsole = Debugger.IsAttached || args.Contains("--console"); - if (!isConsole) + var builder = WebApplication.CreateBuilder(args); + + builder.Host.UseSerilog((_, lc) => { - var pathToExe = Process.GetCurrentProcess().MainModule.FileName; - var pathToContentRoot = Path.GetDirectoryName(pathToExe); - Directory.SetCurrentDirectory(pathToContentRoot); - } - - var configuration = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) - .AddEnvironmentVariables() - .Build(); - - var connectionString = configuration.GetConnectionString("DatabaseConnection"); - var loggingLevelParam = configuration.GetValue("Logging:LogLevel:Default"); - - var loggingLevelOk = Enum.TryParse(loggingLevelParam, out LogEventLevel loggingLevel); - if (!loggingLevelOk) - throw new Exception($"Logging level '{loggingLevelParam}' is not valid."); - - var loggingLevelSwitch = new LoggingLevelSwitch(loggingLevel); - - var columnOptions = new ColumnOptions(); - columnOptions.Store.Remove(StandardColumn.Properties); - columnOptions.Store.Remove(StandardColumn.MessageTemplate); - columnOptions.Store.Add(StandardColumn.LogEvent); - - var mssqlSinkOptions = new MSSqlServerSinkOptions() { AutoCreateSqlTable = true, TableName = "__Logs" }; - - Log.Logger = new LoggerConfiguration() - .MinimumLevel.ControlledBy(loggingLevelSwitch) - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + lc + .ReadFrom.Configuration(builder.Configuration) .Enrich.FromLogContext() .WriteTo.Console() - .WriteTo.MSSqlServer(connectionString, mssqlSinkOptions, columnOptions: columnOptions) - .CreateLogger(); + .WriteTo.ConfiguredDestinations(builder.Configuration); + }); + + builder.Services.ConfigureServices(builder.Configuration); + + var useWindowsService = builder.Configuration.GetValue("Host:UseWindowsService"); + if (useWindowsService) + builder.Host.UseWindowsService(); + + var app = builder.Build(); + app.Configure(); + + var exitCode = 0; try { - var urls = configuration.GetValue("urls"); - Log.Information("Starting network resurrector API..."); - Log.Information($"API listening on {urls}"); + var urls = builder.Configuration.GetValue("Urls"); + Log.Information("Starting network resurrector server..."); + Log.Information($"Server listening on {urls}"); Console.WriteLine("Application started. Press Ctrl+C to shut down."); - CreateHostBuilder(args, configuration, !isConsole).Build().Run(); + app.Run(); } catch (Exception ex) { - Log.Fatal(ex, "Network resurrector API host terminated unexpectedly"); + Log.Fatal(ex, "Network resurrector server host terminated unexpectedly"); } finally { Log.CloseAndFlush(); } - } - public static IHostBuilder CreateHostBuilder(string[] args, IConfiguration configuration, bool useWindowsService) - { - var builder = Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup() - .UseConfiguration(configuration) - .UseSerilog(); - }); - - if (useWindowsService) - builder.UseWindowsService(); - - return builder; + Environment.Exit(exitCode); } } } diff --git a/src/server/NetworkResurrector.Server/appsettings.json b/src/server/NetworkResurrector.Server/appsettings.json index 398a4eb..e9b20da 100644 --- a/src/server/NetworkResurrector.Server/appsettings.json +++ b/src/server/NetworkResurrector.Server/appsettings.json @@ -1,19 +1,33 @@ { - "urls": "http://*:5062", + "Urls": "http://*:5062", "ConnectionStrings": { "DatabaseConnection": "Server=#########;Database=#########;User Id=#########;Password=#########;MultipleActiveResultSets=true" }, - "Logging": { - "LogLevel": { - "Default": "Debug", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Host": { + "UseWindowsService": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Information" + } + } + }, + "Logs": { + "SqlServer": { + "Enabled": false, + "Connection": "Server=#########;Database=#########;User Id=#########;Password=#########;MultipleActiveResultSets=true" + }, + "Seq": { + "Enabled": false, + "Url": "", + "ApiKey": "" } }, "AllowedHosts": "*", "IdentityServer": { - //"BaseAddress": "http://localhost:5063/" - "BaseAddress": "https://lab.code-rove.com/identity-server-api/" + "BaseAddress": "http://:/api/" }, "WakeOnLan": { "Provider": { @@ -21,5 +35,5 @@ "Options": [ "Inhouse", "Nikeee" ] } }, - "Shutdown": { } + "Shutdown": {} }