This commit is contained in:
@@ -16,7 +16,7 @@ UPDATE all the things before commencing work
|
||||
- Find and read changes for 3.1 dotnet core and Note that that above is for v2.2 my controllers appear to date from the v1 .net core era and I will need to then move them to the .netcore 3.1 era changes
|
||||
- This is important and worth doing to make sure everything will work going forward (the swashbuckle [apicontroller] attribute debacle is proof of this)
|
||||
|
||||
|
||||
- Should not process jobs during boot, maybe serverstate=booting would be useful here?
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------
|
||||
Need a sprint to get to a fully testable client with entry form, list and as much as possible all features from COMMON-* specs list
|
||||
|
||||
@@ -22,14 +22,24 @@ namespace AyaNova.Api.ControllerHelpers
|
||||
{
|
||||
private readonly ILogger log;
|
||||
|
||||
public ApiCustomExceptionFilter(ILoggerFactory logger)
|
||||
// public ApiCustomExceptionFilter(ILoggerFactory logger)
|
||||
// {
|
||||
// if (logger == null)
|
||||
// {
|
||||
// throw new ArgumentNullException(nameof(logger));
|
||||
// }
|
||||
|
||||
// this.log = logger.CreateLogger("Server Exception");
|
||||
// }
|
||||
|
||||
public ApiCustomExceptionFilter(ILogger logger)
|
||||
{
|
||||
if (logger == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
this.log = logger.CreateLogger("Server Exception");
|
||||
this.log = logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,10 +81,10 @@ namespace AyaNova.Api.ControllerHelpers
|
||||
if (loggableError)
|
||||
log.LogError(context.Exception, "Error");
|
||||
|
||||
|
||||
|
||||
//Track this exception
|
||||
IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics));
|
||||
metrics.Measure.Meter.Mark(MetricsRegistry.UnhandledExceptionsMeter,context.Exception.GetType().ToString());
|
||||
IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics));
|
||||
metrics.Measure.Meter.Mark(MetricsRegistry.UnhandledExceptionsMeter, context.Exception.GetType().ToString());
|
||||
|
||||
|
||||
HttpResponse response = context.HttpContext.Response;
|
||||
|
||||
@@ -376,6 +376,7 @@ namespace AyaNova.Api.Controllers
|
||||
[HttpGet("exception")]
|
||||
public ActionResult GetException()
|
||||
{
|
||||
log.LogCritical("Widget::getexception->CRITICAL LOG TEST");
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
|
||||
throw new System.NotSupportedException("Test exception from widget controller");
|
||||
|
||||
@@ -33,10 +33,10 @@ namespace AyaNova
|
||||
ServerBootConfig.SetConfiguration(config);
|
||||
|
||||
#region Initialize Logging
|
||||
//NOTE: there is a logging issue that breaks all this with .net 3.1 hostbuilder vs webhostbuilder but webhostbuilder will be deprecated so we need to work around it
|
||||
//the discussion about that is here: https://github.com/aspnet/AspNetCore/issues/9337
|
||||
//NOTE: there is a logging issue that breaks all this with .net 3.1 hostbuilder vs webhostbuilder but webhostbuilder will be deprecated so we need to work around it
|
||||
//the discussion about that is here: https://github.com/aspnet/AspNetCore/issues/9337
|
||||
|
||||
//NLOG OFFICIAL GUIDELINES FOR .net core 3.x https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-3
|
||||
//NLOG OFFICIAL GUIDELINES FOR .net core 3.x https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-3
|
||||
|
||||
//default log level
|
||||
NLog.LogLevel NLogLevel = NLog.LogLevel.Info;
|
||||
@@ -198,6 +198,12 @@ namespace AyaNova
|
||||
logger.Fatal(e, "BOOT: E1090 - AyaNova server can't start due to unexpected exception during initialization");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
logger.Info("AyaNova server shutting down");
|
||||
NLog.LogManager.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,23 +22,41 @@ using AyaNova.Util;
|
||||
using AyaNova.Generator;
|
||||
using AyaNova.Biz;
|
||||
|
||||
|
||||
using NLog.Web;
|
||||
using NLog.Targets;
|
||||
using NLog.Config;
|
||||
using NLog.Extensions.Logging;
|
||||
|
||||
namespace AyaNova
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
public Startup(ILogger<Startup> logger, ILoggerFactory logFactory, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment)
|
||||
{
|
||||
_log = logger;
|
||||
public Startup( Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment)
|
||||
{//ILogger<Startup> logger, ILoggerFactory logFactory,
|
||||
|
||||
// Get the factory for ILogger instances.
|
||||
var nlogLoggerProvider = new NLogLoggerProvider();
|
||||
|
||||
// Create an ILogger.
|
||||
_newLog = nlogLoggerProvider.CreateLogger(typeof(Startup).FullName);
|
||||
|
||||
//x_log = logger;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
AyaNova.Util.ApplicationLogging.LoggerFactory = logFactory;
|
||||
//AyaNova.Util.ApplicationLogging.LoggerFactory = logFactory;
|
||||
//AyaNova.Util.ApplicationLogging.theLogger = _newLog;
|
||||
AyaNova.Util.ApplicationLogging.LoggerProvider=nlogLoggerProvider;
|
||||
|
||||
//this must be set here
|
||||
ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH = hostingEnvironment.ContentRootPath;
|
||||
|
||||
}
|
||||
|
||||
private readonly ILogger<Startup> _log;
|
||||
private readonly ILogger _newLog;
|
||||
|
||||
private readonly ILogger<Startup>x_log;
|
||||
private string _connectionString = "";
|
||||
private readonly Microsoft.AspNetCore.Hosting.IWebHostEnvironment _hostingEnvironment;
|
||||
|
||||
@@ -47,19 +65,20 @@ namespace AyaNova
|
||||
//
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
_log.LogDebug("BOOT: initializing services...");
|
||||
_newLog.LogDebug("BOOT: initializing services...");
|
||||
|
||||
|
||||
|
||||
//Server state service for shutting people out of api
|
||||
_log.LogDebug("BOOT: init ApiServerState service");
|
||||
_newLog.LogDebug("BOOT: init ApiServerState service");
|
||||
services.AddSingleton(new AyaNova.Api.ControllerHelpers.ApiServerState());
|
||||
|
||||
//Init controllers
|
||||
_log.LogDebug("BOOT: init controllers");
|
||||
_newLog.LogDebug("BOOT: init controllers");
|
||||
var MvcBuilder = services.AddControllers(config =>
|
||||
{
|
||||
config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory));
|
||||
// config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory));
|
||||
config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(_newLog));
|
||||
});
|
||||
|
||||
//Prevent default model binding automatic 400 page so we can consistently show *our* error to our specs
|
||||
@@ -69,7 +88,7 @@ namespace AyaNova
|
||||
options.SuppressModelStateInvalidFilter = true;
|
||||
});
|
||||
|
||||
_log.LogDebug("BOOT: init JSON");
|
||||
_newLog.LogDebug("BOOT: init JSON");
|
||||
MvcBuilder.AddNewtonsoftJson(options =>
|
||||
{
|
||||
options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
|
||||
@@ -80,41 +99,41 @@ namespace AyaNova
|
||||
|
||||
//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
|
||||
//_log.LogDebug("BOOT: init Metrics service");
|
||||
//_newLog.LogDebug("BOOT: init Metrics service");
|
||||
//MvcBuilder.AddMetrics();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_log.LogDebug("BOOT: ensuring user and backup folders exist and are separate locations...");
|
||||
_newLog.LogDebug("BOOT: 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
|
||||
_log.LogDebug("BOOT: Testing database server connection...");
|
||||
_newLog.LogDebug("BOOT: Testing database server connection...");
|
||||
|
||||
//parse the connection string properly
|
||||
DbUtil.ParseConnectionString(_log, _connectionString);
|
||||
DbUtil.ParseConnectionString(_newLog, _connectionString);
|
||||
|
||||
//Probe for database server
|
||||
//Will retry every 10 seconds for up to 5 minutes before bailing
|
||||
if (!DbUtil.DatabaseServerExists(_log, "BOOT: waiting for db server "))
|
||||
if (!DbUtil.DatabaseServerExists(_newLog, "BOOT: 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}\")";
|
||||
_log.LogCritical(err);
|
||||
_newLog.LogCritical(err);
|
||||
throw new System.ApplicationException(err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
_log.LogInformation("BOOT: Connected to database server - {0}", DbUtil.DisplayableConnectionString);
|
||||
_newLog.LogInformation("BOOT: Connected to database server - {0}", DbUtil.DisplayableConnectionString);
|
||||
|
||||
|
||||
//ensure database is ready and present
|
||||
DbUtil.EnsureDatabaseExists(_log);
|
||||
DbUtil.EnsureDatabaseExists(_newLog);
|
||||
|
||||
bool LOG_SENSITIVE_DATA = false;
|
||||
|
||||
@@ -123,7 +142,7 @@ namespace AyaNova
|
||||
|
||||
#endif
|
||||
|
||||
_log.LogDebug("BOOT: init EF service");
|
||||
_newLog.LogDebug("BOOT: init EF service");
|
||||
|
||||
services.AddEntityFrameworkNpgsql().AddDbContext<AyContext>(
|
||||
options => options.UseNpgsql(_connectionString
|
||||
@@ -143,7 +162,7 @@ namespace AyaNova
|
||||
|
||||
|
||||
// Add service and create Policy with options
|
||||
_log.LogDebug("BOOT: init CORS service");
|
||||
_newLog.LogDebug("BOOT: init CORS service");
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
@@ -223,7 +242,7 @@ namespace AyaNova
|
||||
ServerBootConfig.AYANOVA_JWT_SECRET = secretKey;
|
||||
var signingKey = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes(ServerBootConfig.AYANOVA_JWT_SECRET));
|
||||
|
||||
_log.LogDebug("BOOT: init Authorization service");
|
||||
_newLog.LogDebug("BOOT: init Authorization service");
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
@@ -254,7 +273,7 @@ namespace AyaNova
|
||||
|
||||
#endregion
|
||||
|
||||
_log.LogDebug("BOOT: init Generator service");
|
||||
_newLog.LogDebug("BOOT: init Generator service");
|
||||
services.AddSingleton<IHostedService, GeneratorService>();
|
||||
|
||||
}
|
||||
@@ -267,7 +286,7 @@ namespace AyaNova
|
||||
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IWebHostEnvironment env,
|
||||
AyContext dbContext, IApiVersionDescriptionProvider provider, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider)
|
||||
{
|
||||
_log.LogDebug("BOOT: configuring request pipeline...");
|
||||
_newLog.LogDebug("BOOT: 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())
|
||||
@@ -286,7 +305,7 @@ namespace AyaNova
|
||||
});
|
||||
|
||||
#region STATIC FILES
|
||||
_log.LogDebug("BOOT: pipeline - static files");
|
||||
_newLog.LogDebug("BOOT: pipeline - static files");
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
//Might need the following if the page doesn't update in the client properly
|
||||
@@ -304,19 +323,19 @@ namespace AyaNova
|
||||
// });
|
||||
#endregion
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - ROUTING");
|
||||
_newLog.LogDebug("BOOT: pipeline - ROUTING");
|
||||
app.UseRouting();//this wasn't here for 2.2 but added for 3.0, needs to come before the stuff after
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - CORS");
|
||||
_newLog.LogDebug("BOOT: pipeline - CORS");
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
|
||||
#region AUTH / ROLES
|
||||
_log.LogDebug("BOOT: pipeline - authentication");
|
||||
_newLog.LogDebug("BOOT: pipeline - authentication");
|
||||
//Use authentication middleware
|
||||
app.UseAuthentication();
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - authorization");
|
||||
_newLog.LogDebug("BOOT: pipeline - authorization");
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
@@ -348,7 +367,7 @@ namespace AyaNova
|
||||
|
||||
#endregion
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - ENDPOINTS");
|
||||
_newLog.LogDebug("BOOT: pipeline - ENDPOINTS");
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
@@ -356,7 +375,7 @@ namespace AyaNova
|
||||
|
||||
#region SWAGGER
|
||||
|
||||
_log.LogDebug("BOOT: pipeline - api explorer");
|
||||
_newLog.LogDebug("BOOT: pipeline - api explorer");
|
||||
// Enable middleware to serve generated Swagger as a JSON endpoint.
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(
|
||||
@@ -393,21 +412,21 @@ namespace AyaNova
|
||||
|
||||
if (ServerBootConfig.AYANOVA_PERMANENTLY_ERASE_DATABASE)
|
||||
{
|
||||
_log.LogWarning("BOOT: AYANOVA_PERMANENTLY_ERASE_DATABASE is true, dropping and recreating database");
|
||||
Util.DbUtil.DropAndRecreateDb(_log);
|
||||
AySchema.CheckAndUpdate(dbContext, _log);
|
||||
_newLog.LogWarning("BOOT: AYANOVA_PERMANENTLY_ERASE_DATABASE is true, dropping and recreating database");
|
||||
Util.DbUtil.DropAndRecreateDb(_newLog);
|
||||
AySchema.CheckAndUpdate(dbContext, _newLog);
|
||||
}
|
||||
|
||||
//Check schema
|
||||
_log.LogDebug("BOOT: db schema check");
|
||||
AySchema.CheckAndUpdate(dbContext, _log);
|
||||
_newLog.LogDebug("BOOT: db schema check");
|
||||
AySchema.CheckAndUpdate(dbContext, _newLog);
|
||||
|
||||
//Check database integrity
|
||||
_log.LogDebug("BOOT: db integrity check");
|
||||
DbUtil.CheckFingerPrint(AySchema.EXPECTED_COLUMN_COUNT, AySchema.EXPECTED_INDEX_COUNT, _log);
|
||||
_newLog.LogDebug("BOOT: db integrity check");
|
||||
DbUtil.CheckFingerPrint(AySchema.EXPECTED_COLUMN_COUNT, AySchema.EXPECTED_INDEX_COUNT, _newLog);
|
||||
|
||||
//Initialize license
|
||||
AyaNova.Core.License.Initialize(apiServerState, dbContext, _log);
|
||||
AyaNova.Core.License.Initialize(apiServerState, dbContext, _newLog);
|
||||
|
||||
//Ensure locales are present, not missing any keys and that there is a server default locale that exists
|
||||
LocaleBiz lb = new LocaleBiz(dbContext, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.OpsAdminFull);
|
||||
@@ -419,7 +438,7 @@ namespace AyaNova
|
||||
//TESTING
|
||||
if (TESTING_REFRESH_DB)
|
||||
{
|
||||
AyaNova.Core.License.Fetch(apiServerState, dbContext, _log);
|
||||
AyaNova.Core.License.Fetch(apiServerState, dbContext, _newLog);
|
||||
Util.Seeder.SeedDatabase(Util.Seeder.SeedLevel.SmallOneManShopTrialDataSet, -7);//#############################################################################################
|
||||
}
|
||||
//TESTING
|
||||
@@ -446,10 +465,10 @@ namespace AyaNova
|
||||
|
||||
|
||||
//Log the active user count so it's in the log record
|
||||
_log.LogInformation($"BOOT: Active techs - {UserBiz.ActiveCount}");
|
||||
_newLog.LogInformation($"BOOT: Active techs - {UserBiz.ActiveCount}");
|
||||
|
||||
//Log the license info so it's on the record
|
||||
_log.LogInformation($"BOOT: License -\r\n=-=-=-=-=-=-=-=-=-=-\r\n{AyaNova.Core.License.LicenseInfo}=-=-=-=-=-=-=-=-=-=-");
|
||||
_newLog.LogInformation($"BOOT: License -\r\n=-=-=-=-=-=-=-=-=-=-\r\n{AyaNova.Core.License.LicenseInfo}=-=-=-=-=-=-=-=-=-=-");
|
||||
|
||||
|
||||
|
||||
@@ -457,7 +476,7 @@ namespace AyaNova
|
||||
apiServerState.SetOpen();
|
||||
|
||||
//final startup log
|
||||
_log.LogInformation("BOOT: COMPLETED - SERVER IS NOW OPEN");
|
||||
_newLog.LogInformation("BOOT: COMPLETED - SERVER IS NOW OPEN");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace AyaNova.Generator
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.LogError("Generate::ProcessJobs resulted in exception error ", ex);
|
||||
log.LogError(ex,"Generate::ProcessJobs result in exception error ");
|
||||
|
||||
}
|
||||
//=================================================================
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using NLog.Extensions.Logging;
|
||||
|
||||
namespace AyaNova.Util
|
||||
{
|
||||
@@ -8,9 +8,17 @@ namespace AyaNova.Util
|
||||
/// </summary>
|
||||
internal static class ApplicationLogging
|
||||
{
|
||||
internal static ILoggerFactory LoggerFactory { get; set; }// = new LoggerFactory();
|
||||
internal static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();
|
||||
internal static ILogger CreateLogger(string categoryName) => LoggerFactory.CreateLogger(categoryName);
|
||||
internal static ILogger theLogger{get;set;}
|
||||
internal static NLogLoggerProvider LoggerProvider { get; set; }// = new LoggerFactory();
|
||||
internal static ILogger CreateLogger<T>() => LoggerProvider.CreateLogger(typeof(T).FullName);
|
||||
//internal static ILogger CreateLogger(string categoryName) => theLogger;
|
||||
internal static ILogger CreateLogger(string categoryName)=> LoggerProvider.CreateLogger(categoryName);
|
||||
|
||||
|
||||
|
||||
// internal static ILoggerFactory LoggerFactory { get; set; }// = new LoggerFactory();
|
||||
// internal static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();
|
||||
// internal static ILogger CreateLogger(string categoryName) => LoggerFactory.CreateLogger(categoryName);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user