Merge pull request #1527 from sbwalker/dev

added logging for startup issues
This commit is contained in:
Shaun Walker 2021-07-01 07:32:34 -04:00 committed by GitHub
commit 070e00b735
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 203 additions and 67 deletions

View File

@ -52,17 +52,9 @@
protected override async Task OnParametersSetAsync() protected override async Task OnParametersSetAsync()
{ {
if (PageState == null) if (PageState == null)
{
// misconfigured api calls should not be processed through the router
if (!_absoluteUri.Contains("~/api/"))
{ {
await Refresh(); await Refresh();
} }
else
{
System.Diagnostics.Debug.WriteLine(GetType().FullName + ": Error: API call to " + _absoluteUri + " is not mapped to a Controller");
}
}
} }
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")] [SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]

View File

@ -14,10 +14,10 @@ using Microsoft.Extensions.Caching.Memory;
using System.Net; using System.Net;
using Oqtane.Repository; using Oqtane.Repository;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Diagnostics;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Oqtane.Controllers namespace Oqtane.Controllers
{ {
@ -31,8 +31,9 @@ namespace Oqtane.Controllers
private readonly IMemoryCache _cache; private readonly IMemoryCache _cache;
private readonly IHttpContextAccessor _accessor; private readonly IHttpContextAccessor _accessor;
private readonly IAliasRepository _aliases; private readonly IAliasRepository _aliases;
private readonly ILogger<InstallationController> _filelogger;
public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases) public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases, ILogger<InstallationController> filelogger)
{ {
_configManager = configManager; _configManager = configManager;
_installationManager = installationManager; _installationManager = installationManager;
@ -41,6 +42,7 @@ namespace Oqtane.Controllers
_cache = cache; _cache = cache;
_accessor = accessor; _accessor = accessor;
_aliases = aliases; _aliases = aliases;
_filelogger = filelogger;
} }
// POST api/<controller> // POST api/<controller>
@ -138,7 +140,7 @@ namespace Oqtane.Controllers
} }
else else
{ {
Debug.WriteLine($"Oqtane Error: The Satellite Assembly Folder For {culture} Does Not Exist"); _filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
} }
} }
@ -156,7 +158,7 @@ namespace Oqtane.Controllers
} }
else else
{ {
Debug.WriteLine($"Oqtane Error: Module {instance.ModuleDefinition.ModuleDefinitionName} Dependency {name}.dll Does Not Exist"); _filelogger.LogError(Utilities.LogMessage(this, $"Module {instance.ModuleDefinition.ModuleDefinitionName} Dependency {name}.dll Does Not Exist"));
} }
} }
} }
@ -171,7 +173,7 @@ namespace Oqtane.Controllers
} }
else else
{ {
Debug.WriteLine($"Oqtane Error: Theme {instance.Theme.ThemeName} Dependency {name}.dll Does Not Exist"); _filelogger.LogError(Utilities.LogMessage(this, $"Theme {instance.Theme.ThemeName} Dependency {name}.dll Does Not Exist"));
} }
} }
} }

View File

@ -194,6 +194,14 @@ namespace Oqtane.Controllers
if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit)) if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit))
{ {
content = _modules.ExportModule(moduleid); content = _modules.ExportModule(moduleid);
if (!string.IsNullOrEmpty(content))
{
_logger.Log(LogLevel.Information, this, LogFunction.Read, "Module Content Exported {ModuleId}", moduleid);
}
else
{
_logger.Log(LogLevel.Warning, this, LogFunction.Read, "No Module Content Exported {ModuleId}", moduleid);
}
} }
else else
{ {
@ -213,6 +221,14 @@ namespace Oqtane.Controllers
if (ModelState.IsValid && module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit)) if (ModelState.IsValid && module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit))
{ {
success = _modules.ImportModule(moduleid, content); success = _modules.ImportModule(moduleid, content);
if (success)
{
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Module Content Imported {ModuleId}", moduleid);
}
else
{
_logger.Log(LogLevel.Warning, this, LogFunction.Update, "Module Content Import Failed {ModuleId}", moduleid);
}
} }
else else
{ {

View File

@ -58,6 +58,7 @@ namespace Oqtane.Controllers
{ {
if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions)) if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions))
{ {
if (string.IsNullOrEmpty(moduledefinition.Version)) moduledefinition.Version = new Version(1, 0, 0).ToString();
moduledefinitions.Add(moduledefinition); moduledefinitions.Add(moduledefinition);
} }
} }
@ -81,6 +82,7 @@ namespace Oqtane.Controllers
ModuleDefinition moduledefinition = _moduleDefinitions.GetModuleDefinition(id, SiteId); ModuleDefinition moduledefinition = _moduleDefinitions.GetModuleDefinition(id, SiteId);
if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions)) if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions))
{ {
if (string.IsNullOrEmpty(moduledefinition.Version)) moduledefinition.Version = new Version(1, 0, 0).ToString();
return moduledefinition; return moduledefinition;
} }
else else
@ -164,6 +166,10 @@ namespace Oqtane.Controllers
if (!string.IsNullOrEmpty(moduledefinition.ServerManagerType)) if (!string.IsNullOrEmpty(moduledefinition.ServerManagerType))
{ {
Type moduletype = Type.GetType(moduledefinition.ServerManagerType); Type moduletype = Type.GetType(moduledefinition.ServerManagerType);
if (moduletype != null)
{
var alias = _tenantManager.GetAlias(); // save current
string result = string.Empty;
foreach (Tenant tenant in _tenants.GetTenants()) foreach (Tenant tenant in _tenants.GetTenants())
{ {
try try
@ -178,11 +184,20 @@ namespace Oqtane.Controllers
{ {
_sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + ".Uninstall.sql"); _sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + ".Uninstall.sql");
} }
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "{ModuleDefinitionName} Uninstalled For Tenant {Tenant}", moduledefinition.ModuleDefinitionName, tenant.Name);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "Error Uninstalling {ModuleDefinitionName} For Tenant {Tenant} {Error}", moduledefinition.ModuleDefinitionName, tenant.Name, ex.Message); result = "For " + tenant.Name + " " + ex.Message;
}
}
_tenantManager.SetAlias(alias); // restore current
if (string.IsNullOrEmpty(result))
{
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "{ModuleDefinitionName} Uninstalled For All Tenants", moduledefinition.ModuleDefinitionName);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "Error Uninstalling {ModuleDefinitionName} {Error}", moduledefinition.ModuleDefinitionName, result);
} }
} }
} }

View File

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Modules; using Oqtane.Modules;
@ -62,7 +63,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton<ISyncManager, SyncManager>(); services.AddSingleton<ISyncManager, SyncManager>();
services.AddSingleton<IDatabaseManager, DatabaseManager>(); services.AddSingleton<IDatabaseManager, DatabaseManager>();
services.AddSingleton<IConfigManager, ConfigManager>(); services.AddSingleton<IConfigManager, ConfigManager>();
services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
return services; return services;
} }

View File

@ -17,7 +17,7 @@ using Oqtane.Repository;
using Oqtane.Shared; using Oqtane.Shared;
using Oqtane.Enums; using Oqtane.Enums;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Diagnostics; using Microsoft.Extensions.Logging;
// ReSharper disable MemberCanBePrivate.Global // ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ConvertToUsingDeclaration // ReSharper disable ConvertToUsingDeclaration
@ -33,14 +33,16 @@ namespace Oqtane.Infrastructure
private readonly IWebHostEnvironment _environment; private readonly IWebHostEnvironment _environment;
private readonly IMemoryCache _cache; private readonly IMemoryCache _cache;
private readonly IConfigManager _configManager; private readonly IConfigManager _configManager;
private readonly ILogger<DatabaseManager> _filelogger;
public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager) public DatabaseManager(IConfigurationRoot config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager, ILogger<DatabaseManager> filelogger)
{ {
_config = config; _config = config;
_serviceScopeFactory = serviceScopeFactory; _serviceScopeFactory = serviceScopeFactory;
_environment = environment; _environment = environment;
_cache = cache; _cache = cache;
_configManager = configManager; _configManager = configManager;
_filelogger = filelogger;
} }
public Installation IsInstalled() public Installation IsInstalled()
@ -137,8 +139,8 @@ namespace Oqtane.Infrastructure
{ {
if (!string.IsNullOrEmpty(installation.Message)) if (!string.IsNullOrEmpty(installation.Message))
{ {
Debug.WriteLine($"Oqtane Error: {installation.Message}");
// problem with prior installation // problem with prior installation
_filelogger.LogError(Utilities.LogMessage(this, installation.Message));
install.ConnectionString = ""; install.ConnectionString = "";
} }
} }
@ -641,7 +643,7 @@ namespace Oqtane.Infrastructure
tenant.Version = Constants.Version; tenant.Version = Constants.Version;
tenants.UpdateTenant(tenant); tenants.UpdateTenant(tenant);
if (site != null) log.Log(site.SiteId, LogLevel.Trace, this, LogFunction.Create, "Site Created {Site}", site); if (site != null) log.Log(site.SiteId, Shared.LogLevel.Information, this, LogFunction.Create, "Site Created {Site}", site);
} }
} }
} }

View File

@ -46,18 +46,14 @@ namespace Oqtane.Infrastructure
public void Log(int siteId, LogLevel level, object @class, LogFunction function, Exception exception, string message, params object[] args) public void Log(int siteId, LogLevel level, object @class, LogFunction function, Exception exception, string message, params object[] args)
{ {
Log log = new Log(); Log log = new Log();
if (siteId == -1)
{ log.SiteId = siteId;
log.SiteId = null; if (log.SiteId == -1 && _alias != null)
if (_alias != null)
{ {
log.SiteId = _alias.SiteId; log.SiteId = _alias.SiteId;
} }
} if (log.SiteId == -1) return; // logs must be site specific
else
{
log.SiteId = siteId;
}
log.PageId = null; log.PageId = null;
log.ModuleId = null; log.ModuleId = null;
log.UserId = null; log.UserId = null;
@ -125,9 +121,10 @@ namespace Oqtane.Infrastructure
{ {
_logs.AddLog(log); _logs.AddLog(log);
} }
catch catch (Exception ex)
{ {
// an error occurred writing to the database // an error occurred writing to the database
var x = ex.Message;
} }
} }
} }

View File

@ -0,0 +1,72 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
namespace Oqtane.Infrastructure
{
public class FileLogger : ILogger
{
protected readonly FileLoggerProvider _FileLoggerProvider;
private readonly IWebHostEnvironment _environment;
private readonly IConfigManager _configManager;
public FileLogger(FileLoggerProvider FileLoggerProvider, IWebHostEnvironment environment,IConfigManager configManager)
{
_FileLoggerProvider = FileLoggerProvider;
_environment = environment;
_configManager = configManager;
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return logLevel != LogLevel.None;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (_configManager.GetSetting("Logging:FileLogger:LogLevel:Default", "") == "")
{
_configManager.AddOrUpdateSetting("Logging:FileLogger:LogLevel:Default", "Error", true);
if (logLevel < LogLevel.Error)
{
return;
}
}
if (!IsEnabled(logLevel))
{
return;
}
string folder = Path.Combine(_environment.ContentRootPath, "Content", "Log");
// ensure directory exists
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
var filepath = Path.Combine(folder, "error.log");
var logentry = string.Format("{0} [{1}] {2} {3}", "[" + DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss+00:00") + "]", logLevel.ToString(), formatter(state, exception), exception != null ? exception.StackTrace : "");
try
{
using (var streamWriter = new StreamWriter(filepath, true))
{
streamWriter.WriteLine(logentry);
}
}
catch
{
// error occurred
}
}
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
namespace Oqtane.Infrastructure
{
/// <summary>
/// FileLogger should only be used in scenarios where a database is not available or tenant/site cannot be determined ( ie. during startup )
/// </summary>
[ProviderAlias("FileLogger")]
public class FileLoggerProvider : ILoggerProvider
{
private readonly IWebHostEnvironment _environment;
private readonly IConfigManager _configManager;
public FileLoggerProvider(IWebHostEnvironment environment, IConfigManager configManager)
{
_environment = environment;
_configManager = configManager;
}
public ILogger CreateLogger(string categoryName)
{
return new FileLogger(this, _environment, _configManager);
}
public void Dispose()
{
}
}
}

View File

@ -81,7 +81,7 @@ namespace Oqtane.Infrastructure
public void SetTenant(int tenantId) public void SetTenant(int tenantId)
{ {
// background processes can set the alias using the SiteState service // background processes can set the alias using the SiteState service
_siteState.Alias = new Alias { TenantId = tenantId }; _siteState.Alias = new Alias { TenantId = tenantId, AliasId = -1, SiteId = -1 };
} }
} }
} }

View File

@ -46,6 +46,9 @@ namespace Oqtane.Infrastructure
case "2.1.0": case "2.1.0":
Upgrade_2_1_0(tenant, scope); Upgrade_2_1_0(tenant, scope);
break; break;
case "2.2.0":
Upgrade_2_2_0(tenant, scope);
break;
} }
} }
} }
@ -150,5 +153,15 @@ namespace Oqtane.Infrastructure
} }
} }
private void Upgrade_2_2_0(Tenant tenant, IServiceScope scope)
{
if (tenant.Name == TenantNames.Master)
{
if (_configManager.GetSetting("Logging:LogLevel:Default", "") == "")
{
_configManager.AddOrUpdateSetting("Logging:LogLevel:Default", "Information", true);
}
}
}
} }
} }

View File

@ -1,5 +1,3 @@
using System;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Enums; using Oqtane.Enums;
@ -15,8 +13,6 @@ namespace Oqtane.Modules
var result = true; var result = true;
using (dbContext) using (dbContext)
{
try
{ {
var migrator = dbContext.GetService<IMigrator>(); var migrator = dbContext.GetService<IMigrator>();
if (migrationType == MigrationType.Down) if (migrationType == MigrationType.Down)
@ -28,15 +24,8 @@ namespace Oqtane.Modules
migrator.Migrate(); migrator.Migrate();
} }
} }
catch (Exception ex)
{
Debug.WriteLine($"Oqtane Error: Error Executing Migration - {ex}");
result = false;
}
}
return result; return result;
} }
} }
} }

View File

@ -5,6 +5,8 @@ using Microsoft.AspNetCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Oqtane.Shared;
namespace Oqtane.Server namespace Oqtane.Server
{ {
@ -13,13 +15,14 @@ namespace Oqtane.Server
public static void Main(string[] args) public static void Main(string[] args)
{ {
var host = BuildWebHost(args); var host = BuildWebHost(args);
using (var serviceScope = host.Services.GetRequiredService<IServiceScopeFactory>().CreateScope()) var databaseManager = host.Services.GetService<IDatabaseManager>();
{
var databaseManager = serviceScope.ServiceProvider.GetService<IDatabaseManager>();
var install = databaseManager.Install(); var install = databaseManager.Install();
if (!string.IsNullOrEmpty(install.Message)) if (!string.IsNullOrEmpty(install.Message))
{ {
Debug.WriteLine($"Oqtane Error: {install.Message}"); var filelogger = host.Services.GetRequiredService<ILogger<Program>>();
if (filelogger != null)
{
filelogger.LogError($"[Oqtane.Server.Program.Main] {install.Message}");
} }
} }
host.Run(); host.Run();

View File

@ -159,7 +159,7 @@ namespace Oqtane.Repository
moduledefinition.Name = (!string.IsNullOrEmpty(moduledef.Name)) ? moduledef.Name : moduledefinition.Name; moduledefinition.Name = (!string.IsNullOrEmpty(moduledef.Name)) ? moduledef.Name : moduledefinition.Name;
moduledefinition.Description = (!string.IsNullOrEmpty(moduledef.Description)) ? moduledef.Description : moduledefinition.Description; moduledefinition.Description = (!string.IsNullOrEmpty(moduledef.Description)) ? moduledef.Description : moduledefinition.Description;
moduledefinition.Categories = (!string.IsNullOrEmpty(moduledef.Categories)) ? moduledef.Categories : moduledefinition.Categories; moduledefinition.Categories = (!string.IsNullOrEmpty(moduledef.Categories)) ? moduledef.Categories : moduledefinition.Categories;
moduledefinition.Version = (!string.IsNullOrEmpty(moduledef.Version)) ? moduledef.Version : moduledefinition.Version; moduledefinition.Version = moduledef.Version;
// remove module definition from list as it is already synced // remove module definition from list as it is already synced
moduledefs.Remove(moduledef); moduledefs.Remove(moduledef);
} }

View File

@ -159,10 +159,9 @@ namespace Oqtane.Repository
} }
} }
} }
catch (Exception ex) catch
{ {
// error occurred during import // error occurred during import
string error = ex.Message;
} }
return success; return success;

View File

@ -412,5 +412,10 @@ namespace Oqtane.Shared
return dictionary; return dictionary;
} }
public static string LogMessage(object @class, string message)
{
return $"[{@class.GetType()}] {message}";
}
} }
} }