diff --git a/API/Controllers/SettingsController.cs b/API/Controllers/SettingsController.cs index 7ceb0443a..b0bc941af 100644 --- a/API/Controllers/SettingsController.cs +++ b/API/Controllers/SettingsController.cs @@ -37,6 +37,7 @@ namespace API.Controllers { var settingsDto = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync(); settingsDto.Port = Configuration.GetPort(Program.GetAppSettingFilename()); + settingsDto.LoggingLevel = Configuration.GetLogLevel(Program.GetAppSettingFilename()); return Ok(settingsDto); } @@ -87,6 +88,7 @@ namespace API.Controllers if (setting.Key == ServerSettingKey.LoggingLevel && updateSettingsDto.LoggingLevel + "" != setting.Value) { setting.Value = updateSettingsDto.LoggingLevel + ""; + Configuration.UpdateLogLevel(Program.GetAppSettingFilename(), updateSettingsDto.LoggingLevel); _unitOfWork.SettingsRepository.Update(setting); } } @@ -120,7 +122,7 @@ namespace API.Controllers [HttpGet("log-levels")] public ActionResult> GetLogLevels() { - return Ok(new [] {"Trace", "Debug", "Information", "Warning", "Critical", "None"}); + return Ok(new [] {"Trace", "Debug", "Information", "Warning", "Critical"}); } } } \ No newline at end of file diff --git a/API/Data/Seed.cs b/API/Data/Seed.cs index a80cba4bd..511fb8c1c 100644 --- a/API/Data/Seed.cs +++ b/API/Data/Seed.cs @@ -6,6 +6,7 @@ using API.Constants; using API.Entities; using API.Entities.Enums; using API.Services; +using Kavita.Common; using Microsoft.AspNetCore.Identity; namespace API.Data @@ -38,12 +39,12 @@ namespace API.Data { new() {Key = ServerSettingKey.CacheDirectory, Value = CacheService.CacheDirectory}, new () {Key = ServerSettingKey.TaskScan, Value = "daily"}, - //new () {Key = ServerSettingKey.LoggingLevel, Value = "Information"}, + new () {Key = ServerSettingKey.LoggingLevel, Value = "Information"}, // Not used from DB, but DB is sync with appSettings.json new () {Key = ServerSettingKey.TaskBackup, Value = "weekly"}, new () {Key = ServerSettingKey.BackupDirectory, Value = Path.GetFullPath(Path.Join(Directory.GetCurrentDirectory(), "backups/"))}, - //new () {Key = ServerSettingKey.Port, Value = "5000"}, // TODO: Remove ServerSettingKey + new () {Key = ServerSettingKey.Port, Value = "5000"}, // Not used from DB, but DB is sync with appSettings.json }; - + foreach (var defaultSetting in defaultSettings) { var existing = context.ServerSetting.FirstOrDefault(s => s.Key == defaultSetting.Key); @@ -54,6 +55,16 @@ namespace API.Data } await context.SaveChangesAsync(); + + // Port and LoggingLevel are managed in appSettings.json. Update the DB values to match + var configFile = Program.GetAppSettingFilename(); + context.ServerSetting.FirstOrDefault(s => s.Key == ServerSettingKey.Port).Value = + Configuration.GetPort(configFile) + ""; + context.ServerSetting.FirstOrDefault(s => s.Key == ServerSettingKey.LoggingLevel).Value = + Configuration.GetLogLevel(configFile); + + await context.SaveChangesAsync(); + } } } \ No newline at end of file diff --git a/API/Extensions/ApplicationServiceExtensions.cs b/API/Extensions/ApplicationServiceExtensions.cs index 2169aeb67..b611cf4d6 100644 --- a/API/Extensions/ApplicationServiceExtensions.cs +++ b/API/Extensions/ApplicationServiceExtensions.cs @@ -1,9 +1,11 @@ -using API.Data; +using System; +using API.Data; using API.Helpers; using API.Interfaces; using API.Interfaces.Services; using API.Services; using API.Services.Tasks; +using Kavita.Common; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -29,12 +31,12 @@ namespace API.Extensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - + services.AddDbContext(options => { options.UseSqlite(config.GetConnectionString("DefaultConnection")); - options.EnableSensitiveDataLogging(env.IsDevelopment()); + options.EnableSensitiveDataLogging(env.IsDevelopment() || Configuration.GetLogLevel(Program.GetAppSettingFilename()).Equals("Debug")); }); services.AddLogging(loggingBuilder => diff --git a/API/Program.cs b/API/Program.cs index 8b43951a1..b084c2ef3 100644 --- a/API/Program.cs +++ b/API/Program.cs @@ -64,6 +64,7 @@ namespace API await context.Database.MigrateAsync(); await Seed.SeedRoles(roleManager); await Seed.SeedSettings(context); + } catch (Exception ex) { @@ -107,8 +108,16 @@ namespace API options.BeforeSend = sentryEvent => { if (sentryEvent.Exception != null - && sentryEvent.Exception.Message.Contains("[GetCoverImage] This archive cannot be read:") - && sentryEvent.Exception.Message.Contains("[BookService] ")) + && sentryEvent.Exception.Message.StartsWith("[GetCoverImage]") + && sentryEvent.Exception.Message.StartsWith("[BookService]") + && sentryEvent.Exception.Message.StartsWith("[ExtractArchive]") + && sentryEvent.Exception.Message.StartsWith("[GetSummaryInfo]") + && sentryEvent.Exception.Message.StartsWith("[GetSummaryInfo]") + && sentryEvent.Exception.Message.StartsWith("[GetNumberOfPagesFromArchive]") + && sentryEvent.Exception.Message.Contains("EPUB parsing error") + && sentryEvent.Exception.Message.Contains("Unsupported EPUB version") + && sentryEvent.Exception.Message.Contains("Incorrect EPUB") + && sentryEvent.Exception.Message.Contains("Access is Denied")) { return null; // Don't send this event to Sentry } diff --git a/API/Services/ArchiveService.cs b/API/Services/ArchiveService.cs index 4cd25d2d9..1f99334b7 100644 --- a/API/Services/ArchiveService.cs +++ b/API/Services/ArchiveService.cs @@ -230,7 +230,7 @@ namespace API.Services } catch (Exception ex) { - _logger.LogWarning(ex, "There was an error and prevented thumbnail generation on {EntryName}. Defaulting to no cover image", entryName); + _logger.LogWarning(ex, "[GetCoverImage] There was an error and prevented thumbnail generation on {EntryName}. Defaulting to no cover image", entryName); } return Array.Empty(); @@ -407,7 +407,7 @@ namespace API.Services } catch (Exception e) { - _logger.LogWarning(e, "There was a problem extracting {ArchivePath} to {ExtractPath}",archivePath, extractPath); + _logger.LogWarning(e, "[ExtractArchive] There was a problem extracting {ArchivePath} to {ExtractPath}",archivePath, extractPath); return; } _logger.LogDebug("Extracted archive to {ExtractPath} in {ElapsedMilliseconds} milliseconds", extractPath, sw.ElapsedMilliseconds); diff --git a/Kavita.Common/Configuration.cs b/Kavita.Common/Configuration.cs index 46b23cf77..755e57743 100644 --- a/Kavita.Common/Configuration.cs +++ b/Kavita.Common/Configuration.cs @@ -7,7 +7,7 @@ namespace Kavita.Common { public static class Configuration { - + #region JWT Token public static bool CheckIfJwtTokenSet(string filePath) { try { @@ -29,8 +29,6 @@ namespace Kavita.Common return false; } - - public static bool UpdateJwtToken(string filePath, string token) { try @@ -44,7 +42,8 @@ namespace Kavita.Common return false; } } - + #endregion + #region Port public static bool UpdatePort(string filePath, int port) { if (new OsInfo(Array.Empty()).IsDocker) @@ -64,7 +63,6 @@ namespace Kavita.Common return false; } } - public static int GetPort(string filePath) { const int defaultPort = 5000; @@ -89,5 +87,48 @@ namespace Kavita.Common return defaultPort; } + #endregion + #region LogLevel + public static bool UpdateLogLevel(string filePath, string logLevel) + { + try + { + var currentLevel = GetLogLevel(filePath); + var json = File.ReadAllText(filePath).Replace($"\"Default\": \"{currentLevel}\"", $"\"Default\": \"{logLevel}\""); + File.WriteAllText(filePath, json); + return true; + } + catch (Exception) + { + return false; + } + } + public static string GetLogLevel(string filePath) + { + try { + var json = File.ReadAllText(filePath); + var jsonObj = JsonSerializer.Deserialize(json); + if (jsonObj.TryGetProperty("Logging", out JsonElement tokenElement)) + { + foreach (var property in tokenElement.EnumerateObject()) + { + if (!property.Name.Equals("LogLevel")) continue; + foreach (var logProperty in property.Value.EnumerateObject()) + { + if (logProperty.Name.Equals("Default")) + { + return logProperty.Value.GetString(); + } + } + } + } + } + catch (Exception ex) { + Console.WriteLine("Error writing app settings: " + ex.Message); + } + + return "Information"; + } + #endregion } } \ No newline at end of file