diff --git a/gaseous-server/Classes/Config.cs b/gaseous-server/Classes/Config.cs index 0c1eb2a..f33004c 100644 --- a/gaseous-server/Classes/Config.cs +++ b/gaseous-server/Classes/Config.cs @@ -503,11 +503,7 @@ namespace gaseous_server.Classes // log retention in days public int LogRetention = 7; - public enum LoggingFormat - { - Json, - Text - } + public bool AlwaysLogToDisk = false; } } } diff --git a/gaseous-server/Classes/Logging.cs b/gaseous-server/Classes/Logging.cs index 149be8c..65218ab 100644 --- a/gaseous-server/Classes/Logging.cs +++ b/gaseous-server/Classes/Logging.cs @@ -7,6 +7,7 @@ namespace gaseous_server.Classes { public class Logging { + private static DateTime lastDiskRetentionSweep = DateTime.UtcNow; public static bool WriteToDiskOnly { get; set; } = false; static public void Log(LogType EventType, string ServerProcess, string Message, Exception? ExceptionValue = null, bool LogToDiskOnly = false) @@ -69,6 +70,11 @@ namespace gaseous_server.Classes if (LogToDiskOnly == false) { + if (Config.LoggingConfiguration.AlwaysLogToDisk == true) + { + LogToDisk(logItem, TraceOutput, null); + } + Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); string sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate; INSERT INTO ServerLogs (EventTime, EventType, Process, Message, Exception) VALUES (@EventTime, @EventType, @Process, @Message, @Exception);"; Dictionary dbDict = new Dictionary(); @@ -93,6 +99,22 @@ namespace gaseous_server.Classes LogToDisk(logItem, TraceOutput, null); } } + + if (lastDiskRetentionSweep.AddMinutes(60) < DateTime.UtcNow) + { + // time to delete any old logs + lastDiskRetentionSweep = DateTime.UtcNow; + string[] files = Directory.GetFiles(Config.LogPath); + + foreach (string file in files) + { + FileInfo fi = new FileInfo(file); + if (fi.LastAccessTime < DateTime.Now.AddDays(Config.LoggingConfiguration.LogRetention * -1)) + { + fi.Delete(); + } + } + } } static void LogToDisk(LogItem logItem, string TraceOutput, Exception? exception) @@ -110,22 +132,82 @@ namespace gaseous_server.Classes File.AppendAllText(Config.LogFilePath, TraceOutput); } - static public List GetLogs(long? StartIndex, int PageNumber = 1, int PageSize = 100) + static public List GetLogs(LogsViewModel model) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + Dictionary dbDict = new Dictionary(); + dbDict.Add("StartIndex", model.StartIndex); + dbDict.Add("PageNumber", (model.PageNumber - 1) * model.PageSize); + dbDict.Add("PageSize", model.PageSize); string sql = ""; - if (StartIndex == null) + + List whereClauses = new List(); + + // handle status criteria + if (model.Status != null) { - sql = "SELECT * FROM ServerLogs ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;"; + if (model.Status.Count > 0) + { + List statusWhere = new List(); + for (int i = 0; i < model.Status.Count; i++) + { + string valueName = "@eventtype" + i; + statusWhere.Add(valueName); + dbDict.Add(valueName, (int)model.Status[i]); + } + + whereClauses.Add("EventType IN (" + string.Join(",", statusWhere) + ")"); + } + } + + // handle start date criteria + if (model.StartDateTime != null) + { + dbDict.Add("startdate", model.StartDateTime); + whereClauses.Add("EventTime >= @startdate"); + } + + // handle end date criteria + if (model.EndDateTime != null) + { + dbDict.Add("enddate", model.EndDateTime); + whereClauses.Add("EventTime <= @enddate"); + } + + // handle search text criteria + if (model.SearchText != null) + { + if (model.SearchText.Length > 0) + { + dbDict.Add("messageSearch", model.SearchText); + whereClauses.Add("MATCH(Message) AGAINST (@messageSearch)"); + } + } + + // compile WHERE clause + string whereClause = ""; + if (whereClauses.Count > 0) + { + whereClause = "(" + String.Join(" AND ", whereClauses) + ")"; + } + + // execute query + if (model.StartIndex == null) + { + if (whereClause.Length > 0) + { + whereClause = "WHERE " + whereClause; + } + sql = "SELECT * FROM ServerLogs " + whereClause + " ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;"; } else { - sql = "SELECT * FROM ServerLogs WHERE Id < @StartIndex ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;"; + if (whereClause.Length > 0) + { + whereClause = "AND " + whereClause; + } + sql = "SELECT * FROM ServerLogs WHERE Id < @StartIndex " + whereClause + " ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;"; } - Dictionary dbDict = new Dictionary(); - dbDict.Add("StartIndex", StartIndex); - dbDict.Add("PageNumber", (PageNumber - 1) * PageSize); - dbDict.Add("PageSize", PageSize); DataTable dataTable = db.ExecuteCMD(sql, dbDict); List logs = new List(); @@ -175,6 +257,17 @@ namespace gaseous_server.Classes } public string? ExceptionValue { get; set; } } + + public class LogsViewModel + { + public long? StartIndex { get; set; } + public int PageNumber { get; set; } = 1; + public int PageSize { get; set; } = 100; + public List Status { get; set; } = new List(); + public DateTime? StartDateTime { get; set; } + public DateTime? EndDateTime { get; set; } + public string? SearchText { get; set; } + } } } diff --git a/gaseous-server/Controllers/V1.0/LogsController.cs b/gaseous-server/Controllers/V1.0/LogsController.cs index e9e00a9..d0e2220 100644 --- a/gaseous-server/Controllers/V1.0/LogsController.cs +++ b/gaseous-server/Controllers/V1.0/LogsController.cs @@ -17,11 +17,11 @@ namespace gaseous_server.Controllers { [MapToApiVersion("1.0")] [MapToApiVersion("1.1")] - [HttpGet] + [HttpPost] [ProducesResponseType(StatusCodes.Status200OK)] - public List Logs(long? StartIndex, int PageNumber = 1, int PageSize = 100) + public List Logs(Logging.LogsViewModel model) { - return Logging.GetLogs(StartIndex, PageNumber, PageSize); + return Logging.GetLogs(model); } } } \ No newline at end of file diff --git a/gaseous-server/Controllers/V1.0/SystemController.cs b/gaseous-server/Controllers/V1.0/SystemController.cs index 5283d80..613a3c9 100644 --- a/gaseous-server/Controllers/V1.0/SystemController.cs +++ b/gaseous-server/Controllers/V1.0/SystemController.cs @@ -179,6 +179,40 @@ namespace gaseous_server.Controllers return Ok(); } + [MapToApiVersion("1.0")] + [MapToApiVersion("1.1")] + [HttpGet] + [Route("Settings/System")] + [Authorize(Roles = "Admin")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetSystemSettings() + { + SystemSettingsModel systemSettingsModel = new SystemSettingsModel{ + AlwaysLogToDisk = Config.LoggingConfiguration.AlwaysLogToDisk, + MinimumLogRetentionPeriod = Config.LoggingConfiguration.LogRetention + }; + + return Ok(systemSettingsModel); + } + + [MapToApiVersion("1.0")] + [MapToApiVersion("1.1")] + [HttpPost] + [Route("Settings/System")] + [Authorize(Roles = "Admin")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult SetSystemSettings(SystemSettingsModel model) + { + if (ModelState.IsValid) + { + Config.LoggingConfiguration.AlwaysLogToDisk = model.AlwaysLogToDisk; + Config.LoggingConfiguration.LogRetention = model.MinimumLogRetentionPeriod; + Config.UpdateConfig(); + } + + return Ok(model); + } + private SystemInfo.PathItem GetDisk(string Path) { SystemInfo.PathItem pathItem = new SystemInfo.PathItem { @@ -278,4 +312,10 @@ namespace gaseous_server.Controllers public int DefaultInterval { get; set; } public int MinimumAllowedValue { get; set; } } + + public class SystemSettingsModel + { + public bool AlwaysLogToDisk { get; set; } + public int MinimumLogRetentionPeriod { get; set; } + } } \ No newline at end of file diff --git a/gaseous-server/Support/Database/MySQL/gaseous-1007.sql b/gaseous-server/Support/Database/MySQL/gaseous-1007.sql index 23deede..5c4fb42 100644 --- a/gaseous-server/Support/Database/MySQL/gaseous-1007.sql +++ b/gaseous-server/Support/Database/MySQL/gaseous-1007.sql @@ -63,4 +63,7 @@ CREATE TABLE `User_Settings` ( `Id` VARCHAR(128) NOT NULL, `Setting` VARCHAR(45) NOT NULL, `Value` LONGTEXT NULL DEFAULT NULL, - PRIMARY KEY (`Id`, `Setting`)); \ No newline at end of file + PRIMARY KEY (`Id`, `Setting`)); + +ALTER TABLE `ServerLogs` +ADD FULLTEXT INDEX `ft_message` USING BTREE (`Message`) VISIBLE; diff --git a/gaseous-server/wwwroot/pages/settings/logs.html b/gaseous-server/wwwroot/pages/settings/logs.html index f2514c6..051cb43 100644 --- a/gaseous-server/wwwroot/pages/settings/logs.html +++ b/gaseous-server/wwwroot/pages/settings/logs.html @@ -2,7 +2,34 @@

Logs

- + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ +
@@ -14,20 +41,64 @@ \ No newline at end of file diff --git a/gaseous-server/wwwroot/styles/style.css b/gaseous-server/wwwroot/styles/style.css index 6c3e872..851cd4b 100644 --- a/gaseous-server/wwwroot/styles/style.css +++ b/gaseous-server/wwwroot/styles/style.css @@ -223,7 +223,7 @@ h3 { z-index: 1; } -input[type='text'], input[type='number'], input[type="email"], input[type="password"] { +input[type='text'], input[type='number'], input[type="email"], input[type="password"], input[type="datetime-local"] { background-color: #2b2b2b; color: white; padding: 5px;