X Tutup
/* * Copyright (C) 2012 Yee Young Han (http://blog.naver.com/websearch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "FileLog.h" #include "TimeUtility.h" #include "FileUtility.h" #include #ifndef WIN32 #include #endif extern bool LogFileCompare( const std::string & strFirst, const std::string & strSecond ); CFileLog::CFileLog() : m_sttFd(NULL), m_iLevel(LOG_ERROR), m_iMaxLogSize(DEFAULT_LOG_FILE_SIZE), m_iLogSize(0) , m_iIndex(1), m_iMaxFolderSize(DEFAULT_LOG_FOLDER_SIZE), m_iFolderSize(0) { memset( m_szDate, 0, sizeof(m_szDate) ); } CFileLog::~CFileLog() { Close(); } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏÀ» ÀúÀåÇÒ µð·ºÅ丮¸¦ ¼³Á¤ÇÑ´Ù. * @param pszDirName ·Î±× ÆÄÀÏÀ» ÀúÀåÇÒ µð·ºÅ丮 * @return ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ±×·¸Áö ¾ÊÀ¸¸é false ¸¦ ¸®ÅÏÇÑ´Ù. */ bool CFileLog::Open( const char * pszDirName ) { if( pszDirName == NULL ) return false; int iLen = (int)strlen( pszDirName ); bool bRes = false; if( iLen < 3 ) return false; m_clsMutex.acquire(); if( m_strDirName.empty() ) { #ifdef WIN32 if( pszDirName[iLen-1] == '\\' ) #else if( pszDirName[iLen-1] == '/' ) #endif { m_strDirName.append( pszDirName, iLen - 1 ); } else { m_strDirName = pszDirName; } if( CDirectory::Create( m_strDirName.c_str() ) ) { m_iFolderSize = CDirectory::GetSize( m_strDirName.c_str() ); bRes = true; } } m_clsMutex.release(); return bRes; } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ ÀúÀåÀ» ÁßÁöÇÑ´Ù. * @returns true ¸¦ ¸®ÅÏÇÑ´Ù. */ bool CFileLog::Close( ) { m_clsMutex.acquire(); if( m_strDirName.empty() == false ) { if( m_sttFd != NULL ) { fclose( m_sttFd ); m_sttFd = NULL; } m_strDirName.clear(); } m_clsMutex.release(); return true; } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ¿¡ ·Î±×¸¦ ÀúÀåÇÑ´Ù. * @param iLevel ·Î±× ÆÄÀÏ ·¹º§ * @param fmt ·Î±× ÆÄÀÏ¿¡ ÀúÀåÇÒ Æ÷¸Ë ¹®ÀÚ¿­ * @param ... fmt Æ÷¸Ë¿¡ ÀÔ·ÂÇÒ ÀÎÀÚµé * @return ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ±×·¸Áö ¾ÊÀ¸¸é false ¸¦ ¸®ÅÏÇÑ´Ù. */ bool CFileLog::Print( EnumLogLevel iLevel, const char * fmt, ... ) { if( ( m_iLevel & iLevel ) == 0 ) return false; va_list ap; char szBuf[LOG_MAX_SIZE]; char szDate[9], szHeader[30]; struct tm sttTm; switch( iLevel ) { case LOG_ERROR: snprintf( szHeader, sizeof(szHeader), "[ERROR] " ); break; case LOG_INFO: snprintf( szHeader, sizeof(szHeader), "[INFO] " ); break; case LOG_DEBUG: snprintf( szHeader, sizeof(szHeader), "[DEBUG] " ); break; case LOG_NETWORK: snprintf( szHeader, sizeof(szHeader), "[NETWORK] " ); break; case LOG_SYSTEM: snprintf( szHeader, sizeof(szHeader), "[SYSTEM] " ); break; case LOG_SQL: snprintf( szHeader, sizeof(szHeader), "[SQL] " ); break; default: memset( szHeader, 0, sizeof(szHeader) ); break; } // ÇöÀçÀÇ ½Ã°£À» ±¸ÇÑ´Ù. struct timeval sttTime; gettimeofday( &sttTime, NULL ); #ifdef WIN32 _localtime32_s( &sttTm, &sttTime.tv_sec ); #else localtime_r( &sttTime.tv_sec, &sttTm ); #endif snprintf( szDate, sizeof(szDate), "%04d%02d%02d", sttTm.tm_year + 1900, sttTm.tm_mon + 1, sttTm.tm_mday ); if( m_clsMutex.acquire() == false ) return false; if( m_strDirName.empty() == false && strcmp( m_szDate, szDate ) ) { // ÇöÀçÀÇ ³¯Â¥¿Í Ŭ·¡½º¿¡ ÀúÀåµÈ ³¯Â¥°¡ ´Ù¸¥ °æ¿ì¿¡´Â ·Î±× ÆÄÀÏÀ» »õ·Î Á¦ÀÛÇÏ¿©¼­ Open ÇÑ´Ù. char szFileName[FULLPATH_FILENAME_MAX_SIZE]; m_iIndex = 1; OPEN_FILE: m_iLogSize = 0; snprintf( szFileName, sizeof(szFileName), "%s%c%04d%02d%02d_%d.txt", m_strDirName.c_str(), DIR_SEP, sttTm.tm_year + 1900, sttTm.tm_mon + 1, sttTm.tm_mday, m_iIndex ); // ÀÌ¹Ì Open µÈ ÆÄÀÏÀÌ ÀÖ´Â °æ¿ì¿¡´Â À̸¦ ´Ý´Â´Ù. if( m_sttFd ) { fclose( m_sttFd ); m_sttFd = NULL; } DeleteOldFile(); if( m_iMaxLogSize > 0 ) { int64_t iFileSize = GetFileSize( szFileName ); if( iFileSize >= m_iMaxLogSize ) { ++m_iIndex; goto OPEN_FILE; } m_iLogSize = (int)iFileSize; } m_sttFd = fopen( szFileName, "ab" ); if( m_sttFd == NULL ) { printf( "log file(%s) open error\n", szFileName ); } snprintf( m_szDate, sizeof(m_szDate), "%s", szDate ); } else if( m_iMaxLogSize > 0 && m_iLogSize >= m_iMaxLogSize ) { ++m_iIndex; goto OPEN_FILE; } m_clsMutex.release(); va_start( ap, fmt ); vsnprintf( szBuf, sizeof(szBuf)-1, fmt, ap ); va_end( ap ); if( m_clsMutex.acquire() == false ) return false; if( m_sttFd ) { int iWrite; #ifdef WIN32 iWrite = fprintf( m_sttFd, "[%02d:%02d:%02d.%06u] %s[%u] %s\r\n" , sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, sttTime.tv_usec, szHeader, GetCurrentThreadId(), szBuf ); #else iWrite = fprintf( m_sttFd, "[%02d:%02d:%02d.%06u] %s[%lu] %s\n" , sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, (unsigned int)sttTime.tv_usec, szHeader, (unsigned long)pthread_self(), szBuf ); #endif fflush( m_sttFd ); m_iLogSize += iWrite; m_iFolderSize += iWrite; } else { #ifdef WIN32 printf( "[%02d:%02d:%02d] %s%s\r\n", sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, szHeader, szBuf ); #else printf( "[%02d:%02d:%02d] %s%s\n", sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, szHeader, szBuf ); #endif } m_clsMutex.release(); return true; } /** * @ingroup SipPlatform * @brief ·Î±× ·¹º§À» °¡Á®¿Â´Ù. * @return ·Î±× ·¹º§À» ¸®ÅÏÇÑ´Ù. */ int CFileLog::GetLevel( ) { return m_iLevel; } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ¿¡ ÀúÀåÇÒ ·Î±× ·¹º§À» ¼³Á¤ÇÑ´Ù. ¿©·¯ ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, '|' ¿¬»êÀÚ¸¦ ÀÌ¿ëÇÏ¿©¼­ ¿©·¯ ·Î±× ·¹º§À» ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. * @param iLevel [in] µð¹ö±× ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, LOG_DEBUG ¸¦ ¼³Á¤ÇÑ´Ù. * Á¤º¸ ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, LOG_INFO ¸¦ ¼³Á¤ÇÑ´Ù. * ¿¡·¯ ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, LOG_ERROR ¸¦ ¼³Á¤ÇÑ´Ù. */ void CFileLog::SetLevel( int iLevel ) { m_iLevel = LOG_ERROR | LOG_SYSTEM; m_iLevel |= iLevel; } /** * @ingroup SipPlatform * @brief ÀÔ·ÂÇÑ ·Î±× ·¹º§ÀÌ ÇöÀç Ãâ·ÂÇÒ ¼ö ÀÖ´Â ·Î±× ·¹º§ÀÎÁö ºÐ¼®ÇÏ¿© ÁØ´Ù. * @param iLevel [in] ·Î±× ·¹º§ * @return ÇöÀç Ãâ·ÂÇÒ ¼ö ÀÖ´Â ·Î±× ·¹º§ÀÎ °æ¿ì¿¡´Â true ¸¦ ¸®ÅÏÇÏ°í ±×·¸Áö ¾ÊÀ¸¸é false ¸¦ ¸®ÅÏÇÑ´Ù. */ bool CFileLog::IsPrintLogLevel( EnumLogLevel iLevel ) { if( ( m_iLevel & iLevel ) == 0 ) return false; return true; } /** * @ingroup SipPlatform * @brief ·Î±×¸¦ ÀúÀåÇÒ ÃÖ´ë ÆÄÀÏ Å©±â¸¦ ¼³Á¤ÇÑ´Ù. * @param iSize ·Î±×¸¦ ÀúÀåÇÒ ÃÖ´ë ÆÄÀÏ Å©±â */ void CFileLog::SetMaxLogSize( int iSize ) { if( iSize < MIN_LOG_FILE_SIZE ) { iSize = MIN_LOG_FILE_SIZE; } else if( iSize > MAX_LOG_FILE_SIZE ) { iSize = MAX_LOG_FILE_SIZE; } m_iMaxLogSize = iSize; } /** * @ingroup SipPlatform * @brief ·Î±× Æú´õ ÃÖ´ë Å©±â¸¦ ¼³Á¤ÇÑ´Ù. * @param iSize ·Î±× Æú´õ ÃÖ´ë Å©±â */ void CFileLog::SetMaxFolderSize( int64_t iSize ) { // ÃÖ¼Ò 30ÀÏ ·Î±× ÆÄÀÏ ÀúÀå °ø°£À» È®º¸ÇÑ´Ù. if( m_iMaxLogSize == 0 ) { if( iSize < ( MIN_LOG_FILE_SIZE * 30 ) ) { iSize = MIN_LOG_FILE_SIZE * 30; } } else { if( iSize < m_iMaxLogSize * 30 ) { iSize = m_iMaxLogSize * 30; } } m_iMaxFolderSize = iSize; } /** * @ingroup SipPlatform * @brief ·Î±× Æú´õÀÇ Å©±â°¡ ¼³Á¤µÈ Å©±âº¸´Ù Å« °æ¿ì, ¿À·¡µÈ ·Î±× ÆÄÀÏÀ» »èÁ¦ÇÑ´Ù. */ void CFileLog::DeleteOldFile( ) { if( m_iMaxFolderSize == 0 ) return; if( m_strDirName.empty() ) return; if( m_iFolderSize >= m_iMaxFolderSize ) { int64_t iWantSize = m_iMaxFolderSize * 8 / 10; FILE_LIST clsFileList; FILE_LIST::iterator itList; int64_t iFileSize; CDirectory::FileList( m_strDirName.c_str(), clsFileList ); clsFileList.sort( LogFileCompare ); for( itList = clsFileList.begin(); itList != clsFileList.end(); ++itList ) { std::string strFileName = m_strDirName; CDirectory::AppendName( strFileName, itList->c_str() ); iFileSize = GetFileSize( strFileName.c_str() ); #ifdef WIN32 DeleteFile( strFileName.c_str() ); #else unlink( strFileName.c_str() ); #endif m_iFolderSize -= iFileSize; if( m_iFolderSize < iWantSize ) break; } } }
X Tutup