diff --git a/Testers/EonaCat.Logger.Test.Web/EonaCat.Logger.Test.Web.csproj b/Testers/EonaCat.Logger.Test.Web/EonaCat.Logger.Test.Web.csproj
index db0a879..16c3fa4 100644
--- a/Testers/EonaCat.Logger.Test.Web/EonaCat.Logger.Test.Web.csproj
+++ b/Testers/EonaCat.Logger.Test.Web/EonaCat.Logger.Test.Web.csproj
@@ -7,7 +7,12 @@
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/Testers/EonaCat.Logger.Test.Web/Program.cs b/Testers/EonaCat.Logger.Test.Web/Program.cs
index ad98028..d0c0137 100644
--- a/Testers/EonaCat.Logger.Test.Web/Program.cs
+++ b/Testers/EonaCat.Logger.Test.Web/Program.cs
@@ -1,331 +1,406 @@
-using EonaCat.Logger;
-using EonaCat.Logger.EonaCatCoreLogger;
-using EonaCat.Logger.EonaCatCoreLogger.Extensions;
-using EonaCat.Logger.EonaCatCoreLogger.Models;
-using EonaCat.Logger.LogClient;
-using EonaCat.Logger.Managers;
-using EonaCat.Logger.Test.Web;
-using EonaCat.MemoryGuard;
-using EonaCat.Versioning.Helpers;
-using EonaCat.Web.RateLimiter;
-using EonaCat.Web.RateLimiter.Endpoints.Extensions;
-using Logger = EonaCat.Logger.Logger;
-using LogLevel = EonaCat.Logger.LogClient.LogLevel;
-
-MemoryGuard.StartDevelopment();
-
-var builder = WebApplication.CreateBuilder(args);
-int onLogCounter = 0;
-var defaultColor = Console.ForegroundColor;
-
-// Add services to the container.
-Logger logger = new Logger();
-logger.UseLocalTime = true;
-logger.LoggerSettings.Id = "TEST";
-logger.LoggerSettings.LogInfo();
-logger.LoggerSettings.LogWarning();
-logger.LoggerSettings.LogError();
-logger.LoggerSettings.LogCritical();
-logger.LoggerSettings.LogDebug();
-logger.LoggerSettings.LogTrace();
-logger.LoggerSettings.LogTraffic();
-logger.LoggerSettings.OnLog += LoggerSettings_OnLog;
-logger.LoggerSettings.UseMask = true;
-
-// Configure the client
-var centralOptions = new LogCentralOptions
+namespace EonaCat.Logger.Test.Web
{
- ServerUrl = "https://localhost:7282",
- ApiKey = "716a964de381979df4303bf93fc091d3",
- ApplicationName = "MyApp",
- ApplicationVersion = "1.0.0",
- Environment = "Production",
- BatchSize = 50,
- FlushIntervalSeconds = 5
-};
+ using EonaCat.Logger;
+ using EonaCat.Logger.EonaCatCoreLogger;
+ using EonaCat.Logger.EonaCatCoreLogger.Extensions;
+ using EonaCat.Logger.EonaCatCoreLogger.Models;
+ using EonaCat.Logger.LogClient;
+ using EonaCat.Logger.Managers;
+ using EonaCat.Logger.Test.Web;
+ using EonaCat.MemoryGuard;
+ using EonaCat.Versioning.Helpers;
+ using EonaCat.Web.RateLimiter;
+ using EonaCat.Web.RateLimiter.Endpoints.Extensions;
+ using System.Runtime.InteropServices;
-var logClient = new LogCentralClient(centralOptions);
-
-// Create the adapter
-var adapter = new LogCentralEonaCatAdapter(logger.LoggerSettings, logClient);
-
-// Now all EonaCat.Logger logs will be sent to LogCentral automatically
-await logger.LogAsync("This is a test log message sent to LogCentral!", ELogType.INFO).ConfigureAwait(false);
-
-Console.WriteLine(DllInfo.EonaCatVersion);
-Console.WriteLine(VersionHelper.GetInformationalVersion());
-
-var jsonLogger = new JsonFileLoggerProvider().CreateLogger("MyCategory") as JsonFileLogger;
-jsonLogger?.SetContext("CorrelationId", "abc-123");
-jsonLogger?.SetContext("UserId", "john.doe");
-jsonLogger?.LogInformation("User logged in");
-
-void LoggerSettings_OnLog(EonaCatLogMessage message)
-{
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine($"LogCounter: {++onLogCounter} {message}");
- Console.ForegroundColor = defaultColor;
-}
-
-var options = new FileLoggerOptions();
-options.MaxRolloverFiles = 5;
-//options.FileSizeLimit = 1 * 1024 * 1024 / 4;
-options.UseLocalTime = true;
-options.UseMask = true;
-builder.Logging.AddEonaCatFileLogger(fileLoggerOptions: options, filenamePrefix: "web");
-builder.Logging.AddEonaCatConsoleLogger();
-
-TcpLoggerOptions tcpLoggerOptions = new TcpLoggerOptions
-{
- Host = "192.168.1.1",
- Port = 12345,
-};
-
-builder.Logging.AddEonaCatTcpLogger((tcpLoggerOptions) =>
-{
- tcpLoggerOptions.Port = 12345;
- tcpLoggerOptions.Host = "192.168.1.1";
-});
-
-builder.Services.AddRazorPages();
-
-//var rateLimitOptions = new RateLimitOptions
-//{
-// Capacity = 10,
-// Duration = TimeSpan.FromMinutes(1)
-//};
-
-//builder.Services.AddRateLimiting(rateLimitOptions);
-var rateOptions = new RateLimiterOptions();
-rateOptions.OutputLimitMessageAsHtml = false;
-rateOptions.OutputLimitMessageAsXml = false;
-rateOptions.OutputLimitMessageAsJson = true;
-
-rateOptions.AddDefaultConfiguration(config =>
- config.AddIpResolver().AddRule(3, TimeSpan.FromSeconds(10))
-);
-
-RateLimiterMiddleware.OnLimitResponseCreated += RateLimiterMiddlewareOnLimitResponseCreatedAsync;
-
-async void RateLimiterMiddlewareOnLimitResponseCreatedAsync(object? sender, HttpContext httpContext)
-{
- await httpContext.Response.WriteAsync(" THIS IS MY CUSTOM RATE LIMIT MESSAGE").ConfigureAwait(false);
-}
-
-//builder.Services.UseWebRateLimiter(rateOptions);
-builder.Services.UseWebRateLimiter(rateOptions);
-builder.Services.UseWebRateLimiter(rateOptions =>
-{
- // Configures the default rateLimitConfiguration
- rateOptions.AddDefaultConfiguration(rateLimitConfiguration =>
+ public class Program
{
- // throttling is based on request ip
- rateLimitConfiguration.AddIpResolver()
- // add general rules for all ips
- .AddRule(3, TimeSpan.FromSeconds(10)) // 3 requests could be called every 10 seconds
- .AddRule(30, TimeSpan.FromMinutes(1)) // 30 requests could be called every 1 minute
- .AddRule(500, TimeSpan.FromHours(1)); // 500 requests could be called every 1 hour
- });
-});
-builder.Services.AddMemoryCache();
-
-
-var app = builder.Build();
-
-// Configure the HTTP request pipeline.
-if (!app.Environment.IsDevelopment())
-{
- app.UseExceptionHandler("/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
-}
-
-//EonaCat.Web.RateLimiter.RateLimiterOptions options = new EonaCat.Web.RateLimiter.RateLimiterOptions();
-//options.LimitMessage = "FUCKING NOOB!";
-//options.WriteLimitMessageToResponse = true;
-//options.WriteLimitMessageStatusCodeToResponse = true;
-//app.UseRateLimiter(options);
-//RateLimiterMiddleware.OnLimitResponseCreated += RateLimiterMiddleware_OnLimitResponseCreatedAsync;
-//async void RateLimiterMiddleware_OnLimitResponseCreatedAsync(object? sender, HttpContext httpContext)
-//{
-// await httpContext.Response.WriteAsync("THIS IS MY CUSTOM RATE LIMIT MESSAGE");
-//}
-
-//app.UseWebTracer();
-
-app.UseHttpsRedirection();
-app.UseStaticFiles();
-
-app.UseRouting();
-app.UseAuthorization();
-app.UseWebRateLimiter();
-
-app.MapRazorPages().RateLimit();
-
-void RunLoggingExceptionTests()
-{
- var loggerSettings = new LoggerSettings();
- loggerSettings.FileLoggerOptions.UseLocalTime = true;
- loggerSettings.UseLocalTime = true;
- loggerSettings.Id = "TEST";
- loggerSettings.TypesToLog.Add(ELogType.INFO);
-
- var logger = new LogManager(loggerSettings);
- for (var i = 0; i < 10; i++)
- {
- try
+ public static async Task Main(string[] args)
{
- throw new Exception($"Normal Exception {i}");
- }
- catch (Exception exception)
- {
- logger.WriteAsync(exception).ConfigureAwait(false);
- Console.WriteLine($"Normal ExceptionLogged: {i}");
+ var _config = new MemoryGuardConfiguration
+ {
+ MonitoringInterval = TimeSpan.FromSeconds(5),
+ AnalysisInterval = TimeSpan.FromSeconds(10),
+ PredictionInterval = TimeSpan.FromSeconds(15),
+ LeakDetectionThreshold = TimeSpan.FromSeconds(5),
+ SuspiciousObjectThreshold = TimeSpan.FromSeconds(3),
+ CaptureStackTraces = true,
+ EnableAutoRemediation = true,
+ AutoSaveReports = true,
+ MemoryPressureThreshold = 500 * 1024 * 1024, // 500MB
+ BackgroundAnalysisInterval = TimeSpan.FromMinutes(1),
+ OptimizationInterval = TimeSpan.FromMinutes(10),
+ PatternDetectionInterval = TimeSpan.FromMinutes(3)
+ };
+
+ MemoryGuard.Initialize(_config);
+ AllocationInterceptor.Initialize(MemoryGuard.Instance);
+
+ var builder = WebApplication.CreateBuilder(args);
+ int onLogCounter = 0;
+ var defaultColor = Console.ForegroundColor;
+
+ // Add services to the container.
+ Logger logger = new Logger();
+ logger.UseLocalTime = true;
+ logger.LoggerSettings.Id = "TEST";
+ logger.LoggerSettings.LogInfo();
+ logger.LoggerSettings.LogWarning();
+ logger.LoggerSettings.LogError();
+ logger.LoggerSettings.LogCritical();
+ logger.LoggerSettings.LogDebug();
+ logger.LoggerSettings.LogTrace();
+ logger.LoggerSettings.LogTraffic();
+ logger.LoggerSettings.OnLog += LoggerSettings_OnLog;
+ logger.LoggerSettings.UseMask = true;
+
+ // Configure the client
+ var centralOptions = new LogCentralOptions
+ {
+ ServerUrl = "https://localhost:7282",
+ ApiKey = "716a964de381979df4303bf93fc091d3",
+ ApplicationName = "MyApp",
+ ApplicationVersion = "1.0.0",
+ Environment = "Production",
+ BatchSize = 50,
+ FlushIntervalSeconds = 5
+ };
+
+ var logClient = new LogCentralClient(centralOptions);
+
+ // Create the adapter
+ var adapter = new LogCentralEonaCatAdapter(logger.LoggerSettings, logClient);
+
+ // Now all EonaCat.Logger logs will be sent to LogCentral automatically
+ await logger.LogAsync("This is a test log message sent to LogCentral!", ELogType.INFO).ConfigureAwait(false);
+
+ Console.WriteLine(DllInfo.EonaCatVersion);
+ Console.WriteLine(VersionHelper.GetInformationalVersion());
+
+
+ // Generate a memory leak for testing
+ var jsonLogger = new JsonFileLoggerProvider().CreateLogger("MyCategory") as JsonFileLogger;
+ jsonLogger?.SetContext("CorrelationId", "abc-123");
+ jsonLogger?.SetContext("UserId", "john.doe");
+ jsonLogger?.LogInformation("User logged in");
+
+ void LoggerSettings_OnLog(EonaCatLogMessage message)
+ {
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ Console.WriteLine($"LogCounter: {++onLogCounter} {message}");
+ Console.ForegroundColor = defaultColor;
+ }
+
+ var options = new FileLoggerOptions();
+ options.MaxRolloverFiles = 5;
+ //options.FileSizeLimit = 1 * 1024 * 1024 / 4;
+ options.UseLocalTime = true;
+ options.UseMask = true;
+ builder.Logging.AddEonaCatFileLogger(fileLoggerOptions: options, filenamePrefix: "web");
+ builder.Logging.AddEonaCatConsoleLogger();
+
+ TcpLoggerOptions tcpLoggerOptions = new TcpLoggerOptions
+ {
+ Host = "192.168.1.1",
+ Port = 12345,
+ };
+
+ builder.Logging.AddEonaCatTcpLogger((tcpLoggerOptions) =>
+ {
+ tcpLoggerOptions.Port = 12345;
+ tcpLoggerOptions.Host = "192.168.1.1";
+ });
+
+ builder.Services.AddRazorPages();
+
+ //var rateLimitOptions = new RateLimitOptions
+ //{
+ // Capacity = 10,
+ // Duration = TimeSpan.FromMinutes(1)
+ //};
+
+ //builder.Services.AddRateLimiting(rateLimitOptions);
+ var rateOptions = new RateLimiterOptions();
+ rateOptions.OutputLimitMessageAsHtml = false;
+ rateOptions.OutputLimitMessageAsXml = false;
+ rateOptions.OutputLimitMessageAsJson = true;
+
+ rateOptions.AddDefaultConfiguration(config =>
+ config.AddIpResolver().AddRule(3, TimeSpan.FromSeconds(10))
+ );
+
+ RateLimiterMiddleware.OnLimitResponseCreated += RateLimiterMiddlewareOnLimitResponseCreatedAsync;
+
+ async void RateLimiterMiddlewareOnLimitResponseCreatedAsync(object? sender, HttpContext httpContext)
+ {
+ await httpContext.Response.WriteAsync(" THIS IS MY CUSTOM RATE LIMIT MESSAGE").ConfigureAwait(false);
+ }
+
+ //builder.Services.UseWebRateLimiter(rateOptions);
+ builder.Services.UseWebRateLimiter(rateOptions);
+ builder.Services.UseWebRateLimiter(rateOptions =>
+ {
+ // Configures the default rateLimitConfiguration
+ rateOptions.AddDefaultConfiguration(rateLimitConfiguration =>
+ {
+ // throttling is based on request ip
+ rateLimitConfiguration.AddIpResolver()
+ // add general rules for all ips
+ .AddRule(3, TimeSpan.FromSeconds(10)) // 3 requests could be called every 10 seconds
+ .AddRule(30, TimeSpan.FromMinutes(1)) // 30 requests could be called every 1 minute
+ .AddRule(500, TimeSpan.FromHours(1)); // 500 requests could be called every 1 hour
+ });
+ });
+ builder.Services.AddMemoryCache();
+
+
+ var app = builder.Build();
+
+ // Configure the HTTP request pipeline.
+ if (!app.Environment.IsDevelopment())
+ {
+ app.UseExceptionHandler("/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+ }
+
+ //EonaCat.Web.RateLimiter.RateLimiterOptions options = new EonaCat.Web.RateLimiter.RateLimiterOptions();
+ //options.LimitMessage = "FUCKING NOOB!";
+ //options.WriteLimitMessageToResponse = true;
+ //options.WriteLimitMessageStatusCodeToResponse = true;
+ //app.UseRateLimiter(options);
+ //RateLimiterMiddleware.OnLimitResponseCreated += RateLimiterMiddleware_OnLimitResponseCreatedAsync;
+ //async void RateLimiterMiddleware_OnLimitResponseCreatedAsync(object? sender, HttpContext httpContext)
+ //{
+ // await httpContext.Response.WriteAsync("THIS IS MY CUSTOM RATE LIMIT MESSAGE");
+ //}
+
+ //app.UseWebTracer();
+
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
+
+ app.UseRouting();
+ app.UseAuthorization();
+ app.UseWebRateLimiter();
+
+ app.MapRazorPages().RateLimit();
+
+ void RunLoggingExceptionTests()
+ {
+ var loggerSettings = new LoggerSettings();
+ loggerSettings.FileLoggerOptions.UseLocalTime = true;
+ loggerSettings.UseLocalTime = true;
+ loggerSettings.Id = "TEST";
+ loggerSettings.TypesToLog.Add(ELogType.INFO);
+
+ var logger = new LogManager(loggerSettings);
+ for (var i = 0; i < 10; i++)
+ {
+ try
+ {
+ throw new Exception($"Normal Exception {i}");
+ }
+ catch (Exception exception)
+ {
+ logger.WriteAsync(exception).ConfigureAwait(false);
+ Console.WriteLine($"Normal ExceptionLogged: {i}");
+ }
+
+ Task.Delay(1);
+ }
+ }
+
+ MemoryLeakTester.Start(logger);
+ await Task.Run(RunMemoryReportTask).ConfigureAwait(false);
+ await Task.Run(RunMaskTest).ConfigureAwait(false);
+ await Task.Run(RunWebLoggerTestsAsync).ConfigureAwait(false);
+ await Task.Run(RunWebLoggingTests).ConfigureAwait(false);
+ await Task.Run(RunLoggingTestsAsync).ConfigureAwait(false);
+ await Task.Run(RunLoggingExceptionTests).ConfigureAwait(false);
+ await Task.Run(RunWebLoggingExceptionTests).ConfigureAwait(false);
+
+ async void RunMemoryReportTask()
+ {
+ while (true)
+ {
+ await MemoryGuard.PrintReportAsync().ConfigureAwait(false);
+ await Task.Delay(60000).ConfigureAwait(false);
+ Console.ReadKey();
+ }
+ }
+
+ void RunWebLoggingExceptionTests()
+ {
+ for (var i = 0; i < 10; i++)
+ {
+ try
+ {
+ throw new Exception($"WebException {i}");
+ }
+ catch (Exception exception)
+ {
+ app.Logger.LogCritical(exception, "CRITICAL");
+ app.Logger.LogDebug(exception, "DEBUG");
+ app.Logger.LogError(exception, "ERROR");
+ app.Logger.LogTrace(exception, "TRACE");
+ app.Logger.LogWarning(exception, "WARNING");
+ app.Logger.LogInformation(exception, "INFORMATION");
+ Console.WriteLine($"WebExceptionLogged: {i}");
+ }
+
+ Task.Delay(1);
+ }
+ }
+
+ async void RunWebLoggingTests()
+ {
+ if (!Directory.Exists(logger.LogFolder))
+ {
+ Directory.CreateDirectory(logger.LogFolder);
+ }
+
+ for (var i = 0; i < 9000000; i++)
+ {
+ app.Logger.LogInformation($"web-test {i}");
+ using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "test.log"), true))
+ {
+ await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
+ }
+ Console.WriteLine($"WebLogged: {i}");
+ await Task.Delay(1);
+ }
+ }
+
+ async void RunMaskTest()
+ {
+ if (!Directory.Exists(logger.LogFolder))
+ {
+ Directory.CreateDirectory(logger.LogFolder);
+ }
+
+ for (var i = 0; i < 9000000; i++)
+ {
+ var message = $"mask-test {i}";
+ app.Logger.LogInformation("password: test");
+ app.Logger.LogInformation("JWT Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
+ app.Logger.LogInformation("JWT Token2: eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.iOeNU4dAFFeBwNj6qdhdvm-IvDQrTa6R22lQVJVuWJxorJfeQww5Nwsra0PjaOYhAMj9jNMO5YLmud8U7iQ5gJK2zYyepeSuXhfSi8yjFZfRiSkelqSkU19I-Ja8aQBDbqXf2SAWA8mHF8VS3F08rgEaLCyv98fLLH4vSvsJGf6ueZSLKDVXz24rZRXGWtYYk_OYYTVgR1cg0BLCsuCvqZvHleImJKiWmtS0-CymMO4MMjCy_FIl6I56NqLE9C87tUVpo1mT-kbg5cHDD8I7MjCW5Iii5dethB4Vid3mZ6emKjVYgXrtkOQ-JyGMh6fnQxEFN1ft33GX2eRHluK9eg");
+
+ using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "testmask.log"), true))
+ {
+ await file.WriteAsync(message);
+ }
+ Console.WriteLine($"Masked: {i}");
+ await Task.Delay(1);
+ }
+ }
+
+ async Task RunLoggingTestsAsync()
+ {
+ var loggerSettings = new LoggerSettings();
+ loggerSettings.Id = "TEST";
+ loggerSettings.UseLocalTime = true;
+ loggerSettings.FileLoggerOptions.UseLocalTime = true;
+ loggerSettings.TypesToLog.Add(ELogType.INFO);
+ loggerSettings.TypesToLog.Add(ELogType.WARNING);
+ loggerSettings.TypesToLog.Add(ELogType.ERROR);
+ loggerSettings.TypesToLog.Add(ELogType.TRAFFIC);
+ loggerSettings.TypesToLog.Add(ELogType.DEBUG);
+ loggerSettings.LogDebug();
+ loggerSettings.LogInfo();
+ loggerSettings.LogWarning();
+ loggerSettings.LogError();
+ loggerSettings.LogCritical();
+ loggerSettings.LogTrace();
+ loggerSettings.LogTraffic();
+ loggerSettings.FileLoggerOptions.FileSizeLimit = 1024 * 1024 * 1;
+ loggerSettings.FileLoggerOptions.FileNamePrefix = "AllTypes";
+ loggerSettings.FileLoggerOptions.MaxRolloverFiles = 5;
+ var logger = new LogManager(loggerSettings);
+
+ for (var i = 0; i < 9000000; i++)
+ {
+ await logger.WriteAsync($"test to file {i} INFO").ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} CRITICAL", ELogType.CRITICAL).ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} DEBUG", ELogType.DEBUG).ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} ERROR", ELogType.ERROR).ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} TRACE", ELogType.TRACE).ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} TRAFFIC", ELogType.TRAFFIC).ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} WARNING", ELogType.WARNING).ConfigureAwait(false);
+ await logger.WriteAsync($"test to file {i} NONE", ELogType.NONE).ConfigureAwait(false);
+ Console.WriteLine($"Logged: {i}");
+ await Task.Delay(1).ConfigureAwait(false);
+ }
+ }
+
+ async Task RunWebLoggerTestsAsync()
+ {
+ var i = 0;
+ while (true)
+ {
+ i++;
+ await Task.Run(async () =>
+ {
+ await logger.LogAsync($"test via logger {i}").ConfigureAwait(false);
+ await logger.LogAsync($"test via logger {i}", ELogType.CRITICAL).ConfigureAwait(false);
+ await logger.LogAsync($"test via logger {i}", ELogType.DEBUG).ConfigureAwait(false);
+ await logger.LogAsync($"test via logger {i}", ELogType.ERROR).ConfigureAwait(false);
+ await logger.LogAsync($"test via logger {i}", ELogType.TRAFFIC).ConfigureAwait(false);
+ await logger.LogAsync($"test via logger {i}", ELogType.WARNING).ConfigureAwait(false);
+ await logger.LogAsync($"test via logger {i}", ELogType.NONE).ConfigureAwait(false);
+ }).ConfigureAwait(false);
+ await Task.Delay(1).ConfigureAwait(false);
+ }
+ }
+ app.Run();
}
- Task.Delay(1);
- }
-}
-
-await Task.Run(RunMemoryReportTask).ConfigureAwait(false);
-await Task.Run(RunMaskTest).ConfigureAwait(false);
-await Task.Run(RunWebLoggerTestsAsync).ConfigureAwait(false);
-await Task.Run(RunWebLoggingTests).ConfigureAwait(false);
-await Task.Run(RunLoggingTestsAsync).ConfigureAwait(false);
-await Task.Run(RunLoggingExceptionTests).ConfigureAwait(false);
-await Task.Run(RunWebLoggingExceptionTests).ConfigureAwait(false);
-
-async void RunMemoryReportTask()
-{
- while (true)
- {
- await MemoryGuard.PrintReportAsync().ConfigureAwait(false);
- await Task.Delay(60000).ConfigureAwait(false);
- Console.ReadKey();
- }
-}
-
-void RunWebLoggingExceptionTests()
-{
- for (var i = 0; i < 10; i++)
- {
- try
+ private static void Instance_LeakDetected(object? sender, EonaCat.MemoryGuard.EventArguments.MemoryLeakDetectedEventArgs e)
{
- throw new Exception($"WebException {i}");
+ throw new NotImplementedException();
}
- catch (Exception exception)
+ }
+
+ static class MemoryLeakTester
+ {
+ // Rooted forever → GC can never collect
+ private static readonly List _managedLeak = new();
+ private static readonly List _handles = new();
+
+ public static void Start(Logger logger)
{
- app.Logger.LogCritical(exception, "CRITICAL");
- app.Logger.LogDebug(exception, "DEBUG");
- app.Logger.LogError(exception, "ERROR");
- app.Logger.LogTrace(exception, "TRACE");
- app.Logger.LogWarning(exception, "WARNING");
- app.Logger.LogInformation(exception, "INFORMATION");
- Console.WriteLine($"WebExceptionLogged: {i}");
+ // Leak triggered via logging (very realistic)
+ logger.LoggerSettings.OnLog += OnLogLeak;
+
+ // Optional background unmanaged leak
+ StartUnmanagedLeak();
+
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("⚠ MEMORY LEAK TEST ENABLED");
+ Console.ResetColor();
}
- Task.Delay(1);
- }
-}
-
-async void RunWebLoggingTests()
-{
- if (!Directory.Exists(logger.LogFolder))
- {
- Directory.CreateDirectory(logger.LogFolder);
- }
-
- for (var i = 0; i < 9000000; i++)
- {
- app.Logger.LogInformation($"web-test {i}");
- using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "test.log"), true))
+ private static void OnLogLeak(EonaCatLogMessage message)
{
- await file.WriteAsync($"WebLogged: {i}{Environment.NewLine}").ConfigureAwait(false);
+ // 5 MB per log
+ var data = new byte[5_000_000];
+ _managedLeak.Add(data);
+
+ // GCHandle leak (advanced / nasty)
+ _handles.Add(GCHandle.Alloc(data, GCHandleType.Normal));
}
- Console.WriteLine($"WebLogged: {i}");
- await Task.Delay(1);
- }
-}
-async void RunMaskTest()
-{
- if (!Directory.Exists(logger.LogFolder))
- {
- Directory.CreateDirectory(logger.LogFolder);
- }
-
- for (var i = 0; i < 9000000; i++)
- {
- var message = $"mask-test {i}";
- app.Logger.LogInformation("password: test");
- app.Logger.LogInformation("JWT Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
- app.Logger.LogInformation("JWT Token2: eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.iOeNU4dAFFeBwNj6qdhdvm-IvDQrTa6R22lQVJVuWJxorJfeQww5Nwsra0PjaOYhAMj9jNMO5YLmud8U7iQ5gJK2zYyepeSuXhfSi8yjFZfRiSkelqSkU19I-Ja8aQBDbqXf2SAWA8mHF8VS3F08rgEaLCyv98fLLH4vSvsJGf6ueZSLKDVXz24rZRXGWtYYk_OYYTVgR1cg0BLCsuCvqZvHleImJKiWmtS0-CymMO4MMjCy_FIl6I56NqLE9C87tUVpo1mT-kbg5cHDD8I7MjCW5Iii5dethB4Vid3mZ6emKjVYgXrtkOQ-JyGMh6fnQxEFN1ft33GX2eRHluK9eg");
-
- using (var file = new StreamWriter(Path.Combine(logger.LogFolder, "testmask.log"), true))
+ private static void StartUnmanagedLeak()
{
- await file.WriteAsync(message);
+ _ = Task.Run(async () =>
+ {
+ while (true)
+ {
+ Marshal.AllocHGlobal(10_000_000); // 10 MB unmanaged
+ await Task.Delay(500).ConfigureAwait(false);
+ }
+ });
}
- Console.WriteLine($"Masked: {i}");
- await Task.Delay(1);
}
-}
-async Task RunLoggingTestsAsync()
-{
- var loggerSettings = new LoggerSettings();
- loggerSettings.Id = "TEST";
- loggerSettings.UseLocalTime = true;
- loggerSettings.FileLoggerOptions.UseLocalTime = true;
- loggerSettings.TypesToLog.Add(ELogType.INFO);
- loggerSettings.TypesToLog.Add(ELogType.WARNING);
- loggerSettings.TypesToLog.Add(ELogType.ERROR);
- loggerSettings.TypesToLog.Add(ELogType.TRAFFIC);
- loggerSettings.TypesToLog.Add(ELogType.DEBUG);
- loggerSettings.LogDebug();
- loggerSettings.LogInfo();
- loggerSettings.LogWarning();
- loggerSettings.LogError();
- loggerSettings.LogCritical();
- loggerSettings.LogTrace();
- loggerSettings.LogTraffic();
- loggerSettings.FileLoggerOptions.FileSizeLimit = 1024 * 1024 * 1;
- loggerSettings.FileLoggerOptions.FileNamePrefix = "AllTypes";
- loggerSettings.FileLoggerOptions.MaxRolloverFiles = 5;
- var logger = new LogManager(loggerSettings);
-
- for (var i = 0; i < 9000000; i++)
- {
- await logger.WriteAsync($"test to file {i} INFO").ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} CRITICAL", ELogType.CRITICAL).ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} DEBUG", ELogType.DEBUG).ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} ERROR", ELogType.ERROR).ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} TRACE", ELogType.TRACE).ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} TRAFFIC", ELogType.TRAFFIC).ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} WARNING", ELogType.WARNING).ConfigureAwait(false);
- await logger.WriteAsync($"test to file {i} NONE", ELogType.NONE).ConfigureAwait(false);
- Console.WriteLine($"Logged: {i}");
- await Task.Delay(1).ConfigureAwait(false);
- }
-}
-
-async Task RunWebLoggerTestsAsync()
-{
- var i = 0;
- while (true)
- {
- i++;
- await Task.Run(async () =>
- {
- await logger.LogAsync($"test via logger {i}").ConfigureAwait(false);
- await logger.LogAsync($"test via logger {i}", ELogType.CRITICAL).ConfigureAwait(false);
- await logger.LogAsync($"test via logger {i}", ELogType.DEBUG).ConfigureAwait(false);
- await logger.LogAsync($"test via logger {i}", ELogType.ERROR).ConfigureAwait(false);
- await logger.LogAsync($"test via logger {i}", ELogType.TRAFFIC).ConfigureAwait(false);
- await logger.LogAsync($"test via logger {i}", ELogType.WARNING).ConfigureAwait(false);
- await logger.LogAsync($"test via logger {i}", ELogType.NONE).ConfigureAwait(false);
- }).ConfigureAwait(false);
- await Task.Delay(1).ConfigureAwait(false);
- }
-}
-
-app.Run();
\ No newline at end of file
+}
\ No newline at end of file