added logging for startup issues

This commit is contained in:
Shaun Walker 2021-07-01 07:37:03 -04:00
parent 5268c326a1
commit eea417ff44
16 changed files with 203 additions and 67 deletions

View File

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

View File

@ -14,10 +14,10 @@ using Microsoft.Extensions.Caching.Memory;
using System.Net;
using Oqtane.Repository;
using Microsoft.AspNetCore.Http;
using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Oqtane.Controllers
{
@ -31,8 +31,9 @@ namespace Oqtane.Controllers
private readonly IMemoryCache _cache;
private readonly IHttpContextAccessor _accessor;
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;
_installationManager = installationManager;
@ -41,6 +42,7 @@ namespace Oqtane.Controllers
_cache = cache;
_accessor = accessor;
_aliases = aliases;
_filelogger = filelogger;
}
// POST api/<controller>
@ -138,7 +140,7 @@ namespace Oqtane.Controllers
}
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
{
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
{
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))
{
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
{
@ -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))
{
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
{

View File

@ -58,6 +58,7 @@ namespace Oqtane.Controllers
{
if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions))
{
if (string.IsNullOrEmpty(moduledefinition.Version)) moduledefinition.Version = new Version(1, 0, 0).ToString();
moduledefinitions.Add(moduledefinition);
}
}
@ -81,6 +82,7 @@ namespace Oqtane.Controllers
ModuleDefinition moduledefinition = _moduleDefinitions.GetModuleDefinition(id, SiteId);
if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions))
{
if (string.IsNullOrEmpty(moduledefinition.Version)) moduledefinition.Version = new Version(1, 0, 0).ToString();
return moduledefinition;
}
else
@ -164,6 +166,10 @@ namespace Oqtane.Controllers
if (!string.IsNullOrEmpty(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())
{
try
@ -178,11 +184,20 @@ namespace Oqtane.Controllers
{
_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)
{
_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.Identity;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Oqtane.Infrastructure;
using Oqtane.Modules;
@ -62,7 +63,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton<ISyncManager, SyncManager>();
services.AddSingleton<IDatabaseManager, DatabaseManager>();
services.AddSingleton<IConfigManager, ConfigManager>();
services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
return services;
}

View File

@ -17,7 +17,7 @@ using Oqtane.Repository;
using Oqtane.Shared;
using Oqtane.Enums;
using Newtonsoft.Json;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ConvertToUsingDeclaration
@ -33,14 +33,16 @@ namespace Oqtane.Infrastructure
private readonly IWebHostEnvironment _environment;
private readonly IMemoryCache _cache;
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;
_serviceScopeFactory = serviceScopeFactory;
_environment = environment;
_cache = cache;
_configManager = configManager;
_filelogger = filelogger;
}
public Installation IsInstalled()
@ -137,8 +139,8 @@ namespace Oqtane.Infrastructure
{
if (!string.IsNullOrEmpty(installation.Message))
{
Debug.WriteLine($"Oqtane Error: {installation.Message}");
// problem with prior installation
_filelogger.LogError(Utilities.LogMessage(this, installation.Message));
install.ConnectionString = "";
}
}
@ -641,7 +643,7 @@ namespace Oqtane.Infrastructure
tenant.Version = Constants.Version;
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)
{
Log log = new Log();
if (siteId == -1)
{
log.SiteId = null;
if (_alias != null)
log.SiteId = siteId;
if (log.SiteId == -1 && _alias != null)
{
log.SiteId = _alias.SiteId;
}
}
else
{
log.SiteId = siteId;
}
if (log.SiteId == -1) return; // logs must be site specific
log.PageId = null;
log.ModuleId = null;
log.UserId = null;
@ -125,9 +121,10 @@ namespace Oqtane.Infrastructure
{
_logs.AddLog(log);
}
catch
catch (Exception ex)
{
// 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)
{
// 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":
Upgrade_2_1_0(tenant, scope);
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.Migrations;
using Oqtane.Enums;
@ -15,8 +13,6 @@ namespace Oqtane.Modules
var result = true;
using (dbContext)
{
try
{
var migrator = dbContext.GetService<IMigrator>();
if (migrationType == MigrationType.Down)
@ -28,15 +24,8 @@ namespace Oqtane.Modules
migrator.Migrate();
}
}
catch (Exception ex)
{
Debug.WriteLine($"Oqtane Error: Error Executing Migration - {ex}");
result = false;
}
}
return result;
}
}
}

View File

@ -5,6 +5,8 @@ using Microsoft.AspNetCore;
using Microsoft.Extensions.DependencyInjection;
using Oqtane.Infrastructure;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Oqtane.Shared;
namespace Oqtane.Server
{
@ -13,13 +15,14 @@ namespace Oqtane.Server
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var serviceScope = host.Services.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var databaseManager = serviceScope.ServiceProvider.GetService<IDatabaseManager>();
var databaseManager = host.Services.GetService<IDatabaseManager>();
var install = databaseManager.Install();
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();

View File

@ -159,7 +159,7 @@ namespace Oqtane.Repository
moduledefinition.Name = (!string.IsNullOrEmpty(moduledef.Name)) ? moduledef.Name : moduledefinition.Name;
moduledefinition.Description = (!string.IsNullOrEmpty(moduledef.Description)) ? moduledef.Description : moduledefinition.Description;
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
moduledefs.Remove(moduledef);
}

View File

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

View File

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