|
1 | 1 | using System; |
2 | 2 | using System.Collections.Generic; |
3 | | -using System.Text; |
| 3 | +using Serilog; |
| 4 | +using System.Threading; |
| 5 | +using ReportPortal.Serilog; |
| 6 | +using Bellatrix.Core.logging; |
4 | 7 |
|
5 | 8 | namespace Bellatrix; |
6 | 9 |
|
7 | 10 | public static class Logger |
8 | 11 | { |
9 | | - private static readonly object _lockObject = new object(); |
| 12 | + // ThreadLocal to ensure each test has its own log buffer |
| 13 | + private static readonly ThreadLocal<Dictionary<string, List<string>>> s_logBuffer = new ThreadLocal<Dictionary<string, List<string>>>(() => new Dictionary<string, List<string>>()); |
10 | 14 |
|
11 | | - public static void LogInformation(string message, params object[] args) |
| 15 | + // ThreadLocal to ensure each thread has its own logger configuration |
| 16 | + private static readonly ThreadLocal<ILogger> s_logger = new ThreadLocal<ILogger>(InitializeLogger); |
| 17 | + |
| 18 | + public static ThreadLocal<string> CurrentTestFullName { get; set; } = new ThreadLocal<string>(); |
| 19 | + |
| 20 | + static Logger() |
| 21 | + { |
| 22 | + s_logBuffer = new ThreadLocal<Dictionary<string, List<string>>>(() => new Dictionary<string, List<string>>()); |
| 23 | + s_logger = new ThreadLocal<ILogger>(InitializeLogger); |
| 24 | + } |
| 25 | + |
| 26 | + private static ILogger InitializeLogger() |
12 | 27 | { |
13 | | - lock (_lockObject) |
| 28 | + var loggerConfiguration = new LoggerConfiguration(); |
| 29 | + var settings = ConfigurationService.GetSection<LoggingSettings>(); |
| 30 | + |
| 31 | + if (settings.IsEnabled) |
14 | 32 | { |
15 | | - try |
| 33 | + if (settings.IsConsoleLoggingEnabled) |
| 34 | + { |
| 35 | + loggerConfiguration.WriteTo.Console(outputTemplate: settings.OutputTemplate); |
| 36 | + } |
| 37 | + |
| 38 | + if (settings.IsDebugLoggingEnabled) |
16 | 39 | { |
17 | | - Console.WriteLine(message, args); |
| 40 | + loggerConfiguration.WriteTo.Debug(outputTemplate: settings.OutputTemplate); |
18 | 41 | } |
19 | | - catch |
| 42 | + |
| 43 | + if (settings.IsFileLoggingEnabled) |
20 | 44 | { |
21 | | - // ignore |
| 45 | + loggerConfiguration.WriteTo.File("test-log.txt", rollingInterval: RollingInterval.Day, outputTemplate: settings.OutputTemplate); |
| 46 | + } |
| 47 | + |
| 48 | + if (settings.IsReportPortalLoggingEnabled) |
| 49 | + { |
| 50 | + loggerConfiguration.WriteTo.ReportPortal(); |
22 | 51 | } |
23 | 52 | } |
| 53 | + |
| 54 | + return loggerConfiguration.CreateLogger(); |
24 | 55 | } |
25 | 56 |
|
26 | | - public static void LogWarning(string message, params object[] args) |
| 57 | + // Method to accumulate logs in the buffer per test/thread |
| 58 | + private static void AccumulateLog(string logLevel, string message) |
27 | 59 | { |
28 | | - try |
| 60 | + if (s_logBuffer.Value == null) |
29 | 61 | { |
30 | | - Console.ForegroundColor = ConsoleColor.Yellow; |
31 | | - Console.WriteLine(message, args); |
32 | | - Console.ResetColor(); |
| 62 | + s_logBuffer.Value = new Dictionary<string, List<string>>(); |
33 | 63 | } |
34 | | - catch |
| 64 | + |
| 65 | + if (!s_logBuffer.Value.ContainsKey(CurrentTestFullName.Value)) |
35 | 66 | { |
36 | | - // ignore |
| 67 | + s_logBuffer.Value.Add(CurrentTestFullName.Value, new List<string>()); |
37 | 68 | } |
| 69 | + |
| 70 | + s_logBuffer.Value[CurrentTestFullName.Value].Add(message); |
| 71 | + } |
| 72 | + |
| 73 | + |
| 74 | + public static void LogInformation(string message, params object[] args) |
| 75 | + { |
| 76 | + AccumulateLog("INFO", string.Format(message, args)); |
38 | 77 | } |
39 | 78 |
|
40 | 79 | public static void LogError(string message, params object[] args) |
41 | 80 | { |
42 | | - lock (_lockObject) |
| 81 | + AccumulateLog("ERROR", string.Format(message, args)); |
| 82 | + } |
| 83 | + |
| 84 | + public static void LogWarning(string message, params object[] args) |
| 85 | + { |
| 86 | + AccumulateLog("WARNING", string.Format(message, args)); |
| 87 | + } |
| 88 | + |
| 89 | + // Lock object to ensure thread-safe execution of FlushLogs |
| 90 | + private static readonly object _flushLock = new object(); |
| 91 | + |
| 92 | + public static string GetLogs() |
| 93 | + { |
| 94 | + if (s_logBuffer.Value.ContainsKey(CurrentTestFullName.Value)) |
43 | 95 | { |
44 | | - try |
45 | | - { |
46 | | - Console.Error.WriteLine(message, args); |
47 | | - } |
48 | | - catch |
| 96 | + return string.Join(Environment.NewLine, s_logBuffer.Value[CurrentTestFullName.Value]); |
| 97 | + } |
| 98 | + |
| 99 | + return "⚠️ No log entries captured for this test."; |
| 100 | + } |
| 101 | + |
| 102 | + // Method to print the accumulated logs at the end of the test |
| 103 | + public static void FlushLogs() |
| 104 | + { |
| 105 | + lock (_flushLock) // Ensure that only one thread can execute FlushLogs at a time |
| 106 | + { |
| 107 | + // Check if there's anything to flush for the current test |
| 108 | + if (s_logBuffer.Value.ContainsKey(CurrentTestFullName.Value)) |
49 | 109 | { |
50 | | - // ignore |
| 110 | + // Flush the logs to the configured sinks |
| 111 | + foreach (var log in s_logBuffer.Value[CurrentTestFullName.Value]) |
| 112 | + { |
| 113 | + s_logger.Value.Information(log); // This could be switched to appropriate log levels |
| 114 | + } |
| 115 | + |
| 116 | + // Clear the log buffer after flushing |
| 117 | + s_logBuffer.Value[CurrentTestFullName.Value].Clear(); |
51 | 118 | } |
52 | 119 | } |
53 | 120 | } |
|
0 commit comments