WSLog.h
#pragma once
#define MAX_MSG_LEN 4096
#define MAX_VA_LEN 3072
#define MAX_DIRPATH_LEN 1024
#define MAX_ABSOLUTEPATH_LEN 2048
#define MAX_FILENAME 1024
#define UM_WRITELOG WM_USER+6654
#define UM_TERMINATE_THREAD WM_USER+2
#define LOG_DEBUG 1
#define LOG_INFO 2
#define LOG_WARNING 3
#define LOG_ERROR 4
#define LOGOUT(int, arg,...) DbgMsg(int, _T("[%s] ") arg, _T(__FUNCTION__), ##__VA_ARGS__)
BOOL InitLog();
void DbgMsg(int nLogLevel, const TCHAR* pFmt, ...);
BOOL SetLogPath(TCHAR* pLogPath, TCHAR* pModuleName);
UINT WriteLog_Thread(LPVOID pParam);
UINT DeleteLog_Thread(LPVOID pParam);
WSLog.cpp
#include "stdafx.h"
#include "WSLog.h"
BOOL g_bInitLog = FALSE;
DWORD g_WriteLogThreadID = -1;
DWORD g_DeleteLogThreadID = -1;
TCHAR g_szAbsoluteLogPath[MAX_ABSOLUTEPATH_LEN] = { 0 };
TCHAR g_szLogPath[MAX_DIRPATH_LEN] = { 0 };
TCHAR g_szModuleName[MAX_FILENAME] = { 0 };
HANDLE g_hWSLogEvent = NULL;
/*
Log는 어디서나 찍을 수 있어야 한다. 즉 static속성을 가져야 한다.
이 경우 클래스로 만드는 것은 적합하지 않다. 배보다 배꼽이 더 큰 형상이다.
InitLog()는 사용자가 직접 호출할 필요 없다. 사용자는 LOGOUT()만 사용하면 된다.
*/
BOOL InitLog()
{
if (g_bInitLog) {
return FALSE;
}
if (g_WriteLogThreadID == -1) {
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WriteLog_Thread,
NULL, 0, &g_WriteLogThreadID);
if(hThread == INVALID_HANDLE_VALUE) {
return FALSE;
}
CloseHandle(hThread);
}
g_hWSLogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_DeleteLogThreadID == -1) {
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DeleteLog_Thread,
NULL, 0, &g_DeleteLogThreadID);
if (hThread == INVALID_HANDLE_VALUE) {
return FALSE;
}
CloseHandle(hThread);
}
if (g_szLogPath == NULL || _tcscmp(g_szLogPath,_T("")) == 0
|| g_szModuleName == NULL || _tcscmp(g_szModuleName, _T("")) == 0) {
if (!SetLogPath(NULL, NULL)) {
return FALSE;
}
}
g_bInitLog = TRUE;
return TRUE;
}
BOOL SetLogPath(TCHAR* pLogPath, TCHAR* pModuleName)
{
if (pLogPath == NULL || _tcslen(pLogPath) == 0) {
TCHAR szCurrentDir[MAX_PATH] = { 0 };
GetCurrentDirectory(_countof(szCurrentDir), szCurrentDir);
_sntprintf_s(g_szLogPath, _countof(g_szLogPath), _T("%s\\Log"), szCurrentDir);
}
else {
_tcsncpy(g_szLogPath, pLogPath, _countof(g_szLogPath));
}
TCHAR* pFileName = NULL;
TCHAR szModuleAbsolutePath[MAX_ABSOLUTEPATH_LEN] = { 0 };
if (pModuleName == NULL || _tcslen(pModuleName) == 0) {
//set current path as Module Name
GetModuleFileName(NULL, szModuleAbsolutePath, _countof(szModuleAbsolutePath));
pFileName = _tcsrchr(szModuleAbsolutePath, _T('\\'));
TCHAR* pPointer = _tcsrchr(pFileName, _T('.'));
*pPointer = _T('\0');
pFileName++;
}
else {
pFileName = pModuleName;
}
_sntprintf_s(g_szModuleName, _countof(g_szModuleName), _T("%s"), pFileName);
if (CreateDirectory(g_szLogPath, NULL) == ERROR_PATH_NOT_FOUND) {
return FALSE;
}
return TRUE;
}
void DbgMsg(int nLogLevel, const TCHAR* pFmt, ...)
{
if (g_bInitLog == FALSE && InitLog() == FALSE) {
return;
}
//#ifndef _DEBUG
// if (nLogLevel == LOG_DEBUG) {
// return;
// }
//#endif
if (pFmt == NULL) {
return;
}
TCHAR szVaMsg[MAX_VA_LEN] = { 0 };
va_list vaArgs;
va_start(vaArgs, pFmt);
_vsntprintf(szVaMsg, _countof(szVaMsg), pFmt, vaArgs);
va_end(vaArgs);
time_t t = time(NULL);
struct tm* st = localtime(&t);
//주의! szLogMsg변수가 szVaMsg변수 위쪽에 선언 될 경우 memory corruption이 발생함.
//TCHAR szLogMsg[MAX_MSG_LEN] = { 0 };
int logMsgLen = MAX_MSG_LEN;
TCHAR* pLogMsg = new TCHAR[logMsgLen];
memset(pLogMsg, 0, logMsgLen * sizeof(TCHAR));
switch (nLogLevel)
{
case LOG_DEBUG:
_sntprintf(pLogMsg, logMsgLen, _T("<D>[%02d/%02d %02d:%02d:%02d] %s\r\n"),
st->tm_mon + 1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec, szVaMsg);
break;
case LOG_INFO:
_sntprintf(pLogMsg, logMsgLen, _T("<I>[%02d/%02d %02d:%02d:%02d] %s\r\n"),
st->tm_mon + 1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec, szVaMsg);
break;
case LOG_WARNING:
_sntprintf(pLogMsg, logMsgLen, _T("<W>[%02d/%02d %02d:%02d:%02d] %s\r\n"),
st->tm_mon + 1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec, szVaMsg);
break;
case LOG_ERROR:
_sntprintf(pLogMsg, logMsgLen, _T("<E>[%02d/%02d %02d:%02d:%02d] %s\r\n"),
st->tm_mon + 1, st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec, szVaMsg);
break;
}
_sntprintf(g_szAbsoluteLogPath, _countof(g_szAbsoluteLogPath), _T("%s\\%04d%02d%02d_%s.log"),
g_szLogPath, st->tm_year + 1900, st->tm_mon + 1, st->tm_mday, g_szModuleName);
PostThreadMessage(g_WriteLogThreadID, UM_WRITELOG, (WPARAM)pLogMsg, (LPARAM)(_tcslen(pLogMsg))*sizeof(TCHAR));
WaitForSingleObject(g_hWSLogEvent, 1000);
}
UINT DeleteLog_Thread(LPVOID pParam)
{
CTimeSpan tsWeekAgo(7, 0, 0, 0);
CTime timeCurrent = CTime::GetCurrentTime();
CTime timeWeeksAgo = timeCurrent - tsWeekAgo;
CString strLogPath = g_szLogPath;
CString strModuleName = g_szModuleName;
CString strBufFile = strLogPath + _T("\\*_") + strModuleName + _T(".log");
CString strTime = timeWeeksAgo.Format(_T("%Y%m%d")) + _T("_") + strModuleName;
CString strFileName;
CFileFind finder;
BOOL isWorking = finder.FindFile(strBufFile);
while (isWorking)
{
strFileName.Empty();
isWorking = finder.FindNextFile();
strFileName = finder.GetFileName();
if (strTime > strFileName) {
DeleteFile(strLogPath + _T("\\") + strFileName);
}
}
return 0;
}
UINT WriteLog_Thread(LPVOID pParam)
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == UM_WRITELOG) {
TCHAR* pLogMsg = (TCHAR*)msg.wParam;
int nLogMsgLen = msg.lParam;
_tprintf(_T("Log:%s\n"), pLogMsg);
HANDLE hFile = CreateFile(g_szAbsoluteLogPath,
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
SetFilePointer(hFile, 0, NULL, FILE_END);
DWORD dwWritten = 0;
WriteFile(hFile, pLogMsg, nLogMsgLen, &dwWritten, NULL);
}
CloseHandle(hFile);
if (pLogMsg != NULL) {
delete(pLogMsg);
}
SetEvent(g_hWSLogEvent);
}
else if (msg.message == UM_TERMINATE_THREAD) {
g_WriteLogThreadID = -1;
break;
}
}
return 0;
}
'Programming > Windows Socket Programming' 카테고리의 다른 글
UDP chat server/client (0) | 2020.04.19 |
---|---|
IOCP model(Chat Server) - Code (0) | 2020.03.14 |
IOCP model(Server) - Idea (0) | 2020.03.14 |
Basic model(Chat Client) - Code (0) | 2020.03.01 |
Basic model(Client) - Idea (0) | 2020.03.01 |