초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace ServerBase;
public abstract class IAppender
{
public abstract void write(IFormatter logFormatter, BusinessLog log);
}//ILogAppender

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using NLog;
using NLog.Fluent;
using ServerCore; using ServerBase;
namespace ServerBase;
public class NLogAppender : IAppender
{
private readonly NLog.Logger m_logger = NLog.LogManager.GetLogger("BusinessLogger");
public NLogAppender(string xmlCofigFilePath = "")
{
if(true == xmlCofigFilePath.isNullOrWhiteSpace())
{
return;
}
reconfigureXML(xmlCofigFilePath);
}
public bool reconfigureXML(string xmlCofigFilePath)
{
var to_reload_configure = new NLog.Config.XmlLoggingConfiguration(xmlCofigFilePath);
if(null == to_reload_configure)
{
return false;
}
LogManager.Configuration = to_reload_configure;
LogManager.ReconfigExistingLoggers();
return true;
}
public bool isLoadedConfigXML()
{
if(null == LogManager.Configuration)
{
return false;
}
return true;
}
public override void write(IFormatter logFormatter, BusinessLog log)
{
m_logger?.Info(logFormatter.toLogString(log));
}
}

View File

@@ -0,0 +1,93 @@

using ServerCore; using ServerBase;
namespace ServerBase;
//========================================================================================================
// 비즈니스 로그 처리자
//
// 운영 담당 부서와 사업 담당 부서에서 필요로 하는 주요 속성들 정의 하여
// 필요로 하는 데이터 포멧에 맞게 출력 한다.
//========================================================================================================
public static class BusinessLogger
{
private static IAppender? m_appender;
private static IFormatter? m_formatter;
private static LogTransToOutputType m_output_type = LogTransToOutputType.TransToSingleLine;
//==========================================================================
// appender를 셋팅한다.
//==========================================================================
public static void setup(IAppender appender, IFormatter logFormatter, LogTransToOutputType outputType)
{
m_appender = appender;
m_formatter = logFormatter;
m_output_type = outputType;
}
//==========================================================================
// 단일 로그를 수집 한다.
//==========================================================================
public static ServerErrorCode collectLog(IWithLogActor actor, ILogInvoker invoker)
{
ArgumentNullReferenceCheckHelper.throwIfNull(actor, () => $"actor is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(invoker, () => $"invoker is null !!!");
if (m_appender == null)
{
return ServerErrorCode.LogAppenderIsNull;
}
if(m_formatter == null)
{
return ServerErrorCode.LogAppenderIsNull;
}
if(true == invoker.hasLog())
{
var is_success = invoker.alloc(actor.toLogActor(), out var log);
if (is_success.isSuccess() && log != null)
{
m_appender.write(m_formatter, log);
}
}
return ServerErrorCode.Success;
}
//==========================================================================
// 복합 로그를 수집 한다.
//==========================================================================
public static ServerErrorCode collectLogs(LogAction logAction, IWithLogActor actor, List<ILogInvoker> invokers)
{
if (m_appender == null)
{
return ServerErrorCode.LogAppenderIsNull;
}
if (m_formatter == null)
{
return ServerErrorCode.LogFormatterIsNull;
}
List<BusinessLog> logs = new List<BusinessLog>();
var result_code = ILogInvoker.alloc(logAction.getLogActionType(), logAction.getTranId(), actor.toLogActor(), invokers, m_output_type, ref logs);
if(result_code.isFail())
{
return result_code;
}
foreach (var log in logs)
{
if (log != null && log.hasLog())
{
m_appender.write(m_formatter, log);
}
}
return ServerErrorCode.Success;
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ServerBase;
public abstract class IFormatter
{
public abstract string toLogString(BusinessLog log);
}//IFormatter

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
namespace ServerBase;
public class JsonText : IFormatter
{
private static readonly JsonSerializerSettings m_serialize_settings = new JsonSerializerSettings();
private static readonly ContractResolver m_resolver = new ContractResolver();
public JsonText()
{
m_serialize_settings.ContractResolver = m_resolver;
m_serialize_settings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
}
public override string toLogString(BusinessLog log)
{
return JsonConvert.SerializeObject(log, m_serialize_settings);
}
//=============================================================================================
// Json을 만들때 무시할 property를 등록한다.
//=============================================================================================
private class ContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
private readonly Dictionary<Type, HashSet<string>> m_ignores;
public ContractResolver()
{
m_ignores = new Dictionary<Type, HashSet<string>>();
}
public void ignoreProperty(Type type, params string[] jsonPropertyNames)
{
if (false == m_ignores.ContainsKey(type))
{
m_ignores[type] = new HashSet<string>();
}
foreach (var prop in jsonPropertyNames)
{
m_ignores[type].Add(prop);
}
}
public bool isIgnored(Type type, string jsonPropertyName)
{
if (false == m_ignores.ContainsKey(type))
{
return false;
}
return m_ignores[type].Contains(jsonPropertyName);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType != null &&
property.PropertyName != null &&
isIgnored(property.DeclaringType, property.PropertyName))
{
property.ShouldSerialize = i => false;
property.Ignored = true;
}
return property;
}
}//ContractResolver
}//JsonText

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ServerBase;
//===================================================================================
// 로그 주체를 지칭한다
//===================================================================================
public abstract class ILogActor
{
public virtual bool fillup(IFormatter formatter)
{
return false;
}
}

View File

@@ -0,0 +1,243 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Amazon.OpenSearchService.Model.Internal.MarshallTransformations;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using ServerCore; using ServerBase;
using LOG_ACTION_TYPE = System.String;
using LOG_DOMAIN_TYPE = System.String;
namespace ServerBase;
public enum LogTransToOutputType
{
TransToMultyLine = 0, // Body 갯수대로 로그 출력
TransToSingleLine = 1, // 한개의 Body로 로그 출력
}
//===================================================================================
// 로그 액션
//===================================================================================
public partial class LogAction
{
private readonly LOG_ACTION_TYPE m_log_action_type = string.Empty;
private Guid m_tran_id = Guid.Empty;
public LogAction(LOG_ACTION_TYPE logActionType)
{
m_log_action_type = logActionType;
m_tran_id = Guid.NewGuid();
}
public LogAction(LOG_ACTION_TYPE logActionType, Guid tranId)
{
m_log_action_type = logActionType;
m_tran_id = tranId;
}
}//LogAction
//===================================================================================
// 로그를 발생 시킨다
//===================================================================================
public abstract partial class ILogInvoker
{
private LogAction? m_log_action_nullable;
private readonly LOG_DOMAIN_TYPE m_log_domain_type = string.Empty;
public ILogInvoker()
{
}
public ILogInvoker(LOG_DOMAIN_TYPE logDomainType)
{
m_log_domain_type = logDomainType;
}
public ILogInvoker(LOG_DOMAIN_TYPE logDomainType, LogAction logAction)
{
m_log_action_nullable = logAction;
m_log_domain_type = logDomainType;
}
public ServerErrorCode alloc(ILogActor logActor, out BusinessLog? businessLog)
{
ArgumentNullReferenceCheckHelper.throwIfNull(logActor, () => $"logActor is null !!!");
businessLog = null;
if (null == m_log_action_nullable)
{
return ServerErrorCode.LogActionIsNull;
}
var header = new BusinessLog.LogHeader(m_log_action_nullable.getTranId().ToString(), logActor);
var body = new BusinessLog.LogBody(m_log_action_nullable.getLogActionType());
{
fillup(ref body);
}
businessLog = new BusinessLog(header, body);
return ServerErrorCode.Success;
}
public static ServerErrorCode alloc( LOG_ACTION_TYPE logActionType, Guid tran
, ILogActor actorLog, List<ILogInvoker> invokers
, LogTransToOutputType outputType, ref List<BusinessLog> outLogs )
{
if (logActionType.isNullOrWhiteSpace())
{
return ServerErrorCode.LogActionTypeInvalid;
}
var header = new BusinessLog.LogHeader(tran.ToString(), actorLog);
switch (outputType)
{
case LogTransToOutputType.TransToMultyLine:
{
foreach (var each in invokers)
{
var body = new BusinessLog.LogBody(logActionType);
{
if (false == each.hasLog())
{
continue;
}
each.fillup(ref body);
outLogs.Add(new BusinessLog(header, body));
}
}
}
break;
case LogTransToOutputType.TransToSingleLine:
{
var body = new BusinessLog.LogBody(logActionType);
{
foreach (var each in invokers)
{
if (false == each.hasLog())
{
continue;
}
each.fillup(ref body);
}
outLogs.Add(new BusinessLog(header, body));
}
}
break;
}
return ServerErrorCode.Success;
}
protected abstract void fillup(ref BusinessLog.LogBody body);
// 로그가 들어 있는지 검사한다.
public abstract bool hasLog();
public virtual string toBasicString()
{
return $"LogInvoker:{this.getTypeName()}";
}
//===================================================================================
// 사용자 정의 로그 정보 추상 클래스 이다.
//===================================================================================
public abstract class IInfo
{
[JsonProperty(Order = -2)]
private readonly LOG_DOMAIN_TYPE Domain = string.Empty;
// ILogInvoker 에 의해 생성될 경우 로그 정보 컨테이너에 적재되고
// 로그 정보를 Json 기반으로 직렬화 한다.
public IInfo(ILogInvoker parent)
{
Domain = parent.m_log_domain_type;
}
// 로그 정보 전달 객체로 활용 된다 !!!
public IInfo()
{
}
}//IInfo
}//ILogInvoker
public class BusinessLog
{
[JsonProperty]
private readonly LogHeader Header;
[JsonProperty]
private readonly LogBody Body;
public BusinessLog(LogHeader header, LogBody body)
{
Header = header;
Body = body;
}
public bool hasLog()
{
return Header != null && Body != null && Header.hasLog() && Body.hasLog();
}
public class LogHeader
{
[JsonProperty]
private readonly string TranId = string.Empty;
[JsonProperty]
private readonly ILogActor Actor;
public LogHeader(string tran_id, ILogActor actor_log)
{
TranId = tran_id;
Actor = actor_log;
}
public bool hasLog()
{
return Actor != null;
}
}
public class LogBody
{
[JsonProperty]
private readonly LOG_ACTION_TYPE Action = string.Empty;
[JsonProperty]
private readonly List<ILogInvoker.IInfo> Infos = new List<ILogInvoker.IInfo>();
public LogBody(LOG_ACTION_TYPE action)
{
Action = action;
}
public bool hasLog(bool allow_empty = false)
{
if (Action.isNullOrWhiteSpace())
{
return false;
}
return allow_empty ? true : Infos.Count != 0;
}
public void append(ILogInvoker.IInfo info)
{
Infos.Add(info);
}
}
}