Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added logging for startup issues #1527

Merged
merged 1 commit into from
Jul 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions Oqtane.Client/UI/SiteRouter.razor
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,7 @@
{
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");
}
await Refresh();
}
}

Expand Down
12 changes: 7 additions & 5 deletions Oqtane.Server/Controllers/InstallationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
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
{
Expand All @@ -31,8 +31,9 @@ public class InstallationController : Controller
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;
Expand All @@ -41,6 +42,7 @@ public InstallationController(IConfigManager configManager, IInstallationManager
_cache = cache;
_accessor = accessor;
_aliases = aliases;
_filelogger = filelogger;
}

// POST api/<controller>
Expand Down Expand Up @@ -138,7 +140,7 @@ private byte[] GetAssemblies()
}
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"));
}
}

Expand All @@ -156,7 +158,7 @@ private byte[] GetAssemblies()
}
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"));
}
}
}
Expand All @@ -171,7 +173,7 @@ private byte[] GetAssemblies()
}
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"));
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions Oqtane.Server/Controllers/ModuleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ public string Export(int moduleid)
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
{
Expand All @@ -213,6 +221,14 @@ public bool Import(int moduleid, [FromBody] string content)
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
{
Expand Down
37 changes: 26 additions & 11 deletions Oqtane.Server/Controllers/ModuleDefinitionController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public IEnumerable<ModuleDefinition> Get(string siteid)
{
if (_userPermissions.IsAuthorized(User, PermissionNames.Utilize, moduledefinition.Permissions))
{
if (string.IsNullOrEmpty(moduledefinition.Version)) moduledefinition.Version = new Version(1, 0, 0).ToString();
moduledefinitions.Add(moduledefinition);
}
}
Expand All @@ -81,6 +82,7 @@ public ModuleDefinition Get(int id, string siteid)
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
Expand Down Expand Up @@ -164,25 +166,38 @@ public void Delete(int id, int siteid)
if (!string.IsNullOrEmpty(moduledefinition.ServerManagerType))
{
Type moduletype = Type.GetType(moduledefinition.ServerManagerType);
foreach (Tenant tenant in _tenants.GetTenants())
if (moduletype != null)
{
try
var alias = _tenantManager.GetAlias(); // save current
string result = string.Empty;
foreach (Tenant tenant in _tenants.GetTenants())
{
if (moduletype.GetInterface("IInstallable") != null)
try
{
_tenantManager.SetTenant(tenant.TenantId);
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
((IInstallable)moduleobject).Uninstall(tenant);
if (moduletype.GetInterface("IInstallable") != null)
{
_tenantManager.SetTenant(tenant.TenantId);
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
((IInstallable)moduleobject).Uninstall(tenant);
}
else
{
_sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + ".Uninstall.sql");
}
}
else
catch (Exception ex)
{
_sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + ".Uninstall.sql");
result = "For " + tenant.Name + " " + ex.Message;
}
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "{ModuleDefinitionName} Uninstalled For Tenant {Tenant}", moduledefinition.ModuleDefinitionName, tenant.Name);
}
catch (Exception ex)
_tenantManager.SetAlias(alias); // restore current
if (string.IsNullOrEmpty(result))
{
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "Error Uninstalling {ModuleDefinitionName} For Tenant {Tenant} {Error}", moduledefinition.ModuleDefinitionName, tenant.Name, ex.Message);
_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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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;
Expand Down Expand Up @@ -62,7 +63,7 @@ internal static IServiceCollection AddOqtaneSingletonServices(this IServiceColle
services.AddSingleton<ISyncManager, SyncManager>();
services.AddSingleton<IDatabaseManager, DatabaseManager>();
services.AddSingleton<IConfigManager, ConfigManager>();

services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
return services;
}

Expand Down
10 changes: 6 additions & 4 deletions Oqtane.Server/Infrastructure/DatabaseManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
using Oqtane.Shared;
using Oqtane.Enums;
using Newtonsoft.Json;
using System.Diagnostics;
using Microsoft.Extensions.Logging;

// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ConvertToUsingDeclaration
Expand All @@ -33,14 +33,16 @@ public class DatabaseManager : IDatabaseManager
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()
Expand Down Expand Up @@ -137,8 +139,8 @@ public Installation Install(InstallConfig install)
{
if (!string.IsNullOrEmpty(installation.Message))
{
Debug.WriteLine($"Oqtane Error: {installation.Message}");
// problem with prior installation
_filelogger.LogError(Utilities.LogMessage(this, installation.Message));
install.ConnectionString = "";
}
}
Expand Down Expand Up @@ -641,7 +643,7 @@ private Installation CreateSite(InstallConfig install)
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);
}
}
}
Expand Down
19 changes: 8 additions & 11 deletions Oqtane.Server/Infrastructure/LogManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,14 @@ public void Log(int siteId, LogLevel level, object @class, LogFunction function,
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 = _alias.SiteId;
}
}
else

log.SiteId = siteId;
if (log.SiteId == -1 && _alias != null)
{
log.SiteId = siteId;
log.SiteId = _alias.SiteId;
}
if (log.SiteId == -1) return; // logs must be site specific

log.PageId = null;
log.ModuleId = null;
log.UserId = null;
Expand Down Expand Up @@ -125,9 +121,10 @@ public void Log(Log log)
{
_logs.AddLog(log);
}
catch
catch (Exception ex)
{
// an error occurred writing to the database
var x = ex.Message;
}
}
}
Expand Down
72 changes: 72 additions & 0 deletions Oqtane.Server/Infrastructure/Logging/FileLogger.cs
Original file line number Diff line number Diff line change
@@ -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
}
}
}
}
30 changes: 30 additions & 0 deletions Oqtane.Server/Infrastructure/Logging/FileLoggerProvider.cs
Original file line number Diff line number Diff line change
@@ -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()
{
}
}
}
2 changes: 1 addition & 1 deletion Oqtane.Server/Infrastructure/TenantManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void SetAlias(Alias alias)
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 };
}
}
}
Loading