LOG FILE 처리에 대한 실제 사용 예
로직 처리 동작 확인의 필요성
프로그램의 임의의 지점에서 데이터의 상태를 확인하기 위해서는 파일로 데이터를 출력해봐야 프로그램이 올바로 동작하는지을 알 수 있다. 그러기 위해서는 데이터를 파일로 처리하는 로직을 구성해야만 한다.
교착상태 방지를 위한 안전 장치
한 곳에서만 사용하는 것이 아님으로 CSingleLock을 사용한다. 교착상태를 방지하기위한 방법으로 선점한 곳에서 사용하고 반환되면 사용할 수 있도록 구성한다. 파일 생성 로직도 멤버로 설정하지않고 로컬에서 처리하도록 하였다. 파일 기록은 맨 마지막 행에 추가하도록 구성하였다.
시간 정보를 이용한 로그 파일 이름과 데이터 저장 형식
로그 파일 이름 생성 규칙은 LOG_년월일.log 형식으로 한다. 즉, 날이 바뀔 때마다 새로운 로그 파일을 생성하도록 한다. 로그 파일 내부에 저장되는 데이터의 저장 시간을 확인하기 위해서 시간 태그를 저장할 수 있도록 저장되는 로그의 맨 앞쪽에 시간태그를 넣도록 한다. 년월일시분초밀리초까지 기록할 수 있도록 한다.
파일 저장 처리 SEQUENCE
로그 파일 저장에 대한 SEQUENCE는 다음과 같이 진행한다.
- 파일 열기의 속성은 파일이 존재하지 않으면 생성하고 쓰기 가능하며, 공유도 할 수 있는 속성을 가진 파일로 연다
- 파일 열기가 정상적이면, 3번 과정으로 가고 실패이면 모든 동작을 끝내고 RETURN한다.
- 파일의 맨 마지막으로 쓰기 포인터를 옮긴다.
- 버퍼에 저장된 데이터를 파일로 WRITE한다.
- 쓰기가 완료된 파일 닫기한다.
언제든지 사용할 수 있는 예제 코드
BOOL CLog::_WriteSLogData(CString sData, int nFile)
{
//console창에 프린트하는 내용을 파일로 저장한다.
//환경설정 창에서 로그파일 생성 여부를 설정할 수 있고
//그 설정에 따라 로그 파일 생성 여부가 결정된다.
CSingleLock csl(&CLog::m_logLock);
csl.Lock(); ///< 크리티컬 섹션을 시작한다.
if (nFile)
{
CString sModulePath, sCurtime;
TCHAR CurrDir[MAX_PATH + 1];
GetCurrentDirectory(MAX_PATH+1, CurrDir);
sModulePath = (LPCTSTR)CurrDir;
//sModulePath = GetCurrentDirectory();
//sModulePath = _T("\\SDMMC");
CTime tmCur = ::CTime::GetCurrentTime();
CString sDate = tmCur.Format(_T("\\LOG\\SENDLOG_%Y-%m-%d.log")); //날짜별 log 파일 생성위해서.
DWORD curTime = GetTickCount64();
int scurT = (int)(curTime/1000);
int Hour = (int)(scurT/3600);
int Min = (int)((scurT-(Hour*3600))/60);
int Sec = scurT-(Hour*3600)-Min*60;
int MSec = (int)(curTime%1000);
sCurtime.Format(_T("[%02d:%02d:%02d %03d] "), tmCur.GetHour(), tmCur.GetMinute(), tmCur.GetSecond(), MSec);
CString sLog;
sLog = sModulePath + sDate;
sData = sCurtime + sData;
sData += "\r\n";
char buf[4096];
WideCharToMultiByte( CP_ACP, 0, sData, -1, buf, sizeof(buf), NULL, NULL);
CFile file;
CFileException e;
if (!file.Open(sLog, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate | CFile::shareDenyWrite, &e))
{ ///< 파일 열기 동작에 오류가 발생하면 모든 동작을 닫고 파일 처리를 종료한다.
csl.Unlock();
e.m_cause;
return FALSE;
}
file.SeekToEnd(); ///< 파일의 마지막 줄로 포인터를 옮긴다.
file.Write(buf, strlen(buf)); ///< 파일 쓰기 동작을 진행한다.
file.Close(); ///< 열었던 로그 파일을 닫는다.
}
csl.Unlock(); ///< 크리티컬 섹션을 끝낸다.
return TRUE;
}