This commit is contained in:
2020-05-18 15:59:40 +00:00
parent 2b1c84ade0
commit 49ef9d1a20
3 changed files with 55 additions and 124 deletions

View File

@@ -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<Startup>()
.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

View File

@@ -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<AyContext>(
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<IHostedService, GeneratorService>();
}
@@ -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)

View File

@@ -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)