diff --git a/server/AyaNova/Program.cs b/server/AyaNova/Program.cs index c939fcad..5ca30ed8 100644 --- a/server/AyaNova/Program.cs +++ b/server/AyaNova/Program.cs @@ -153,40 +153,36 @@ namespace AyaNova } // NLog: setup the logger first to catch all errors - var logger = NLogBuilder.ConfigureNLog(logConfig).GetLogger("Init");//.GetCurrentClassLogger(); + var logger = NLogBuilder.ConfigureNLog(logConfig).GetLogger("BOOT"); //This is the first log entry - logger.Info("AYANOVA SERVER BOOTING (log level: \"{0}\")", ServerBootConfig.AYANOVA_LOG_LEVEL); - logger.Info(AyaNovaVersion.FullNameAndVersion); + logger.Info($"AYANOVA SERVER {AyaNovaVersion.VersionString} BOOTING"); + //log configuration try - { - - var AyaNovaConfig=config.AsEnumerable().Where(m => m.Key.StartsWith("AYANOVA") && m.Key!="AYANOVA_JWT_SECRET").Select(m=>m.Key+ "="+ m.Value).ToList(); - + { + var AyaNovaConfig=config.AsEnumerable().Where(m => m.Key.StartsWith("AYANOVA") && m.Key!="AYANOVA_JWT_SECRET").Select(m=>m.Key+ "="+ m.Value).ToList(); var DiagConfig=string.Join(",", AyaNovaConfig); DiagConfig=DbUtil.PasswordRedactedConnectionString(DiagConfig); - logger.Info($"BOOT: configuration {DiagConfig}"); + logger.Info($"Config {DiagConfig}"); } catch (Exception ex) { - logger.Error(ex, "BOOT: error fetching configuration"); + logger.Error(ex, "Error fetching configuration"); } - logger.Debug($"BOOT: Full configuration is {config.GetDebugView()}"); - logger.Debug("BOOT: Log path is \"{0}\" ", ServerBootConfig.AYANOVA_LOG_PATH); + logger.Debug($"Full configuration is {config.GetDebugView()}"); - if (ServerBootConfig.AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG) - { - logger.Warn("BOOT: AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG is enabled! Disable as soon as no longer required."); - } + if (ServerBootConfig.AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG) + logger.Warn("AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG is enabled, this will cause the server to run very slowly"); + //Log environmental settings - logger.Info("BOOT: OS - {0}", Environment.OSVersion.ToString()); - logger.Debug("BOOT: Machine - {0}", Environment.MachineName); - logger.Debug("BOOT: User - {0}", Environment.UserName); - logger.Debug("BOOT: .Net Version - {0}", Environment.Version.ToString()); - logger.Debug("BOOT: CPU count - {0}", Environment.ProcessorCount); - logger.Debug("BOOT: Default language - \"{0}\"", ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION); + logger.Info("OS - {0}", Environment.OSVersion.ToString()); + logger.Debug("Machine - {0}", Environment.MachineName); + logger.Debug("User - {0}", Environment.UserName); + logger.Debug(".Net Version - {0}", Environment.Version.ToString()); + logger.Debug("CPU count - {0}", Environment.ProcessorCount); + #endregion @@ -201,7 +197,7 @@ namespace AyaNova //AyaNova won't be able to serve static files if (!Directory.Exists(wwwRootFolder)) { - var err = string.Format("BOOT: E1010 - AyaNova was not started in the correct folder. AyaNova must be started from the folder that contains the \"wwwroot\" folder but was started instead from this folder: \"{0}\" which does not contain the wwwroot folder.", startFolder); + var err = string.Format("E1010 - AyaNova was not started in the correct folder. AyaNova must be started from the folder that contains the \"wwwroot\" folder but was started instead from this folder: \"{0}\" which does not contain the wwwroot folder.", startFolder); logger.Fatal(err); throw new System.ApplicationException(err); } @@ -213,7 +209,7 @@ namespace AyaNova } catch (Exception e) { - logger.Fatal(e, "BOOT: E1090 - AyaNova server can't start due to unexpected exception during initialization"); + logger.Fatal(e, "E1090 - AyaNova server can't start due to unexpected exception during initialization"); throw; } finally @@ -231,7 +227,7 @@ namespace AyaNova public static IHostBuilder BuildHost(string[] args, NLog.Logger logger) { - logger.Debug("BOOT: building host"); + logger.Debug("Building host"); var configuration = new ConfigurationBuilder().AddCommandLine(args).Build(); return Host.CreateDefaultBuilder(args) @@ -289,73 +285,8 @@ namespace AyaNova logging.ClearProviders(); }) .UseNLog(); // NLog: setup NLog for Dependency injection - }); - - } - - /* Dotnet 2.2 buildwebhost will be deprecated in favor of buildhost - public static IWebHost BuildWebHost(string[] args, NLog.Logger logger) - { - logger.Debug("BOOT: building web host"); - var configuration = new ConfigurationBuilder().AddCommandLine(args).Build(); - - return WebHost.CreateDefaultBuilder(args) - .CaptureStartupErrors(true) - .UseSetting("detailedErrors", "true") - .UseUrls(ServerBootConfig.AYANOVA_USE_URLS)//default port and urls, set first can be overridden by any later setting here - .UseConfiguration(configuration)//support command line override of port (dotnet run urls=http://*:8081) - .UseIISIntegration()//support IIS integration just in case, it appears here to override prior settings if necessary (port) - .ConfigureMetricsWithDefaults(builder => - { - if (ServerBootConfig.AYANOVA_METRICS_USE_INFLUXDB) - { - builder.Report.ToInfluxDb( - options => - { - - options.InfluxDb.BaseUri = new Uri(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_BASEURL); - options.InfluxDb.Database = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_DBNAME; - if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY)) - { - options.InfluxDb.Consistenency = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY; - } - options.InfluxDb.UserName = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_USERNAME; - options.InfluxDb.Password = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_PASSWORD; - if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY)) - { - options.InfluxDb.RetentionPolicy = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY; - } - - options.InfluxDb.CreateDataBaseIfNotExists = true; - options.HttpPolicy.BackoffPeriod = TimeSpan.FromSeconds(30); - options.HttpPolicy.FailuresBeforeBackoff = 5; - options.HttpPolicy.Timeout = TimeSpan.FromSeconds(10); - //options.MetricsOutputFormatter = new App.Metrics.Formatters.Json.MetricsJsonOutputFormatter(); - //options.Filter = filter; - options.FlushInterval = TimeSpan.FromSeconds(20); - }); - } - - }) - .UseMetricsEndpoints(opt => - { - opt.EnvironmentInfoEndpointEnabled = false; - opt.MetricsEndpointEnabled = false; - opt.MetricsTextEndpointEnabled = false; - }) - .UseMetrics() - .UseStartup() - .ConfigureLogging((context, logging) => - { - // clear all previously registered providers - //https://stackoverflow.com/a/46336988/8939 - logging.ClearProviders(); - }) - .UseNLog() // NLog: setup NLog for Dependency injection - .Build(); - } - */ + } }//eoc diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index 0ccb038d..043d4662 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -35,7 +35,7 @@ namespace AyaNova var nlogLoggerProvider = new NLogLoggerProvider(); // Create an ILogger. - _newLog = nlogLoggerProvider.CreateLogger("Server"); + _newLog = nlogLoggerProvider.CreateLogger("SERVER"); //x_log = logger; _hostingEnvironment = hostingEnvironment; @@ -59,16 +59,16 @@ namespace AyaNova // public void ConfigureServices(IServiceCollection services) { - _newLog.LogDebug("BOOT: initializing services..."); + _newLog.LogDebug("Initializing services..."); //Server state service for shutting people out of api - _newLog.LogDebug("BOOT: init ApiServerState service"); + _newLog.LogDebug("ApiServerState"); services.AddSingleton(new AyaNova.Api.ControllerHelpers.ApiServerState()); //Init controllers - _newLog.LogDebug("BOOT: init controllers"); + _newLog.LogDebug("Controllers"); var MvcBuilder = services.AddControllers(config => { // config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory)); @@ -85,7 +85,7 @@ namespace AyaNova options.SuppressModelStateInvalidFilter = true; }); - _newLog.LogDebug("BOOT: init JSON"); + _newLog.LogDebug("JSON"); MvcBuilder.AddNewtonsoftJson(options => { @@ -97,39 +97,39 @@ namespace AyaNova //HTTP CLIENT FACTORY USED BY LICENSE.CS //https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1 - _newLog.LogDebug("BOOT: init HTTPClientFactory"); + _newLog.LogDebug("HTTPClientFactory"); services.AddHttpClient(); //2019-10-17 METRICS will not work just yet with .netcore 3.1 see here https://github.com/AppMetrics/AppMetrics/issues/480 //awaiting a new release from them - _newLog.LogDebug("BOOT: init Metrics service"); + _newLog.LogDebug("Metrics"); services.AddMetrics(); - _newLog.LogDebug("BOOT: ensuring user and backup folders exist and are separate locations..."); + _newLog.LogDebug("Ensuring user and backup folders exist and are separate locations..."); FileUtil.EnsureUserAndUtilityFoldersExistAndAreNotIdentical(_hostingEnvironment.ContentRootPath); #region DATABASE _connectionString = ServerBootConfig.AYANOVA_DB_CONNECTION; //Check DB server exists and can be connected to - _newLog.LogDebug("BOOT: Testing database server connection..."); + _newLog.LogDebug("Testing database server connection..."); //parse the connection string properly DbUtil.ParseConnectionString(_newLog, _connectionString); //Probe for database server //Will retry every 10 seconds for up to 5 minutes before bailing - if (!DbUtil.DatabaseServerExists(_newLog, "BOOT: waiting for db server ")) + if (!DbUtil.DatabaseServerExists(_newLog, "Waiting for db server ")) { - var err = $"BOOT: E1000 - AyaNova can't connect to the database server after trying for 5 minutes (connection string is:\"{DbUtil.DisplayableConnectionString}\")"; + var err = $"E1000 - AyaNova can't connect to the database server after trying for 5 minutes (connection string is:\"{DbUtil.DisplayableConnectionString}\")"; _newLog.LogCritical(err); throw new System.ApplicationException(err); } - _newLog.LogInformation("BOOT: Connected to database server - {0}", DbUtil.DisplayableConnectionString); + _newLog.LogInformation("Connected to database server - {0}", DbUtil.DisplayableConnectionString); //ensure database is ready and present @@ -142,7 +142,7 @@ namespace AyaNova #endif - _newLog.LogDebug("BOOT: init EF service"); + _newLog.LogDebug("EF Core"); services.AddEntityFrameworkNpgsql().AddDbContext( options => options.UseNpgsql(_connectionString @@ -162,7 +162,7 @@ namespace AyaNova // Add service and create Policy with options - _newLog.LogDebug("BOOT: init CORS service"); + _newLog.LogDebug("CORS"); services.AddCors(options => { options.AddPolicy("CorsPolicy", @@ -254,7 +254,7 @@ namespace AyaNova ServerBootConfig.AYANOVA_JWT_SECRET = secretKey; var signingKey = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes(ServerBootConfig.AYANOVA_JWT_SECRET)); - _newLog.LogDebug("BOOT: init Authorization service"); + _newLog.LogDebug("Authorization"); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; @@ -285,7 +285,7 @@ namespace AyaNova #endregion - _newLog.LogDebug("BOOT: init Generator service"); + _newLog.LogDebug("Generator"); services.AddSingleton(); } @@ -298,7 +298,7 @@ namespace AyaNova public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IWebHostEnvironment env, AyContext dbContext, IApiVersionDescriptionProvider provider, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider) { - _newLog.LogDebug("BOOT: configuring request pipeline..."); + _newLog.LogDebug("Configuring request pipeline..."); //this *may* be useful in the event of an issue so uncomment if necessary but errors during dev are handled equally by the logging, I think // if (env.IsDevelopment()) @@ -326,7 +326,7 @@ namespace AyaNova #region STATIC FILES - _newLog.LogDebug("BOOT: pipeline - static files"); + _newLog.LogDebug("Static files"); app.UseDefaultFiles(); app.UseStaticFiles(); //Might need the following if the page doesn't update in the client properly @@ -344,19 +344,19 @@ namespace AyaNova // }); #endregion - _newLog.LogDebug("BOOT: pipeline - ROUTING"); + _newLog.LogDebug("Routing pipeline"); app.UseRouting();//this wasn't here for 2.2 but added for 3.0, needs to come before the stuff after - _newLog.LogDebug("BOOT: pipeline - CORS"); + _newLog.LogDebug("CORS pipeline"); app.UseCors("CorsPolicy"); #region AUTH / ROLES CUSTOM MIDDLEWARE - _newLog.LogDebug("BOOT: pipeline - authentication"); + _newLog.LogDebug("Authentication pipeline"); //Use authentication middleware app.UseAuthentication(); - _newLog.LogDebug("BOOT: pipeline - authorization"); + _newLog.LogDebug("Authorization pipeline"); app.UseAuthorization(); @@ -414,7 +414,7 @@ namespace AyaNova #endregion - _newLog.LogDebug("BOOT: pipeline - ENDPOINTS"); + _newLog.LogDebug("Endpoints pipeline"); app.UseEndpoints(endpoints => { endpoints.MapControllers(); @@ -422,7 +422,7 @@ namespace AyaNova #region SWAGGER - _newLog.LogDebug("BOOT: pipeline - api explorer"); + _newLog.LogDebug("API explorer pipeline"); // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); app.UseSwaggerUI( @@ -464,29 +464,29 @@ namespace AyaNova { if (ServerBootConfig.AYANOVA_SERVER_TEST_MODE) { - _newLog.LogWarning("BOOT: AYANOVA_SERVER_TEST_MODE is true, dropping and recreating database"); + _newLog.LogWarning("AYANOVA_SERVER_TEST_MODE, dropping and recreating database"); } else { - _newLog.LogWarning("BOOT: AYANOVA_PERMANENTLY_ERASE_DATABASE is true, dropping and recreating database"); + _newLog.LogWarning("AYANOVA_PERMANENTLY_ERASE_DATABASE, dropping and recreating database"); } Util.DbUtil.DropAndRecreateDbAsync(_newLog).Wait(); AySchema.CheckAndUpdateAsync(dbContext, _newLog).Wait(); } //Check schema - _newLog.LogDebug("BOOT: db schema check"); + _newLog.LogDebug("DB schema check"); AySchema.CheckAndUpdateAsync(dbContext, _newLog).Wait(); //Check database integrity - _newLog.LogDebug("BOOT: db integrity check"); + _newLog.LogDebug("DB integrity check"); DbUtil.CheckFingerPrintAsync(AySchema.EXPECTED_COLUMN_COUNT, AySchema.EXPECTED_INDEX_COUNT, _newLog).Wait(); //Initialize license AyaNova.Core.License.InitializeAsync(apiServerState, dbContext, _newLog).Wait(); //Set static global biz settings - _newLog.LogDebug("BOOT: init global settings"); + _newLog.LogDebug("Global settings"); ServerGlobalBizSettings.Initialize(null, dbContext); //Ensure translations are present, not missing any keys and that there is a server default translation that exists @@ -497,7 +497,7 @@ namespace AyaNova //TESTING if (ServerBootConfig.AYANOVA_SERVER_TEST_MODE) { - _newLog.LogInformation($"BOOT: server test mode seeding, level is {ServerBootConfig.AYANOVA_SERVER_TEST_MODE_SEEDLEVEL}, tz offset is {ServerBootConfig.AYANOVA_SERVER_TEST_MODE_TZ_OFFSET}"); + _newLog.LogInformation($"Server test mode seeding, level is {ServerBootConfig.AYANOVA_SERVER_TEST_MODE_SEEDLEVEL}, tz offset is {ServerBootConfig.AYANOVA_SERVER_TEST_MODE_TZ_OFFSET}"); AyaNova.Core.License.FetchKeyAsync(apiServerState, dbContext, _newLog).Wait(); //NOTE: For unit testing make sure the time zone is same as tester to ensure list filter by date tests will work because server is on same page as user in terms of time Util.Seeder.SeedDatabaseAsync(Util.Seeder.StringToSeedLevel(ServerBootConfig.AYANOVA_SERVER_TEST_MODE_SEEDLEVEL), ServerBootConfig.AYANOVA_SERVER_TEST_MODE_TZ_OFFSET).Wait(); @@ -522,10 +522,10 @@ namespace AyaNova //Log the active user count so it's in the log record - _newLog.LogInformation($"BOOT: Active techs - {UserBiz.ActiveCountAsync().Result}"); + _newLog.LogInformation($"Active techs - {UserBiz.ActiveCountAsync().Result}"); //Log the license info so it's on the record - _newLog.LogInformation($"BOOT: License - [{AyaNova.Core.License.LicenseInfoLogFormat}]"); + _newLog.LogInformation($"License - [{AyaNova.Core.License.LicenseInfoLogFormat}]"); @@ -533,7 +533,7 @@ namespace AyaNova apiServerState.SetOpen(); //final startup log - _newLog.LogInformation("BOOT: COMPLETED - SERVER IS NOW OPEN"); + _newLog.LogInformation("Boot complete - server open"); #if (DEBUG) //Show in dev console that server is open (so I don't need to look in the log to see it) diff --git a/server/AyaNova/util/Seeder.cs b/server/AyaNova/util/Seeder.cs index b248ed02..b56edbce 100644 --- a/server/AyaNova/util/Seeder.cs +++ b/server/AyaNova/util/Seeder.cs @@ -62,7 +62,7 @@ namespace AyaNova.Util try { - await LogStatusAsync(JobId, LogJob, log, $"SEEDER: Seeding data level is {slevel.ToString()}, time zone offset is {timeZoneOffset.ToString()}"); + await LogStatusAsync(JobId, LogJob, log, $"Seeding data, level {slevel.ToString()}, time zone offset {timeZoneOffset.ToString()}"); //Only allow this in a trial database if (!AyaNova.Core.License.ActiveKey.TrialLicense)