using GUI.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
namespace CoreUnit.Common
{
public class LogUnit
{
public delegate void EventHandlerLog(LogItem item);
public delegate void EventDisplayLog(LogItem item, eLogLevel logLevel);
public enum eLogProtocol : int { Time = 0, Msg, Position, Type };
public enum eLogLevel { LOW, MIDDLE, HIGH }; //로그를 표시하는 레벨을 정리함(High: detail한 로그까지 표시(Debug모드), Low: 단순한 로그(System로그)만 표시)
public enum eLogType { ERROR, ALARM, PRODUCT, SYSTEM, BUTTON, USER_ACCOUNT, MCC, COMMAND, COMMUNICATION, DEBUG, INITIALIZE, DATA, MEASURE };
///
///ERROR : 중알람 - SW 정지됨
///ALARM : 경알람 - SW 정지 안 됨
///PRODUCT : 생산 관련
///SYSTEM : SW 시스템
///BUTTON : UI 버튼
///USER_ACCOUNT : 장비 사용자
///MCC : 시퀀스 차트
///COMMAND : ReactiveLayer(Resource, Behavior)의 수행 정보를 DeliberateLayer(GUI) 로 전달
///COMMUNICATION : 통신
///DEBUG : 디버그용(테스트용)
///INITIALIZZE : SW 초기화 시에만 사용
///
public struct LogItem
{
public DateTime time;
public string msg;
public string position;
public eLogType type;
public eLogLevel level;
public int unitNo;
public LogItem Clone()
{
LogItem item = new LogItem();
item.time = this.time;
item.msg = this.msg;
item.position = this.position;
item.type = this.type;
item.level = this.level;
item.unitNo = this.unitNo;
return item;
}
}
object logBufferLock = new object();
List m_logBuffer = new List();
public List LogBuffer {
get { return m_logBuffer; }
set { m_logBuffer = value; }
}
object logDisplayErrorItemLock = new object();
List m_displayedErrorItem = new List();
public List DisplayedErrorItem {
get { return m_displayedErrorItem; }
set { m_displayedErrorItem = value; }
}
object logBufferForSavingLock = new object();
Dictionary> m_logBufferForSaving = new Dictionary>();
public Dictionary> LogBufferForSaving {
get { return m_logBufferForSaving; }
set { m_logBufferForSaving = value; }
}
eLogLevel m_logLevel = eLogLevel.HIGH;
public eLogLevel LogLevel {
get { lock (this) { return m_logLevel; } }
set { lock (this) { m_logLevel = value; } }
}
public LogUnit()
{
lock (logBufferForSavingLock) {
foreach (eLogType logType in Enum.GetValues(typeof(eLogType))) {
LogBufferForSaving[logType] = new List();
}
}
}
public void DisplayLog(ListView lsvLog, List logItemList, eLogLevel masterLogLevel)
{
if (0 < logItemList.Count) {
lsvLog.BeginUpdate();
foreach (LogItem item in logItemList) {
if (item.level <= masterLogLevel || item.type == eLogType.ERROR || item.type == eLogType.ALARM) // 로그 레벨에 따른 로그 필터 기능 추가
{
ListViewItem lvi = new ListViewItem(item.time.ToString("yyyyMMdd HH:mm:ss.fff"));
lvi.SubItems.Add(item.msg);
lsvLog.Items.Add(lvi);
}
}
int count = lsvLog.Items.Count;
uint maxLogCount = Settings.Default.MaxLogCount;
if (0 < maxLogCount && maxLogCount < count) {
for (int i = 0; i < count - maxLogCount; i++) {
lsvLog.Items.RemoveAt(0);
}
}
lsvLog.EndUpdate();
if (0 < lsvLog.Items.Count) {
lsvLog.Items[lsvLog.Items.Count - 1].EnsureVisible();
}
}
}
public void WriteLogToFile(string systemDataFolderPath)
{
foreach (eLogType logType in Enum.GetValues(typeof(eLogType))) {
lock (logBufferForSavingLock) {
if (0 < LogBufferForSaving[logType].Count) //로그가 있는 경우에 file 기록함.
{
try {
string logFolder = string.Format(@"{0}\Log\{1}\{2}", systemDataFolderPath, logType.ToString(), DateTime.Now.ToString("yyyy.MM.dd"));
string logFile = string.Format(@"{0}\{1}.log", logFolder, DateTime.Now.ToString("HH"));
if (Directory.Exists(logFolder) == false) {
Directory.CreateDirectory(logFolder);
}
using (FileStream file = new FileStream(logFile, FileMode.Append, FileAccess.Write)) {
using (StreamWriter sw = new StreamWriter(file, System.Text.Encoding.Default)) {
for (int i = 0; i < LogBufferForSaving[logType].Count; i++) {
sw.WriteLine(LogBufferForSaving[logType][i]);
}
}
}
LogBufferForSaving[logType].Clear();
} catch (Exception ex) {
throw ex;
}
}
}
}
}
public void SetLog(eLogType type, string position, string msg, eLogLevel level = eLogLevel.MIDDLE)
{
SetLog(type, position, msg, -1, level);
}
public void SetLog(eLogType type, string position, string msg, int unitNo, eLogLevel level = eLogLevel.MIDDLE)
{
LogItem logItem = new LogItem();
logItem.time = DateTime.Now;
logItem.msg = msg;
logItem.position = position;
logItem.level = level;
logItem.unitNo = unitNo;
if (type == eLogType.ERROR) {
var callSite = (new System.Diagnostics.StackTrace(1, true)).GetFrame(0);
logItem.position += string.Format("(FILE NAME:{0},LINE NO:{1})", callSite.GetFileName(), callSite.GetFileLineNumber());
}
logItem.type = type;
lock (logBufferLock) {
LogBuffer.Add(logItem);
}
}
public bool FilterSameErrorLog(LogItem currLogItem)
{
if (currLogItem.type == eLogType.ERROR || currLogItem.type == eLogType.ALARM) {
lock (logDisplayErrorItemLock) {
foreach (LogItem log in DisplayedErrorItem) {
if (log.msg == currLogItem.msg) {
return true;
}
}
DisplayedErrorItem.Add(currLogItem);
}
}
return false;
}
public void ClearDisplayerErrorLog()
{
lock (logDisplayErrorItemLock) {
if (DisplayedErrorItem.Count != 0) {
DisplayedErrorItem.Clear();
}
}
}
public void HandleLog(EventHandlerLog evtHandlerLog, string systemDataFolderPath, ListView lsvLog, eLogLevel masterLogLevel, bool enableDebugMode)
{
List arrangedLogItemList = new List();
lock (logBufferLock) {
if (0 < LogBuffer.Count) {
for (int i = 0; i < LogBuffer.Count; i++) {
LogItem logItem = LogBuffer[i];
if (!FilterSameErrorLog(logItem)) {
arrangedLogItemList.Add(logItem.Clone());
SaveLogToBuffer(enableDebugMode, logItem, masterLogLevel);
}
}
LogBuffer.Clear();
Thread.Sleep(1);
}
}
WriteLogToFile(systemDataFolderPath);
DisplayLog(lsvLog, arrangedLogItemList, masterLogLevel);
foreach (LogItem item in arrangedLogItemList) {
evtHandlerLog(item); // 이 안에서 문제가 될 코드(예를 들면, 로그 기록)가 지나치게 많아서 lock을 걸 수가 없다 (정리 필요)
}
}
public void HandleLogByUnit(EventHandlerLog evtHandlerLog, string systemDataFolderPath, ListView[] lsvLog, eLogLevel masterLogLevel, bool enableDebugMode)
{
List arrangedLogItemListAll = new List();
List arrangedLogItemList1 = new List();
List arrangedLogItemList2 = new List();
List arrangedLogItemList3 = new List();
List arrangedLogItemList4 = new List();
lock (logBufferLock) {
if (0 < LogBuffer.Count) {
for (int i = 0; i < LogBuffer.Count; i++) {
LogItem logItem = LogBuffer[i];
if (!FilterSameErrorLog(logItem)) {
SaveLogToBuffer(enableDebugMode, logItem, masterLogLevel);
arrangedLogItemListAll.Add(logItem.Clone());
switch (logItem.unitNo) {
case 1:
arrangedLogItemList1.Add(logItem.Clone());
break;
case 2:
arrangedLogItemList2.Add(logItem.Clone());
break;
case 3:
arrangedLogItemList3.Add(logItem.Clone());
break;
case 4:
arrangedLogItemList4.Add(logItem.Clone());
break;
default:
break;
}
}
}
LogBuffer.Clear();
Thread.Sleep(1);
}
}
WriteLogToFile(systemDataFolderPath);
if (3 < lsvLog.Length) {
DisplayLog(lsvLog[0], arrangedLogItemList1, masterLogLevel);
DisplayLog(lsvLog[1], arrangedLogItemList2, masterLogLevel);
DisplayLog(lsvLog[2], arrangedLogItemList3, masterLogLevel);
DisplayLog(lsvLog[3], arrangedLogItemList4, masterLogLevel);
}
foreach (LogItem item in arrangedLogItemListAll) {
evtHandlerLog(item); // 이 안에서 문제가 될 코드(예를 들면, 로그 기록)가 지나치게 많아서 lock을 걸 수가 없다 (정리 필요)
}
}
private void SaveLogToBuffer(bool enableDebugMode, LogItem logItem, eLogLevel masterLogLevel)
{
string msg = string.Format("[TIME]:{0}\t[TYPE]:{1}\t[CONTENT]:{2}\t[POSITION]:{3}"
, logItem.time.ToString("yyyy-MM-dd HH:mm:ss.fff")
, Enum.GetName(typeof(eLogType), logItem.type)
, logItem.msg
, logItem.position);
lock (logBufferForSavingLock) {
if (enableDebugMode) //DB.Dao.SystemRecipe.EnableDebugMode
{
LogBufferForSaving[eLogType.DEBUG].Add(msg); //DEBUG 폴더에는 모든 로그를 저장
}
if ((logItem.level >= masterLogLevel) || (logItem.type == eLogType.ERROR) || (logItem.type == eLogType.ALARM)) //로그 레벨에 따른 로그 필터 기능 추가
{
if (enableDebugMode && logItem.type == eLogType.DEBUG) {
// 로그 중복 기록 방지
} else {
LogBufferForSaving[logItem.type].Add(msg);
}
}
}
}
//////////////////////////////////////////////////////////////////////////
public string GetExceptionInformation(eLogType logType, Exception ex)
{
string msg = string.Format("[Type]\r\n{0}\r\n[Message]\r\n{1}\r\n[Exception]\r\n{2}\r\n{3}\r\n", logType.ToString(), ex.Message, ex.TargetSite.ToString(), ex.StackTrace.ToString());
if (ex.InnerException != null) {
msg += "[InnerException]\r\n" + ex.InnerException.TargetSite.ToString() + "\r\n" + ex.InnerException.StackTrace.ToString();
}
return msg;
}
public void DeleteLogOverUserPeriod(string logDataFolder, int logDeletePeriod, string[] dataFolders = null)
{
DirectoryInfo logFolder;
//1.로그 폴더 삭제
foreach (eLogType logType in Enum.GetValues(typeof(eLogType))) {
string folderName = string.Format(@"{0}\Log\{1}", logDataFolder, logType.ToString());
if (Directory.Exists(folderName) == true) {
logFolder = new DirectoryInfo(folderName);
foreach (DirectoryInfo datetimeDir in logFolder.GetDirectories()) {
if (datetimeDir.CreationTime < DateTime.Now.AddDays(-1 * logDeletePeriod)) {
datetimeDir.Delete(true);
UtilUnit.logUnit.SetLog(eLogType.SYSTEM, MethodBase.GetCurrentMethod().Name, string.Format(@"로그 폴더 삭제(폴더명:{0}\{1})", logFolder, datetimeDir.Name), eLogLevel.HIGH);
}
Thread.Sleep(1);
}
}
}
if (dataFolders != null) {
//2.사용자 정의 폴더 삭제
foreach (string dataFolder in dataFolders) {
logFolder = new DirectoryInfo(dataFolder);
foreach (DirectoryInfo dir in logFolder.GetDirectories()) {
DirectoryInfo reviewFolder = new DirectoryInfo(dir.FullName);
foreach (DirectoryInfo datetimeDir in reviewFolder.GetDirectories()) {
if (datetimeDir.CreationTime < DateTime.Now.AddDays(-1 * logDeletePeriod)) {
//날짜폴더 삭제
datetimeDir.Delete(true);
UtilUnit.logUnit.SetLog(eLogType.SYSTEM, MethodBase.GetCurrentMethod().Name, string.Format("검사 폴더 삭제(폴더명:{0})", datetimeDir.Name), eLogLevel.HIGH);
}
Thread.Sleep(1);
}
}
}
}
}
}
}