From f03bf86d31f871caa4a7a67b3a2244a873431d0d Mon Sep 17 00:00:00 2001 From: SHM Date: Thu, 24 Jul 2025 16:00:18 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=84=B1=ED=98=84=EB=AA=A8]=20Log4net=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0,=20LogXnet=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Projects/Config/LogXnetConfig.json | 79 ++++ Projects/DLL/SystemX.Core.dll | Bin 51712 -> 50688 bytes .../dacpac/SystemX.DB.AccountDB.dacpac | Bin 3503 -> 3503 bytes .../SystemX.Core/Communication/Http.cs | 22 +- .../Communication/Socket/Listener.cs | 4 +- .../Communication/Socket/Session.cs | 8 +- .../SystemX.Core/DB/DBTransaction.cs | 14 +- .../SystemX.Core/Log4net/Log4net.cs | 405 ------------------ .../SystemX.Core/LogXnet/ChannelLogger.cs | 171 ++++++++ .../LogXnet/ChannelLoggerProvider.cs | 20 + .../SystemX.Core/LogXnet/LogXLabel.cs | 28 ++ .../SystemX.Core/LogXnet/LogXnet.cs | 162 +++++++ .../SystemX.Core/LogXnet/LogXnetConfig.cs | 30 ++ .../SystemX.Core/Model/Auth/Login.cs | 3 +- .../SystemX.Core/Model/Auth/Logout.cs | 3 +- .../SystemX.Core/Model/Auth/Register.cs | 3 +- .../Services/DBContextProvider.cs | 2 +- .../SystemX.Core/SystemX.Core.csproj | 1 - .../SystemX.Core/Utils/JsonUtils.cs | 6 +- 19 files changed, 521 insertions(+), 440 deletions(-) create mode 100644 Projects/Config/LogXnetConfig.json delete mode 100644 Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLogger.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLoggerProvider.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/LogXnet/LogXLabel.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnet.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnetConfig.cs diff --git a/Projects/Config/LogXnetConfig.json b/Projects/Config/LogXnetConfig.json new file mode 100644 index 0000000..4428544 --- /dev/null +++ b/Projects/Config/LogXnetConfig.json @@ -0,0 +1,79 @@ +{ + "ConsoleEnable": true, + "FileOutputEnable": true, + "TimeStampEnable": true, + "ThreadIdEnable": true, + "AutoRemoveEnable": true, + "OutputFilePath": "/log", + "TimeStampForamt": "yyyy-MM-dd HH:mm:ss.fff", + "AutoRemoveIntervalDay": 10, + "LogLevel": "Debug", + "LogDefines": [ + { + "LogLevel": "DEFAULT", + "LogLabel": "default", + "ForeColorRGB": "#fbebd2" + }, + + { + "LogLevel": "Debug", + "LogLabel": "Debug", + "ForeColorRGB": "#148CFF" + }, + { + "LogLevel": "Debug", + "LogLabel": "Db", + "ForeColorRGB": "#46BEFF" + }, + { + "LogLevel": "Debug", + "LogLabel": "HTTP", + "ForeColorRGB": "#6E6EFF" + }, + { + "LogLevel": "Debug", + "LogLabel": "CONTROLLER", + "ForeColorRGB": "#B4B4FF" + }, + { + "LogLevel": "Debug", + "LogLabel": "SOCKET", + "ForeColorRGB": "#5A78AF" + }, + { + "LogLevel": "Information", + "LogLabel": "Information", + "ForeColorRGB": "22;198;12" + }, + { + "LogLevel": "Information", + "LogLabel": "INFO", + "ForeColorRGB": "#419B4F" + }, + { + "LogLevel": "Warning", + "LogLabel": "Warning", + "ForeColorRGB": "#E1B002" + }, + { + "LogLevel": "Error", + "LogLabel": "Error", + "ForeColorRGB": "#ff0000" + }, + { + "LogLevel": "Error", + "LogLabel": "Exception", + "ForeColorRGB": "255;123;123" + }, + { + "LogLevel": "Critical", + "LogLabel": "Critical", + "ForeColorRGB": "#a70000" + }, + { + "LogLevel": "Critical", + "LogLabel": "Fatal", + "ForeColorRGB": "#FF6347" + } + ] +} \ No newline at end of file diff --git a/Projects/DLL/SystemX.Core.dll b/Projects/DLL/SystemX.Core.dll index cf2421f40ca92a584eeccbf9aa9e50f379c20c08..1e63ab1eeb210f37d4fa1d716773cb6c7e9e67ff 100644 GIT binary patch literal 50688 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 K|Bo-81pW)gys}mR literal 51712 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

XHf9gEINb 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 HeH8c`2nOz| diff --git a/Projects/SystemX.Core/DBPatch/sqlScripts/dacpac/SystemX.DB.AccountDB.dacpac b/Projects/SystemX.Core/DBPatch/sqlScripts/dacpac/SystemX.DB.AccountDB.dacpac index 3dca7fadca116c27294b5cde56dd1bc37797bd01..503d4b35c4f2f021cdcaeacfeca0d6deca17300a 100644 GIT binary patch delta 634 zcmZ24yIwd_q?=iUri?u^oBc9O+&m>1j>&R_9O`rwo+n~dxx^IkZ=_1URytg5LGCTcro zf1E4j&1B#r;qd0xy1vPF0c8uS|1EejQCoS3U2E>6*O9?;KQ_c`N-#UusYW}yuI`?` zxIUz9dUjSuT;S>1O{;e@e$NnDe)d96%J0L^=X{=@dDwXS@tv0Y);-YWvA_0d>%+A# zLp3(O?g_bd_M-H2hH#dp4|eIk+9t|@+#Dj8~p>V-H8e=w>Qb5u{Peb}IN>l4>8 zIfDZRo)Mter1y{RRrcML>+33)JC=J9d%j_`+Hp=l71M zRLiTb2hZKww=coo^WfASe^n2B@qMzN5hck)*+24}Jd^t|IJMOCn1JbRJeFYk6OR=l N^_cJ)fCbZeJpeFwFgO4J delta 615 zcmZ24yJAExu%A`YbXyB%ff@zCrw^INyprYu64A}2F)i`M_XpKZU9=kK}4 z`{rbCs(SR)vHa{8iDM0)T|2L^_O7XTd%OKbS_$KILC3%yimw%xY0pvK#WPLi{Kc-8 zlAU)B@Va!nZfG;))jV_kVA@1|jySiH#>EHhrY-!g@N|;(&eto?MY+dskXL`;b?2W@ s!Y{Q=_fb+vl>OxC+)u$tqn^hEOmE|{1k;~*tPn}Xgx3Hpn9l0~0QLGJUH||9 diff --git a/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs b/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs index 9c92073..6198ff4 100644 --- a/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs +++ b/Projects/SystemX.Core/SystemX.Core/Communication/Http.cs @@ -34,19 +34,19 @@ namespace SystemX.Core.Communication { await Task.Delay(1); try - { - Log4net.WriteLine($"[POST] Request({guid})::{url}{Environment.NewLine}{request?.ToJson()}", LogType.HTTP); + { + LogXnet.WriteLine($"[POST] Request({guid})::{url}{Environment.NewLine}{request?.ToJson()}", LogXLabel.HTTP); DateTime requestTime = DateTime.Now; var res = await httpClient.PostAsJsonAsync(url, request); response = await res.Content.ReadFromJsonAsync(); - Log4net.WriteLine($"[POST] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}{Environment.NewLine}{response?.ToJson()}", LogType.HTTP); + LogXnet.WriteLine($"[POST] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}{Environment.NewLine}{response?.ToJson()}", LogXLabel.HTTP); break; } catch (Exception e) - { - Log4net.WriteLine(e); + { + LogXnet.WriteLine(e); retry += 1; } @@ -79,16 +79,16 @@ namespace SystemX.Core.Communication if (string.IsNullOrEmpty(bearerToken) == false) httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $"{bearerToken}"); - Log4net.WriteLine($"[GET] Request({guid})::{url}", LogType.HTTP); + LogXnet.WriteLine($"[GET] Request({guid})::{url}", LogXLabel.HTTP); DateTime requestTime = DateTime.Now; response = await httpClient.GetFromJsonAsync(url); - Log4net.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogType.HTTP); + LogXnet.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogXLabel.HTTP); } catch (Exception e) { - Log4net.WriteLine(e); + LogXnet.WriteLine(e); } } @@ -112,17 +112,17 @@ namespace SystemX.Core.Communication if (string.IsNullOrEmpty(bearerToken) == false) httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $"{bearerToken}"); - Log4net.WriteLine($"[GET] Request({guid})::{url}", LogType.HTTP); + LogXnet.WriteLine($"[GET] Request({guid})::{url}", LogXLabel.HTTP); DateTime requestTime = DateTime.Now; var response = await httpClient.GetAsync(url); stream = await response.Content.ReadAsStreamAsync(); - Log4net.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogType.HTTP); + LogXnet.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogXLabel.HTTP); } catch (Exception e) { - Log4net.WriteLine(e); + LogXnet.WriteLine(e); } } diff --git a/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs b/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs index a118396..21f3e4b 100644 --- a/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs +++ b/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs @@ -53,12 +53,12 @@ namespace SystemX.Core.Communication } else { - Log4net.WriteLine(args.SocketError.ToString(), LogType.Error); + LogXnet.WriteLine(args.SocketError.ToString(), LogXLabel.Error); } } catch(Exception e) { - Log4net.WriteLine(e, LogType.Error); + LogXnet.WriteLine(e); } RegisterAccept(args); diff --git a/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Session.cs b/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Session.cs index 4013e0c..3f9e858 100644 --- a/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Session.cs +++ b/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Session.cs @@ -138,7 +138,7 @@ namespace SystemX.Core.Communication } catch (Exception e) { - Log4net.WriteLine($"RegisterSend Failed {e}", LogType.Error); + LogXnet.WriteLine($"RegisterSend Failed {e}", LogXLabel.Exception); } } @@ -160,7 +160,7 @@ namespace SystemX.Core.Communication } catch (Exception e) { - Log4net.WriteLine($"OnSendCompleted Failed {e}", LogType.Error); + LogXnet.WriteLine($"OnSendCompleted Failed {e}", LogXLabel.Exception); } } else @@ -187,7 +187,7 @@ namespace SystemX.Core.Communication } catch (Exception e) { - Log4net.WriteLine($"RegisterRecv Failed {e}", LogType.Error); + LogXnet.WriteLine($"RegisterRecv Failed {e}", LogXLabel.Exception); } } @@ -223,7 +223,7 @@ namespace SystemX.Core.Communication } catch (Exception e) { - Log4net.WriteLine($"OnRecvCompleted Failed {e}", LogType.Error); + LogXnet.WriteLine($"OnRecvCompleted Failed {e}", LogXLabel.Exception); } } else diff --git a/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs b/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs index b1ee905..71cc638 100644 --- a/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs +++ b/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs @@ -31,7 +31,7 @@ namespace SystemX.Core.DB } catch (Exception ex) { - Log4net.WriteLine(ex); + LogXnet.WriteLine(ex); } return entity; @@ -52,13 +52,13 @@ namespace SystemX.Core.DB transaction.Commit(); result = true; - Log4net.WriteLine("Transaction Commit", LogType.Debug); + LogXnet.WriteLine("Transaction Commit", LogXLabel.Debug); } catch (Exception ex) { transaction.Rollback(); - Log4net.WriteLine("Transaction Rollback", LogType.Error); - Log4net.WriteLine(ex); + LogXnet.WriteLine("Transaction Rollback", LogXLabel.Exception); + LogXnet.WriteLine(ex); } transaction.Dispose(); @@ -81,13 +81,13 @@ namespace SystemX.Core.DB await transaction.CommitAsync(); result = true; - Log4net.WriteLine("Transaction Commit", LogType.Debug); + LogXnet.WriteLine("Transaction Commit", LogXLabel.Debug); } catch (Exception ex) { await transaction.RollbackAsync(); - Log4net.WriteLine("Transaction Rollback", LogType.Error); - Log4net.WriteLine(ex); + LogXnet.WriteLine("Transaction Rollback", LogXLabel.Exception); + LogXnet.WriteLine(ex); } await transaction.DisposeAsync(); diff --git a/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs b/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs deleted file mode 100644 index 4eb1b00..0000000 --- a/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs +++ /dev/null @@ -1,405 +0,0 @@ -using log4net; -using log4net.Repository; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - - -#region LogType -public enum LogType -{ - //default level - Info = 0, - Warn = 1, - Error = 2, - Debug = 3, - Fatal = 4, - - //custom level - Exception = 7, - - DB = 10, - - HTTP = 20, - SOCKET = 21, - CONTROLLER = 22, -} -#endregion - -#region CustomLevel -public static class Log4netCustomLevel -{ - public static readonly log4net.Core.Level EXCEPTION = new log4net.Core.Level(10007, LogType.Exception.ToString()); - public static readonly log4net.Core.Level DB = new log4net.Core.Level(10010, LogType.DB.ToString()); - public static readonly log4net.Core.Level HTTP = new log4net.Core.Level(10020, LogType.HTTP.ToString()); - public static readonly log4net.Core.Level SOCKET = new log4net.Core.Level(10021, LogType.SOCKET.ToString()); - public static readonly log4net.Core.Level CONTROLLER = new log4net.Core.Level(10022, LogType.CONTROLLER.ToString()); - - public static void SetCustomLevel(ILoggerRepository repo) - { - repo.LevelMap.Add(EXCEPTION); - repo.LevelMap.Add(DB); - repo.LevelMap.Add(HTTP); - repo.LevelMap.Add(SOCKET); - repo.LevelMap.Add(CONTROLLER); - } -} -#endregion - -public static class Log4net -{ - private static ILog? Manager; - - private static ILoggerRepository repo = LogManager.GetRepository(); - - public static bool IsConfigLoad { get; set; } = false; - - public static string Log4netConfigPath { get; } = @"../../Config/log4net.config"; - - //로그 사용여부 - public static bool IsDebugEnabled { get; set; } = true; - public static bool IsDBEnabled { get; set; } = true; - public static bool IsHttpEnabled { get; set; } = true; - public static bool IsSocketEnabled { get; set; } = true; - public static bool IsControllerEnabled { get; set; } = true; - - //자동삭제 - private static bool AutoRemove { get; set; } = false; - private static int AutoRemoveKeepingDay = 30; - - static Log4net() - { - string log4netConfigPath = Log4netConfigPath; - - if (File.Exists(log4netConfigPath) == true) - { - File.Delete(log4netConfigPath); - } - - Console.WriteLine($"Create log4netConfig: {log4netConfigPath}"); - File.WriteAllText(log4netConfigPath, Config); - - IsConfigLoad = OpenConfig(log4netConfigPath); - } - - private static bool OpenConfig(string path) - { - bool result = true; - - try - { - Log4netCustomLevel.SetCustomLevel(repo); - - if (File.Exists(path) == false) - result = false; - - log4net.Config.XmlConfigurator.Configure(new FileInfo(path)); - Manager = LogManager.GetLogger(""); - } - catch (Exception e) - { - Console.WriteLine("Log4net Init Error"); - Console.WriteLine(e.Message); - result = false; - } - - return result; - } - - public static void AutoRemoveLog(int autoRemoveKeepingDay = 30) - { - if (AutoRemove == false) - { - AutoRemove = true; - AutoRemoveKeepingDay = autoRemoveKeepingDay; - - string logDirectory = @$"{Path.GetDirectoryName(Environment.ProcessPath)}\log"; - Log4net.WriteLine($"Log4net Auto Remove: {AutoRemove}, Remove Day: -{AutoRemoveKeepingDay}", LogType.Warn); - Log4net.WriteLine($"Log4net Auto Path: {logDirectory}", LogType.Warn); - - Task.Run(async () => - { - //1분후 시작 - await Task.Delay(TimeSpan.FromMinutes(1)); - while (true) - { - var files = Directory.GetFiles(logDirectory, "*.log", SearchOption.AllDirectories); - foreach (var file in files) - { - var lastAccessDateTime = File.GetLastWriteTime(file); - if (lastAccessDateTime < DateTime.Now.AddDays(AutoRemoveKeepingDay * -1)) - { - try - { - File.Delete(file); - WriteLine($"Remove log: {Path.GetFileName(file)}", LogType.Warn); - } - catch - { - WriteLine($"Using log file: {Path.GetFileName(file)}", LogType.Warn); - } - } - } - - //일정시간마다 반복 - Log4net.WriteLine($"Log Auto Remove Run", LogType.Warn); - await Task.Delay(TimeSpan.FromHours(12)); - } - }); - } - } - - public static void WriteLine(T log, LogType logType = LogType.Info, bool trace = false, - [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", - [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", - [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) - { - if (IsConfigLoad == false) - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine($"[Log4net Initialize Error] {log}"); - return; - } - - if(log is Exception ex) - { - WriteLineException(ex, memberName, sourceFilePath, sourceLineNumber); - return; - } - - string strTrace = $"TRACE::[{Path.GetFileName(sourceFilePath)}][Method:{memberName}][LINE:{sourceLineNumber}]"; - - switch (logType) - { - case LogType.Info: - { - if (trace == true) - { - Manager?.Info($"{strTrace}"); - } - Manager?.Info(log); - break; - } - case LogType.Warn: - { - if (trace == true) - { - Manager?.Warn($"{strTrace}"); - } - Manager?.Warn(log); - break; - } - case LogType.Error: - { - if (trace == true) - { - Manager?.Error($"{strTrace}"); - } - Manager?.Error(log); - break; - } - case LogType.Debug: - { - if (IsDebugEnabled == true) - { - if (trace == true) - { - Manager?.Debug($"{strTrace}"); - } - Manager?.Debug(log); - } - break; - } - case LogType.Fatal: - { - Manager?.Fatal($"{strTrace}"); - Manager?.Fatal(log); - break; - } - case LogType.Exception: - { - Type? t = MethodBase.GetCurrentMethod()?.DeclaringType; - if (t != null) - { - if (trace == true) - { - Manager?.Logger.Log(t, Log4netCustomLevel.EXCEPTION, $"{strTrace}", null); - } - Manager?.Logger.Log(t, Log4netCustomLevel.EXCEPTION, log, null); - } - break; - } - case LogType.DB: - { - if(IsDBEnabled == true) - { - Type? t = MethodBase.GetCurrentMethod()?.DeclaringType; - if (t != null) - { - if (trace == true) - { - Manager?.Logger.Log(t, Log4netCustomLevel.DB, $"{strTrace}", null); - } - Manager?.Logger.Log(t, Log4netCustomLevel.DB, log, null); - } - } - break; - } - case LogType.HTTP: - { - if(IsHttpEnabled == true) - { - Type? t = MethodBase.GetCurrentMethod()?.DeclaringType; - if (t != null) - { - if (trace == true) - { - Manager?.Logger.Log(t, Log4netCustomLevel.HTTP, $"{strTrace}", null); - } - Manager?.Logger.Log(t, Log4netCustomLevel.HTTP, log, null); - } - } - break; - } - case LogType.SOCKET: - { - if(IsSocketEnabled == true) - { - Type? t = MethodBase.GetCurrentMethod()?.DeclaringType; - if (t != null) - { - if (trace == true) - { - Manager?.Logger.Log(t, Log4netCustomLevel.SOCKET, $"{strTrace}", null); - } - Manager?.Logger.Log(t, Log4netCustomLevel.SOCKET, log, null); - } - } - break; - } - case LogType.CONTROLLER: - { - if(IsControllerEnabled == true) - { - Type? t = MethodBase.GetCurrentMethod()?.DeclaringType; - if (t != null) - { - if (trace == true) - { - Manager?.Logger.Log(t, Log4netCustomLevel.CONTROLLER, $"{strTrace}", null); - } - Manager?.Logger.Log(t, Log4netCustomLevel.CONTROLLER, log, null); - } - } - break; - } - } - } - - private static void WriteLineException(Exception? ex, - [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", - [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", - [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) - { - WriteLine($"TRACE::[{Path.GetFileName(sourceFilePath)}][Method:{memberName}][LINE:{sourceLineNumber}]", LogType.Exception); - WriteLine(ex?.Message, LogType.Exception); - } - - #region Config - static string Config = @$" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - #endregion -} - - -/* -log4net 지정 가능 색상 -Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, -DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White - */ \ No newline at end of file diff --git a/Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLogger.cs b/Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLogger.cs new file mode 100644 index 0000000..8a791a8 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLogger.cs @@ -0,0 +1,171 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Channels; +using System.Threading.Tasks; + +public class ChannelLogger : ILogger, IDisposable +{ + public class ChannelLog + { + public string message { get; set; } = string.Empty; + public string rgb { get; set; } = string.Empty; + } + + // + private readonly string _categoryName; + private static readonly Channel _logChannel = Channel.CreateUnbounded(new UnboundedChannelOptions + { + SingleReader = true, + SingleWriter = false + }); + + private static readonly Task _processorTask; + private static readonly object _initLock = new(); + private static bool _initialized = false; + + private static LogXnetConfig? _config; + private static LogLevel _currentLogLevel = LogLevel.Debug; + + static ChannelLogger() + { + _processorTask = Task.Run(ProcessLogMessagesAsync); + } + + public ChannelLogger(string categoryName) + { + _categoryName = categoryName; + + // Ensure static constructor ran + if (!_initialized) + { + lock (_initLock) + { + if (!_initialized) + { + _initialized = true; + } + } + } + } + + public IDisposable BeginScope(TState state) => default!; + public bool IsEnabled(LogLevel logLevel) + { + return logLevel >= _currentLogLevel; + } + + public void Log(LogLevel logLevel, EventId eventId, + TState state, Exception? exception, Func formatter) + { + if (!IsEnabled(logLevel)) return; + + var message = formatter(state, exception); + var timestamp = DateTime.Now.ToString($"yyyy-MM-dd HH:mm:ss.fff"); + + var fullMessage = string.Empty; + if(_config.TimeStampEnable == true) + { + fullMessage += $"[{timestamp}]"; + } + if(_config.ThreadIdEnable == true) + { + fullMessage += $"[{Environment.CurrentManagedThreadId}]"; + } + + fullMessage += $"[{eventId.Name}] {message}"; + _logChannel.Writer.TryWrite(new ChannelLog { message = fullMessage, rgb = $"{_config.LogDefines.Find(x=>x.LogLabel.ToLower() == eventId.Name.ToLower())?.ForeColorRGB}" } ); + } + + private static async Task ProcessLogMessagesAsync() + { + DateTime currentDate = DateTime.Now.Date; + StreamWriter? writer = null; + + await foreach (var msg in _logChannel.Reader.ReadAllAsync()) + { + // 현재 날짜 구함 + var logDate = DateTime.Now.Date; + + if (currentDate != logDate || writer == null) + { + // 날짜가 바뀐 경우: 기존 파일 닫고 새 파일 생성 + writer?.Dispose(); + + string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var logDir = $@"{folderPath}/{_config.OutputFilePath}/{logDate.Year}/{logDate.Month}/"; + Directory.CreateDirectory(logDir); + + var logFile = Path.Combine(logDir, $"{logDate.ToString("yyyy-MM-dd")}.log"); + writer = new StreamWriter(new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) + { + AutoFlush = true + }; + + currentDate = logDate; + } + + if(_config.ConsoleEnable == true) + { + // 색상 지정, 로그출력 + if (string.IsNullOrEmpty(msg.rgb) == false) + { + try + { + if (msg.rgb.Contains("#")) + { + var color = ColorTranslator.FromHtml(msg.rgb); + msg.rgb = $"{color.R};{color.G};{color.B}"; + } + + Console.Write($"\u001b[38;2;{msg.rgb}m"); + } + catch (Exception ex) + { + } + } + Console.WriteLine(msg.message); + Console.Write("\u001b[0m"); + } + + if(_config.FileOutputEnable == true) + { + // 파일 출력 + await writer.WriteLineAsync(msg.message); + } + } + + writer?.Dispose(); + } + + public static async Task ShutdownAsync() + { + _logChannel.Writer.Complete(); + await _processorTask; + } + + public static void SetConfig(LogXnetConfig config) + { + _config = config; + + if(Enum.TryParse(_config.LogLevel, out var logLevel) == true) + { + _currentLogLevel = logLevel; + } + } + + public static void SetLogLevel(LogLevel level) + { + _currentLogLevel = level; + } + + public void Dispose() + { + } +} + diff --git a/Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLoggerProvider.cs b/Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLoggerProvider.cs new file mode 100644 index 0000000..45b3e02 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/LogXnet/ChannelLoggerProvider.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +public class ChannelLoggerProvider : ILoggerProvider +{ + public ILogger CreateLogger(string categoryName) + { + return new ChannelLogger(categoryName); + } + + public void Dispose() + { + ChannelLogger.ShutdownAsync().Wait(); + } +} + diff --git a/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXLabel.cs b/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXLabel.cs new file mode 100644 index 0000000..1c196c9 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXLabel.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +public enum LogXLabel +{ + DEFAULT = 0, + + Debug = 1000, + DB = 1100, + HTTP = 1200, + CONTROLLER = 1250, + SOCKET=1300, + + Information = 2000, + INFO = 2010, + + Warning = 3000, + + Error = 4000, + Exception = 4100, + + Critical = 5000, + Fatal = 5001, +} + diff --git a/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnet.cs b/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnet.cs new file mode 100644 index 0000000..1ae38e2 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnet.cs @@ -0,0 +1,162 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +public static class LogXnet +{ + private static ILoggerFactory? _factory; + private static ILogger? _logger; + + public static bool ConfigLoad { get; private set; } = false; + private static LogXnetConfig? _config { get; set; } + + static LogXnet() + { + Initialize(); + } + + public static bool ReadConfig(string configPath) + { + try + { + var readConfigJson = File.ReadAllText(configPath); + _config = JsonSerializer.Deserialize(readConfigJson); + + if(_config != null) + { + var level = Enum.Parse(_config.LogLevel); + SetConfig(_config); + + //Auto Config + if (_config.AutoRemoveEnable == true) + { + Task.Run(FileAutoRemove); + WriteLine($"Auto log remove enable: Keeping {_config.AutoRemoveIntervalDay} day.", LogXLabel.INFO); + } + else + { + WriteLine($"Auto log remove disnable", LogXLabel.Warning); + } + } + + ConfigLoad = true; + } + catch(Exception ex) + { + WriteLine(ex); + } + + return ConfigLoad; + } + + private static void Initialize() + { + _factory = LoggerFactory.Create(builder => + { + builder.ClearProviders(); + builder.AddProvider(new ChannelLoggerProvider()); + builder.SetMinimumLevel(LogLevel.Debug); + }); + + _logger = _factory.CreateLogger("Global"); + } + + public static void WriteLine(string message, string logLabel) + { + if(_config != null) + { + var logLevelStr = _config.LogDefines.Find(x => $"{x.LogLabel.ToLower()}" == $"{logLabel.ToLower()}")?.LogLevel; + if (Enum.TryParse(logLevelStr, out var logLevel) == true) + { + switch (logLevel) + { + case LogLevel.Trace: + _logger?.LogTrace(new EventId(1000, $"{logLabel}"), message); + break; + case LogLevel.Debug: + _logger?.LogDebug(new EventId(1000, $"{logLabel}"), message); + break; + case LogLevel.Information: + _logger?.LogInformation(new EventId(1000, $"{logLabel}"), message); + break; + case LogLevel.Warning: + _logger?.LogWarning(new EventId(1000, $"{logLabel}"), message); + break; + case LogLevel.Error: + _logger?.LogError(new EventId(1000, $"{logLabel}"), message); + break; + case LogLevel.Critical: + _logger?.LogCritical(new EventId(1000, $"{logLabel}"), message); + break; + + default: + break; + } + } + else + { + _logger?.LogCritical(new EventId(1000, $"DEFAULT"), message); + } + } + } + + public static void WriteLine(string message, LogXLabel logLabel = LogXLabel.DEFAULT) + { + WriteLine(message, logLabel.ToString()); + } + + public static void WriteLine(Exception ex) + { + WriteLine(ex.Message, LogXLabel.Exception.ToString()); + } + + public static void SetLogLevel(LogLevel level) + { + ChannelLogger.SetLogLevel(level); + } + + private static void SetConfig(LogXnetConfig config) + { + ChannelLogger.SetConfig(config); + } + + private static async Task FileAutoRemove() + { + while (true) + { + if (_config.AutoRemoveEnable == false) + { + break; + } + + string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var logDir = $@"{folderPath}/{_config.OutputFilePath}"; + var files = Directory.GetFiles(logDir, "", SearchOption.AllDirectories); + + foreach (var f in files) + { + var fileName = Path.GetFileNameWithoutExtension(f); + if (DateTime.Now - DateTime.Parse(fileName) >= TimeSpan.FromDays(_config.AutoRemoveIntervalDay)) + { + File.Delete(f); + WriteLine($"Remove Log: {fileName}.log", LogXLabel.Warning); + } + } + + await Task.Delay(new TimeSpan(0, 1, 0)); + } + } + + public static void Shutdown() + { + _factory?.Dispose(); + } +} + diff --git a/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnetConfig.cs b/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnetConfig.cs new file mode 100644 index 0000000..e7e8a19 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/LogXnet/LogXnetConfig.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +public class LogXnetConfig +{ + public bool ConsoleEnable { get; set; } = true; + public bool FileOutputEnable { get; set; } = true; + public bool TimeStampEnable { get; set; } = true; + public bool ThreadIdEnable { get; set; } = true; + public bool AutoRemoveEnable { get; set; } = true; + + + public string OutputFilePath { get; set; } = string.Empty; + public string TimeStampForamt { get; set; } = "yyyy-MM-dd HH:mm:ss.fff"; + public int AutoRemoveIntervalDay { get; set; } = 30; + public string LogLevel { get; set; } = $"Information"; + + public List LogDefines { get; set; } = new List(); + + public class LogDefine + { + public string LogLevel { get; set; } = string.Empty; + public string LogLabel { get; set; } = string.Empty; + public string ForeColorRGB { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/Projects/SystemX.Core/SystemX.Core/Model/Auth/Login.cs b/Projects/SystemX.Core/SystemX.Core/Model/Auth/Login.cs index 58d60b3..3702a63 100644 --- a/Projects/SystemX.Core/SystemX.Core/Model/Auth/Login.cs +++ b/Projects/SystemX.Core/SystemX.Core/Model/Auth/Login.cs @@ -1,5 +1,4 @@ -using log4net.Core; -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Projects/SystemX.Core/SystemX.Core/Model/Auth/Logout.cs b/Projects/SystemX.Core/SystemX.Core/Model/Auth/Logout.cs index 85767d2..88faba0 100644 --- a/Projects/SystemX.Core/SystemX.Core/Model/Auth/Logout.cs +++ b/Projects/SystemX.Core/SystemX.Core/Model/Auth/Logout.cs @@ -1,5 +1,4 @@ -using log4net.Core; -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Projects/SystemX.Core/SystemX.Core/Model/Auth/Register.cs b/Projects/SystemX.Core/SystemX.Core/Model/Auth/Register.cs index 738162c..cde0682 100644 --- a/Projects/SystemX.Core/SystemX.Core/Model/Auth/Register.cs +++ b/Projects/SystemX.Core/SystemX.Core/Model/Auth/Register.cs @@ -1,5 +1,4 @@ -using log4net.Core; -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Projects/SystemX.Core/SystemX.Core/Services/DBContextProvider.cs b/Projects/SystemX.Core/SystemX.Core/Services/DBContextProvider.cs index 0e7e12d..07a9e43 100644 --- a/Projects/SystemX.Core/SystemX.Core/Services/DBContextProvider.cs +++ b/Projects/SystemX.Core/SystemX.Core/Services/DBContextProvider.cs @@ -23,7 +23,7 @@ namespace SystemX.Core.Services if (DBDictionary.ContainsKey($"{db.DBName}") == false) DBDictionary.Add($"{db.DBName}", db); else - Log4net.WriteLine($"Exist key DB Dictionary {db.DBName}", LogType.Error); + LogXnet.WriteLine($"Exist key DB Dictionary {db.DBName}", LogXLabel.Error); } } } diff --git a/Projects/SystemX.Core/SystemX.Core/SystemX.Core.csproj b/Projects/SystemX.Core/SystemX.Core/SystemX.Core.csproj index ed90dae..29111eb 100644 --- a/Projects/SystemX.Core/SystemX.Core/SystemX.Core.csproj +++ b/Projects/SystemX.Core/SystemX.Core/SystemX.Core.csproj @@ -19,7 +19,6 @@ - all diff --git a/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs b/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs index 16ae4c1..8e570d0 100644 --- a/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs +++ b/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs @@ -16,8 +16,8 @@ public static class JsonUtils } catch (Exception e) { - Log4net.WriteLine("JsonUtils.ToJson()", LogType.Error); - Log4net.WriteLine(e); + LogXnet.WriteLine("JsonUtils.ToJson()", LogXLabel.Exception); + LogXnet.WriteLine(e); } return result; @@ -32,7 +32,7 @@ public static class JsonUtils } catch(Exception e) { - Log4net.WriteLine("JsonUtils.ToObject()", LogType.Warn); + LogXnet.WriteLine("JsonUtils.ToObject()", LogXLabel.Warning); } return result;