From f4d1a7b0dbaf4149623da2394be49cd5a566d3fe Mon Sep 17 00:00:00 2001 From: IzyPro <45710398+IzyPro@users.noreply.github.com> Date: Fri, 22 Mar 2024 13:34:40 +0100 Subject: [PATCH 1/5] fix: Fixed sub-folder app.UseBasePath() issue (https://github.com/IzyPro/WatchDog/issues/130) --- WatchDog/src/WatchDog.cs | 6 +++++- WatchDogCompleteApiNet6/Program.cs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/WatchDog/src/WatchDog.cs b/WatchDog/src/WatchDog.cs index 05c0252..2c14d0b 100644 --- a/WatchDog/src/WatchDog.cs +++ b/WatchDog/src/WatchDog.cs @@ -36,7 +36,11 @@ public WatchDog(WatchDogOptionsModel options, RequestDelegate next, IBroadcastHe public async Task InvokeAsync(HttpContext context) { - var requestPath = context.Request.Path.ToString().Remove(0,1); + var requestPath = context.Request.Path.ToString(); + + if(requestPath.StartsWith('/')) + requestPath = requestPath.Remove(0,1); + if (!requestPath.Contains("WTCHDwatchpage") && !requestPath.Contains("watchdog") && !requestPath.Contains("WTCHDGstatics") && diff --git a/WatchDogCompleteApiNet6/Program.cs b/WatchDogCompleteApiNet6/Program.cs index 0b82874..e84757f 100644 --- a/WatchDogCompleteApiNet6/Program.cs +++ b/WatchDogCompleteApiNet6/Program.cs @@ -25,7 +25,7 @@ builder.Services.AddSwaggerGen(); var app = builder.Build(); - +app.UsePathBase("/sub"); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { @@ -45,7 +45,7 @@ { conf.WatchPageUsername = "admin"; conf.WatchPagePassword = "Qwerty@123"; - conf.Blacklist = "/auth"; + conf.Blacklist = "/auth, user"; }); app.Run(); From 2f26e740a078e30b2e086d11d1c91e2772c5f513 Mon Sep 17 00:00:00 2001 From: IzyPro <45710398+IzyPro@users.noreply.github.com> Date: Fri, 22 Mar 2024 14:25:01 +0100 Subject: [PATCH 2/5] fix: potential workaround for litedb issue (https://github.com/IzyPro/WatchDog/issues/137) --- WatchDog.sln | 8 +++- WatchDog/src/Helpers/PaginatedEnumerable.cs | 2 +- .../Controllers/WeatherForecastController.cs | 36 +++++++++++++++ WatchDogCompleteTestApiNet8/Program.cs | 35 +++++++++++++++ .../Properties/launchSettings.json | 41 ++++++++++++++++++ .../WatchDogCompleteTestApiNet8.csproj | 15 +++++++ .../WatchDogCompleteTestApiNet8.http | 6 +++ .../WeatherForecast.cs | 13 ++++++ .../appsettings.Development.json | 8 ++++ WatchDogCompleteTestApiNet8/appsettings.json | 9 ++++ WatchDogCompleteTestApiNet8/watchlogs-log.db | Bin 0 -> 114688 bytes WatchDogCompleteTestApiNet8/watchlogs.db | Bin 0 -> 8192 bytes 12 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs create mode 100644 WatchDogCompleteTestApiNet8/Program.cs create mode 100644 WatchDogCompleteTestApiNet8/Properties/launchSettings.json create mode 100644 WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj create mode 100644 WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.http create mode 100644 WatchDogCompleteTestApiNet8/WeatherForecast.cs create mode 100644 WatchDogCompleteTestApiNet8/appsettings.Development.json create mode 100644 WatchDogCompleteTestApiNet8/appsettings.json create mode 100644 WatchDogCompleteTestApiNet8/watchlogs-log.db create mode 100644 WatchDogCompleteTestApiNet8/watchlogs.db diff --git a/WatchDog.sln b/WatchDog.sln index 7b82fe9..e197d7e 100644 --- a/WatchDog.sln +++ b/WatchDog.sln @@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteTestAPI", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteApiNet6", "WatchDogCompleteApiNet6\WatchDogCompleteApiNet6.csproj", "{B0EA2031-4C36-442F-BC82-618AB0A5DA16}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchDogCompleteMVCTest", "WatchDogCompleteMVCTest\WatchDogCompleteMVCTest.csproj", "{0DCCA957-8A36-405D-8092-233A3759732D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WatchDogCompleteMVCTest", "WatchDogCompleteMVCTest\WatchDogCompleteMVCTest.csproj", "{0DCCA957-8A36-405D-8092-233A3759732D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchDogCompleteTestApiNet8", "WatchDogCompleteTestApiNet8\WatchDogCompleteTestApiNet8.csproj", "{BE9CC5C0-2F4F-4E8C-ADF1-5B2FE83AE13B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,6 +35,10 @@ Global {0DCCA957-8A36-405D-8092-233A3759732D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DCCA957-8A36-405D-8092-233A3759732D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0DCCA957-8A36-405D-8092-233A3759732D}.Release|Any CPU.Build.0 = Release|Any CPU + {BE9CC5C0-2F4F-4E8C-ADF1-5B2FE83AE13B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE9CC5C0-2F4F-4E8C-ADF1-5B2FE83AE13B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE9CC5C0-2F4F-4E8C-ADF1-5B2FE83AE13B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE9CC5C0-2F4F-4E8C-ADF1-5B2FE83AE13B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/WatchDog/src/Helpers/PaginatedEnumerable.cs b/WatchDog/src/Helpers/PaginatedEnumerable.cs index 51dd2bf..ac2fa04 100644 --- a/WatchDog/src/Helpers/PaginatedEnumerable.cs +++ b/WatchDog/src/Helpers/PaginatedEnumerable.cs @@ -41,7 +41,7 @@ public static Page ToPaginatedList(this IFindFluent source, int page public static Page ToPaginatedList(this ILiteQueryable source, int pageIndex, int pageSize = Constants.PageSize) { var count = source.LongCount(); - var items = source.Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToEnumerable(); + var items = source.Skip((pageIndex - 1) * pageSize).Limit(pageSize).ToList(); return new Page(items, count, pageIndex, pageSize); } } diff --git a/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs b/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..2376c8d --- /dev/null +++ b/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs @@ -0,0 +1,36 @@ +using Microsoft.AspNetCore.Mvc; +using WatchDog; + +namespace WatchDogCompleteTestApiNet8.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + WatchLogger.Log(".....INFO......"); + WatchLogger.LogError("........ERROR......"); + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/WatchDogCompleteTestApiNet8/Program.cs b/WatchDogCompleteTestApiNet8/Program.cs new file mode 100644 index 0000000..b9e473a --- /dev/null +++ b/WatchDogCompleteTestApiNet8/Program.cs @@ -0,0 +1,35 @@ +using WatchDog; +using WatchDog.src.Enums; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +//builder.Services.AddWatchDogServices(); +builder.Services.AddWatchDogServices(opt => { opt.IsAutoClear = true; opt.SetExternalDbConnString = "Server=(localdb)\\mssqllocaldb;Database=test;Trusted_Connection=True;"; opt.DbDriverOption = WatchDogDbDriverEnum.MSSQL; }); + +var app = builder.Build(); + +app.UseWatchDogExceptionLogger(); +// Configure the HTTP request pipeline. +app.UseSwagger(); +app.UseSwaggerUI(); + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.UseWatchDog(conf => +{ + conf.WatchPageUsername = "admin"; + conf.WatchPagePassword = "Qwerty@123"; + conf.Blacklist = "/auth, user"; +}); + +app.MapControllers(); + +app.Run(); diff --git a/WatchDogCompleteTestApiNet8/Properties/launchSettings.json b/WatchDogCompleteTestApiNet8/Properties/launchSettings.json new file mode 100644 index 0000000..bd01240 --- /dev/null +++ b/WatchDogCompleteTestApiNet8/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:42324", + "sslPort": 44361 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5289", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7239;http://localhost:5289", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj b/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj new file mode 100644 index 0000000..515a8a4 --- /dev/null +++ b/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + true + + + + + + + + diff --git a/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.http b/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.http new file mode 100644 index 0000000..e615340 --- /dev/null +++ b/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.http @@ -0,0 +1,6 @@ +@WatchDogCompleteTestApiNet8_HostAddress = http://localhost:5289 + +GET {{WatchDogCompleteTestApiNet8_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/WatchDogCompleteTestApiNet8/WeatherForecast.cs b/WatchDogCompleteTestApiNet8/WeatherForecast.cs new file mode 100644 index 0000000..0a71e18 --- /dev/null +++ b/WatchDogCompleteTestApiNet8/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace WatchDogCompleteTestApiNet8 +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/WatchDogCompleteTestApiNet8/appsettings.Development.json b/WatchDogCompleteTestApiNet8/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/WatchDogCompleteTestApiNet8/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/WatchDogCompleteTestApiNet8/appsettings.json b/WatchDogCompleteTestApiNet8/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/WatchDogCompleteTestApiNet8/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/WatchDogCompleteTestApiNet8/watchlogs-log.db b/WatchDogCompleteTestApiNet8/watchlogs-log.db new file mode 100644 index 0000000000000000000000000000000000000000..3997b3204ecefac60e07cbd1b23ba625cfe8502e GIT binary patch literal 114688 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 literal 0 HcmV?d00001 From cb729fefcf9b5b6b492079dfe3c0f373602bb7f5 Mon Sep 17 00:00:00 2001 From: khelechy Date: Mon, 25 Mar 2024 11:01:05 +0100 Subject: [PATCH 3/5] made fixes to searches on sql, and added checks for newer logs to follow search and filter rule --- WatchDog/src/Helpers/SQLDbHelper.cs | 16 +++-- WatchDog/src/WatchPage/index.html | 92 +++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/WatchDog/src/Helpers/SQLDbHelper.cs b/WatchDog/src/Helpers/SQLDbHelper.cs index 3c4e69e..33eb11e 100644 --- a/WatchDog/src/Helpers/SQLDbHelper.cs +++ b/WatchDog/src/Helpers/SQLDbHelper.cs @@ -12,6 +12,9 @@ internal static class SQLDbHelper // WATCHLOG OPERATIONS public static async Task> GetAllWatchLogs(string searchString, string verbString, string statusCode, int pageNumber) { + searchString = searchString?.ToLower(); + verbString = verbString?.ToLower(); + var query = @$"SELECT * FROM {Constants.WatchLogTableName} "; if (!string.IsNullOrEmpty(searchString) || !string.IsNullOrEmpty(verbString) || !string.IsNullOrEmpty(statusCode)) @@ -20,14 +23,14 @@ public static async Task> GetAllWatchLogs(string searchString, st if (!string.IsNullOrEmpty(searchString)) { if(GeneralHelper.IsPostgres()) - query += $"({nameof(WatchLog.Path)} LIKE '%{searchString}%' OR {nameof(WatchLog.Method)} LIKE '%{searchString}%' OR {nameof(WatchLog.ResponseStatus)}::text LIKE '%{searchString}%' OR {nameof(WatchLog.QueryString)} LIKE '%{searchString}%')" + (string.IsNullOrEmpty(statusCode) && string.IsNullOrEmpty(verbString) ? "" : " AND "); + query += $"(LOWER( {nameof(WatchLog.Path)} ) LIKE '%{searchString}%' OR LOWER( {nameof(WatchLog.Method)} ) LIKE '%{searchString}%' OR {nameof(WatchLog.ResponseStatus)}::text LIKE '%{searchString}%' OR LOWER( {nameof(WatchLog.QueryString)} ) LIKE '%{searchString}%')" + (string.IsNullOrEmpty(statusCode) && string.IsNullOrEmpty(verbString) ? "" : " AND "); else - query += $"({nameof(WatchLog.Path)} LIKE '%{searchString}%' OR {nameof(WatchLog.Method)} LIKE '%{searchString}%' OR {nameof(WatchLog.ResponseStatus)} LIKE '%{searchString}%' OR {nameof(WatchLog.QueryString)} LIKE '%{searchString}%')" + (string.IsNullOrEmpty(statusCode) && string.IsNullOrEmpty(verbString) ? "" : " AND "); + query += $"(LOWER( {nameof(WatchLog.Path)} ) LIKE '%{searchString}%' OR LOWER( {nameof(WatchLog.Method)} ) LIKE '%{searchString}%' OR {nameof(WatchLog.ResponseStatus)} LIKE '%{searchString}%' OR LOWER( {nameof(WatchLog.QueryString)} ) LIKE '%{searchString}%')" + (string.IsNullOrEmpty(statusCode) && string.IsNullOrEmpty(verbString) ? "" : " AND "); } if (!string.IsNullOrEmpty(verbString)) { - query += $"{nameof(WatchLog.Method)} LIKE '%{verbString}%' " + (string.IsNullOrEmpty(statusCode) ? "" : "AND "); + query += $"LOWER( {nameof(WatchLog.Method)} ) LIKE '%{verbString}%' " + (string.IsNullOrEmpty(statusCode) ? "" : "AND "); } if (!string.IsNullOrEmpty(statusCode)) @@ -91,7 +94,7 @@ public static async Task> GetAllWatchExceptionLogs(strin if (!string.IsNullOrEmpty(searchString)) { searchString = searchString.ToLower(); - query += $"WHERE {nameof(WatchExceptionLog.Source)} LIKE '%{searchString}%' OR {nameof(WatchExceptionLog.Message)} LIKE '%{searchString}%' OR {nameof(WatchExceptionLog.StackTrace)} LIKE '%{searchString}%' "; + query += $"WHERE LOWER ( {nameof(WatchExceptionLog.Source)} ) LIKE '%{searchString}%' OR LOWER ( {nameof(WatchExceptionLog.Message)} ) LIKE '%{searchString}%' OR LOWER( {nameof(WatchExceptionLog.StackTrace)} ) LIKE '%{searchString}%' "; } query += $"ORDER BY {nameof(WatchExceptionLog.Id)} DESC"; using (var connection = ExternalDbContext.CreateSQLConnection()) @@ -142,12 +145,13 @@ public static async Task> GetAllLogs(string searchString, if (!string.IsNullOrEmpty(searchString)) { searchString = searchString.ToLower(); - query += $"{nameof(WatchLoggerModel.CallingFrom)} LIKE '%{searchString}%' OR {nameof(WatchLoggerModel.CallingMethod)} LIKE '%{searchString}%' OR {nameof(WatchLoggerModel.Message)} LIKE '%{searchString}%' OR {nameof(WatchLoggerModel.EventId)} LIKE '%{searchString}%' " + (string.IsNullOrEmpty(logLevelString) ? "" : "AND "); + query += $"LOWER( {nameof(WatchLoggerModel.CallingFrom)} ) LIKE '%{searchString}%' OR LOWER( {nameof(WatchLoggerModel.CallingMethod)} ) LIKE '%{searchString}%' OR LOWER ( {nameof(WatchLoggerModel.Message)} ) LIKE '%{searchString}%' OR {nameof(WatchLoggerModel.EventId)} LIKE '%{searchString}%' " + (string.IsNullOrEmpty(logLevelString) ? "" : "AND "); } if (!string.IsNullOrEmpty(logLevelString)) { - query += $"{nameof(WatchLoggerModel.LogLevel)} LIKE '%{logLevelString}%' "; + logLevelString = logLevelString?.ToLower(); + query += $"LOWER( {nameof(WatchLoggerModel.LogLevel)} ) LIKE '%{logLevelString}%' "; } query += $"ORDER BY {nameof(WatchLoggerModel.Id)} DESC"; diff --git a/WatchDog/src/WatchPage/index.html b/WatchDog/src/WatchPage/index.html index e53b8ce..2781c3e 100644 --- a/WatchDog/src/WatchPage/index.html +++ b/WatchDog/src/WatchPage/index.html @@ -544,17 +544,24 @@

Are you sure you want to clear all logs?

const tr = $("" + "" + data.log.method + "" + truncate(data.log.path, 50) + " " + data.log.responseStatus + "" + data.log.timeSpent + "" + moment(data.log.startTime).format('LLL') + ""); tr.on('click', populateModal.bind(null, data.log)); - $('#tableBody').prepend(tr); + if (shouldShowOnFiltered(data.type, data.log)) { + $('#tableBody').prepend(tr); + } + } else if (data.type === "exLog") { const tr = $("" + "" + data.log.source + "" + truncate(data.log.message, 50) + "" + data.log.typeOf + "" + moment(data.log.encounteredAt).format('LLL') + " "); tr.on('click', populateExceptionModal.bind(null, data.log)); - $('#tableBodyEx').prepend(tr); + if (shouldShowOnFiltered(data.type, data.log)) { + $('#tableBodyEx').prepend(tr); + } } else if (data.type === "log") { const tr = $("" + "" + moment(data.log.timestamp).format('LLL') + "" + (data.log.callingFrom ??= '') + "\nLine:" + data.log.lineNumber + "" + (data.log.callingMethod ??= '') + "" + data.log.logLevel + "" + truncate(data.log.message, 50) + " "); tr.on('click', populateInCodeModal.bind(null, data.log)); - $('#tableBodyInCode').prepend(tr); + if (shouldShowOnFiltered(data.type, data.log)) { + $('#tableBodyInCode').prepend(tr); + } } } }) @@ -600,6 +607,83 @@

Are you sure you want to clear all logs?

} }); + function shouldShowOnFiltered(logType, log) { + shouldShow = true + + if (logType === "rqLog") { + // check if searchString, verb and statusCode has a current value + + searchString = $('#searchString').val() + statusCodeString = $('#myStatusCodeDropDown').val() + verbString = $('#myVerbDropDown').val() + + if (!searchString && statusCodeString === "ALL" && verbString === "ALL") { + return true; + } + + searchString = searchString.toLowerCase(); + + if (searchString && (log.path?.toLowerCase().includes(searchString) || log.method?.toLowerCase().includes(searchString) || + (log.queryString && log.queryString?.toLowerCase().includes(searchString)))) { + + shouldShow &= true; + + } + + if (verbString !== "ALL") { + if (log.method?.toLowerCase() !== verbString.toLowerCase()) { + shouldShow &= false + } + } + + if (statusCodeString !== "ALL") { + if (log.responseStatus != statusCodeString) { + shouldShow &= false + } + } + + + } else if (logType === "exLog") { + + // check if searchString has a current value + + searchString = $('#exSearchString').val() + + if (!searchString) { + return true; + } + + searchString = searchString.toLowerCase() + if (log.message.toLowerCase().includes(searchString) || log.stackTrace.includes(searchString) || log.source.includes(searchString)) { + return true; + } + + } else if (logType === "log") { + + // check if searchString and logLevelString has a current value + + searchString = $('#inCodeSearchString').val() + logLevelString = $('#myLogLevelDropDown').val() + + if (!searchString && logLevelString === "ALL") { + return true; + } + + searchString = searchString.toLowerCase(); + logLevelString = logLevelString.toLowerCase(); + + if ((searchString && (log.message.toLowerCase().includes(searchString) || log.callingMethod.toLowerCase().includes(searchString) || + log.callingFrom.toLowerCase().includes(searchString) || + (log.eventId && log.eventId.toLowerCase().includes(searchString)))) && (logLevelString !== "ALL" && log.logLevel.toLowerCase() === logLevelString)) + { + return true; + } + + } + + return shouldShow + } + function getLogs(searchString = "", verb = "", statusCode = "") { $('#rqLoader').show(); $.ajax({ @@ -778,7 +862,7 @@

Are you sure you want to clear all logs?

function filterLogLevel(logLevelString) { inCodePageIndex = 1; $('#tableBodyInCode').empty(); - getInCodeLogs($('#searchString').val(), logLevelString); + getInCodeLogs($('#inCodeSearchString').val(), logLevelString); } function nextPage() { From 5282bc4a158b17646b6ae8d9d4099ee701f97b2e Mon Sep 17 00:00:00 2001 From: IzyPro <45710398+IzyPro@users.noreply.github.com> Date: Fri, 29 Mar 2024 14:28:40 +0100 Subject: [PATCH 4/5] feat: official support for .net8 feat: support for UseOutputcache (https://github.com/IzyPro/WatchDog/issues/136) --- WatchDog/WatchDog.csproj | 4 +++- WatchDog/WatchDogExtension.cs | 6 +++++- WatchDog/src/Models/WatchDogOptionsModel.cs | 1 + .../Controllers/WeatherForecastController.cs | 2 ++ WatchDogCompleteTestApiNet8/Program.cs | 4 +++- .../WatchDogCompleteTestApiNet8.csproj | 5 ++++- 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/WatchDog/WatchDog.csproj b/WatchDog/WatchDog.csproj index 962858e..7c4fb27 100644 --- a/WatchDog/WatchDog.csproj +++ b/WatchDog/WatchDog.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;net6.0 + netcoreapp3.1;net6.0;net8.0 WatchDog is a Realtime Message, Event, HTTP (Request & Response) and Exception logger and viewer for ASP.Net Core Web Apps and APIs. It allows developers log and view messages, events, http requests made to their web application and also exception caught during runtime in their web applications, all in Realtime. It leverages SignalR for real-time monitoring and LiteDb a Serverless MongoDB-like database with no configuration with the option of using your external databases. https://github.com/IzyPro/WatchDog favicon.png @@ -53,6 +53,7 @@ + @@ -60,6 +61,7 @@ + diff --git a/WatchDog/WatchDogExtension.cs b/WatchDog/WatchDogExtension.cs index e6c4597..aa8d111 100644 --- a/WatchDog/WatchDogExtension.cs +++ b/WatchDog/WatchDogExtension.cs @@ -118,6 +118,11 @@ public static IApplicationBuilder UseWatchDog(this IApplicationBuilder app, Acti if (!string.IsNullOrEmpty(options.CorsPolicy)) app.UseCors(options.CorsPolicy); + #if NET8_0_OR_GREATER + if (options.UseOutputCache) + app.UseOutputCache(); + #endif + return app.UseEndpoints(endpoints => { endpoints.MapHub("/wtchdlogger"); @@ -140,7 +145,6 @@ public static IApplicationBuilder UseWatchDog(this IApplicationBuilder app, Acti public static IFileInfo GetFile() { return Provider.GetFileInfo("src.WatchPage.index.html"); - } public static string GetFolder() diff --git a/WatchDog/src/Models/WatchDogOptionsModel.cs b/WatchDog/src/Models/WatchDogOptionsModel.cs index 50c7f3c..075833a 100644 --- a/WatchDog/src/Models/WatchDogOptionsModel.cs +++ b/WatchDog/src/Models/WatchDogOptionsModel.cs @@ -8,6 +8,7 @@ public class WatchDogOptionsModel public string WatchPagePassword { get; set; } public string Blacklist { get; set; } public string CorsPolicy { get; set; } = string.Empty; + public bool UseOutputCache { get; set; } public WatchDogSerializerEnum Serializer { get; set; } = WatchDogSerializerEnum.Default; } } diff --git a/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs b/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs index 2376c8d..19e47a1 100644 --- a/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs +++ b/WatchDogCompleteTestApiNet8/Controllers/WeatherForecastController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.OutputCaching; using WatchDog; namespace WatchDogCompleteTestApiNet8.Controllers @@ -20,6 +21,7 @@ public WeatherForecastController(ILogger logger) } [HttpGet(Name = "GetWeatherForecast")] + [OutputCache] public IEnumerable Get() { WatchLogger.Log(".....INFO......"); diff --git a/WatchDogCompleteTestApiNet8/Program.cs b/WatchDogCompleteTestApiNet8/Program.cs index b9e473a..2d64bc2 100644 --- a/WatchDogCompleteTestApiNet8/Program.cs +++ b/WatchDogCompleteTestApiNet8/Program.cs @@ -9,6 +9,7 @@ // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +builder.Services.AddOutputCache(); //builder.Services.AddWatchDogServices(); builder.Services.AddWatchDogServices(opt => { opt.IsAutoClear = true; opt.SetExternalDbConnString = "Server=(localdb)\\mssqllocaldb;Database=test;Trusted_Connection=True;"; opt.DbDriverOption = WatchDogDbDriverEnum.MSSQL; }); @@ -22,12 +23,13 @@ app.UseHttpsRedirection(); app.UseAuthorization(); - +app.UseOutputCache(); app.UseWatchDog(conf => { conf.WatchPageUsername = "admin"; conf.WatchPagePassword = "Qwerty@123"; conf.Blacklist = "/auth, user"; + conf.UseOutputCache = true; }); app.MapControllers(); diff --git a/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj b/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj index 515a8a4..7ac8abf 100644 --- a/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj +++ b/WatchDogCompleteTestApiNet8/WatchDogCompleteTestApiNet8.csproj @@ -9,7 +9,10 @@ - + + + + From 5af6db1c0a030fb67f4a836f3a89a3ab2b2b491c Mon Sep 17 00:00:00 2001 From: IzyPro <45710398+IzyPro@users.noreply.github.com> Date: Sat, 30 Mar 2024 09:54:29 +0100 Subject: [PATCH 5/5] feat: regex blacklisting build: prepared readme and proj properties for deployment --- README.md | 29 ++++++++++++--------- WatchDog/WatchDog.csproj | 11 +++++--- WatchDog/src/Models/WatchDogOptionsModel.cs | 1 + WatchDog/src/WatchDog.cs | 17 +++++++++++- WatchDogCompleteTestApiNet8/Program.cs | 4 ++- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 66bb08d..add71d9 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,14 @@ It leverages `SignalR` for real-time monitoring and `LiteDb` a Serverless MongoD ## What's New -- Security Optimization -- Query Filters Fixes and Optimizations -- Package Assembly as DB Name Fix(MongoDB) +- Official support for .NET8 +- Support for .NET8 UseOutputCache +- Blacklisting using Regex +- Bug Fixes ### Breaking Changes -- SqlDriverOption is now DbDriverOption (>= 1.4.0) +- SqlDriverOption is now DbDriverOption (>= v1.4.0) ## Support @@ -43,12 +44,12 @@ It leverages `SignalR` for real-time monitoring and `LiteDb` a Serverless MongoD Install via .NET CLI ```bash -dotnet add package WatchDog.NET --version 1.4.10 +dotnet add package WatchDog.NET --version 1.4.11 ``` Install via Package Manager ```bash -Install-Package WatchDog.NET --version 1.4.10 +Install-Package WatchDog.NET --version 1.4.11 ``` @@ -93,9 +94,9 @@ Add Database Connection String and Choose DbDriver Option ```c# services.AddWatchDogServices(opt => { - opt.IsAutoClear = false; + opt.IsAutoClear = true; opt.SetExternalDbConnString = "Server=localhost;Database=testDb;User Id=postgres;Password=root;"; - opt.DbDriverOption = WatchDogSqlDriverEnum.PostgreSql; + opt.DbDriverOption = WatchDogDbDriverEnum.PostgreSql; }); ``` @@ -127,8 +128,10 @@ app.UseWatchDog(opt => #### Optional Configurations: `Optional` - Blacklist: List of routes, paths or endpoints to be ignored (should be a comma separated string like below). -- Serializer: If not default, specify the type of global json serializer/converter used -- CorsPolicy: Policy Name if project uses CORS +- Serializer: If not default, specify the type of global json serializer/converter used. +- CorsPolicy: Policy Name if project uses CORS. +- UseOutputCache: If your application uses [ASP.NET Output Cache](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/output). This feature is only available for .NET8 and above. +- UseRegexForBlacklisting: Enables the use of Regex to blacklist request routes, paths or endpoints. ```c# app.UseWatchDog(opt => @@ -138,7 +141,9 @@ app.UseWatchDog(opt => //Optional opt.Blacklist = "Test/testPost, api/auth/login"; //Prevent logging for specified endpoints opt.Serializer = WatchDogSerializerEnum.Newtonsoft; //If your project use a global json converter - opt.CorsPolicy = "MyCorsPolicy" + opt.CorsPolicy = "MyCorsPolicy"; + opt.UseOutputCache = true; + opt.UseRegexForBlacklisting = true; }); ``` @@ -210,5 +215,5 @@ Kelechi Onyekwere - [Github](https://github.com/Khelechy) [Twitter](https://twi Israel Ulelu - [Github](https://github.com/IzyPro) [Twitter](https://twitter.com/IzyPro_) - +