c++ 日志操作

程序需要一个简单的日志类,为此简单学习了Boost.Log和google的glog,前者功能非常强大,后者非常小巧但是不够灵活,最终打算自己写一个。

 环境:

win7 32位旗舰版、VS2010旗舰版

TinyLog.h文件

#ifndef _TINY_LOG_H_
#define _TINY_LOG_H_

#include <fstream>
#include <list>
#include <string>

#define _WINDOWS

namespace TinyLogHelper
{
	template<typename T>
	T GetCurrentDir()
	{
	}

#ifdef _WINDOWS

	#include <windows.h>

	//////////////////////////////////////////////////////////////////////////
	//	线程互斥锁
	//////////////////////////////////////////////////////////////////////////
	class CLock
	{
	public:
		CLock()
		{
			InitializeCriticalSection(&m_cs);//初始化临界区
		}

		~CLock()
		{
			DeleteCriticalSection(&m_cs);//删除临界区
		}

		void Lock()
		{
			EnterCriticalSection(&m_cs);//加锁
		}

		void UnLock()
		{
			LeaveCriticalSection(&m_cs);//解锁
		}

	private:
		CRITICAL_SECTION m_cs;
	};

	//////////////////////////////////////////////////////////////////////////
	//	函数功能:
	//		获取当前目录
	//////////////////////////////////////////////////////////////////////////
	template<>
	std::string GetCurrentDir<std::string>();

	template<>
	std::wstring GetCurrentDir<std::wstring>();

#endif
}

namespace TinyLog
{
	//////////////////////////////////////////////////////////////////////////
	//						CTinyLog类修改记录								
	//	2014-5-24
	//		使用m_nLogBufferLength记录当前日志缓存的大小,而不使用GetLogBufferSize
	//		函数将整个日志缓存遍历一次来获取,提高运行速度。
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	//	日志等级
	//		LogLevelDebug等级,会输出所有日志信息
	//		LogLevelInfo等级,会输出INFO日志信息
	//		LogLevelError等级,会输出ERROR日志信息
	//////////////////////////////////////////////////////////////////////////
	enum LogLevel
	{
		LogLevelDebug,//调试
		LogLevelInfo,//信息
		LogLevelError,//错误
	};

	const static char* pszLogLevelString[3] = {
		"Debug",
		"Info",
		"Error"
	};

	//////////////////////////////////////////////////////////////////////////
	//	类说明:
	//		单线程日志类,应该只在一个线程中操作日志
	//////////////////////////////////////////////////////////////////////////
	template<typename T>
	class CTinyLog
	{

	};

	template<>
	class CTinyLog<char>
	{
	public:
		CTinyLog();

		~CTinyLog();

	public:
		//添加日志记录
		CTinyLog& operator <<(const char* pszMessage);

		//添加调试日志
		void Debug(const char* pszMessage);

		//添加信息日志
		void Info(const char* pszMessage);

		//添加错误日志
		void Error(const char* pszMessage);

		//将日志缓存写入到文件中
		CTinyLog& WriteToFile();

		//得到第一个写入文件路径
		std::string GetFirstWriteFilePath() const;

		//得到下一个写入文件路径
		std::string GetNextWriteFilePath() const;

		//得到文件路径格式
		std::string GetCurrentFilePathFormat() const;

	public://属性
		//设置文件
		bool SetFileDir(const std::string& strFileDir);

		//设置文件扩展名
		bool SetFillExtendName(const std::string& strFileExtendName);

		//设置文件名称格式
		bool SetFileNameFormat(const std::string& strFileNameFormat);

		//设置最大文件大小(字节)
		void SetMaxFileSize(std::size_t size);

		//设置最大写入文件大小(字节)
		void SetMaxWriteFileSize(std::size_t size);

		//设置最大文件个数
		void SetMaxFileCount(std::size_t count);

		//设置日志等级
		void SetLogLevel(LogLevel emLogLevel);

	private:
		//日志缓存
		std::list<std::string> m_lstLogBuffer;

		std::string m_strFileDir;//文件目录
		std::string m_strFileExtendName;//文件扩展名
		std::string m_strFileNameFormat;//文件名格式

		std::size_t m_nMaxFileSize;//最大文件大小(字节)
		std::size_t m_nMaxWriteFileSize;//最大写入文件大小(字节)
		mutable std::size_t m_nFileIndex;//文件索引
		std::size_t m_nFileCount;//文件最大个数

		LogLevel m_emLogLevel;//日志等级

		std::size_t m_nLogBufferLength;//日志缓存长度(字节)
	};

	template<>
	class CTinyLog<wchar_t>
	{

	};

	//////////////////////////////////////////////////////////////////////////
	//	类说明:
	//		多线程日志类,可以在多个线程中操作日志
	//////////////////////////////////////////////////////////////////////////
	template<typename T>
	class CTinyLogM
	{

	};

	template<>
	class CTinyLogM<char>
	{
	public:
		CTinyLogM();

		~CTinyLogM();

	public:
		//添加日志记录
		CTinyLogM& operator <<(const char* pszMessage);

		//添加调试日志
		void Debug(const char* pszMessage);

		//添加信息日志
		void Info(const char* pszMessage);

		//添加错误日志
		void Error(const char* pszMessage);

		//将日志缓存写入到文件中
		CTinyLogM& WriteToFile();

		//得到第一个写入文件路径
		std::string GetFirstWriteFilePath() const;

		//得到下一个写入文件路径
		std::string GetNextWriteFilePath() const;

		//得到文件路径格式
		std::string GetCurrentFilePathFormat() const;

	public://属性
		//设置文件目录
		bool SetFileDir(const std::string& strFileDir);

		//设置文件扩展名
		bool SetFillExtendName(const std::string& strFileExtendName);

		//设置文件名称格式
		bool SetFileNameFormat(const std::string& strFileNameFormat);

		//设置最大文件大小(字节)
		void SetMaxFileSize(std::size_t size);

		//设置最大写入文件大小(字节)
		void SetMaxWriteFileSize(std::size_t size);

		//设置最大文件个数
		void SetMaxFileCount(std::size_t count);

		//设置日志等级
		void SetLogLevel(LogLevel emLogLevel);

	private:
		//日志缓存
		std::list<std::string> m_lstLogBuffer;

		std::string m_strFileDir;//文件目录
		std::string m_strFileExtendName;//文件扩展名
		std::string m_strFileNameFormat;//文件名格式

		std::size_t m_nMaxFileSize;//最大文件大小(字节)
		std::size_t m_nMaxWriteFileSize;//最大写入文件大小(字节)
		mutable std::size_t m_nFileIndex;//文件索引
		std::size_t m_nFileCount;//文件最大个数
		//线程互斥锁
		mutable TinyLogHelper::CLock m_lock;
		
		LogLevel m_emLogLevel;//日志等级

		std::size_t m_nLogBufferLength;//日志缓存长度(字节)
	};

	template<>
	class CTinyLogM<wchar_t>
	{

	};
}

#endif

TinyLog.cpp文件

#include <time.h>
#include "TinyLog.h"

namespace TinyLogHelper
{
#ifdef _WINDOWS

	//////////////////////////////////////////////////////////////////////////
	//	函数功能:
	//		获取当前目录
	//////////////////////////////////////////////////////////////////////////
	template<>
	std::string GetCurrentDir<std::string>()
	{
		std::string s(256, '\0');
		DWORD dwLength = GetCurrentDirectoryA(s.size(), &s[0]);
		return s.substr(0, dwLength);
	}

	template<>
	std::wstring GetCurrentDir<std::wstring>()
	{
		std::wstring s(256, L'\0');
		DWORD dwLength = GetCurrentDirectoryW(s.size(), &s[0]);
		return s.substr(0, dwLength);
	}
#endif
}

namespace TinyLog
{
	CTinyLog<char>::CTinyLog()
	{
		m_strFileDir = TinyLogHelper::GetCurrentDir<std::string>();
		m_strFileDir += "/";
		SetFillExtendName(".log");
		SetFileNameFormat("_%d");

		SetMaxFileSize(1 * 1024 * 1024);//1 MB
		SetMaxWriteFileSize(4 * 1024);//4 KB
		SetMaxFileCount(10);
		m_nFileIndex = 1;
		m_emLogLevel = LogLevelInfo;
		m_nLogBufferLength = 0;
	}

	CTinyLog<char>::~CTinyLog()
	{
		WriteToFile();
	}

	//添加日志记录
	CTinyLog<char>& CTinyLog<char>::operator <<(const char* pszMessage)
	{
		time_t timet;
		struct tm* pTime = NULL;
		char szTime[256] = {0};
		int nCharNum = 0;
		//得到当前时间
		time(&timet);
		pTime = localtime(&timet);
		nCharNum = sprintf(szTime, "%02d-%02d-%02d\t", pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
		if (nCharNum > 0)
		{
			std::string s;
			s = s + szTime + pszMessage;
			m_lstLogBuffer.push_back(s);//添加记录
			m_nLogBufferLength += (s.size() + 2);
		}
		//写入缓存日志到文件
		if (m_nLogBufferLength > m_nMaxWriteFileSize)
		{
			WriteToFile();
		}

		return *this;
	}

	//添加调试日志
	void CTinyLog<char>::Debug(const char* pszMessage)
	{
		if (m_emLogLevel == LogLevelDebug)
		{
			std::string s = pszLogLevelString[m_emLogLevel];
			s = s + "\t" + pszMessage;
			*this << s.c_str();
		}
	}

	//添加信息日志
	void CTinyLog<char>::Info(const char* pszMessage)
	{
		if (m_emLogLevel == LogLevelInfo ||
			m_emLogLevel == LogLevelDebug)
		{
			std::string s = pszLogLevelString[m_emLogLevel];
			s = s + "\t" + pszMessage;
			*this << s.c_str();
		}
	}

	//添加错误日志
	void CTinyLog<char>::Error(const char* pszMessage)
	{
		if (m_emLogLevel == LogLevelError ||
			m_emLogLevel == LogLevelDebug)
		{
			std::string s = pszLogLevelString[m_emLogLevel];
			s = s + "\t" + pszMessage;
			*this << s.c_str();
		}
	}

	//将日志缓存写入到文件中
	CTinyLog<char>& CTinyLog<char>::WriteToFile()
	{
		bool bRet = false;
		
		try
		{
			std::string path;
			std::ofstream ofs;
			//打开第一个写入的文件
			path = GetFirstWriteFilePath();
			if (path.empty())
			{
				bRet = false;
				throw bRet;
			}
			ofs.open(path, std::ios::app);
			if (!ofs.is_open())
			{
				bRet = false;
				throw bRet;
			}
			std::size_t nFileSize = 0;
			std::list<std::string>::iterator beg, end;

			beg = m_lstLogBuffer.begin();
			end = m_lstLogBuffer.end();
			while (beg != end)
			{
				ofs.seekp(0, std::ios::end);
				nFileSize = ofs.tellp();
				if (nFileSize + beg->size() + 2 < m_nMaxFileSize)
				{
					ofs << *beg << std::endl;//回车换行
					m_nLogBufferLength -= (beg->size() + 2);
					beg = m_lstLogBuffer.erase(beg);
				}
				else
				{
					//打开下一个写入的文件
					path = GetNextWriteFilePath();
					if (path.empty())
					{
						bRet = false;
						throw bRet;
					}
					if (ofs.is_open())
					{
						ofs.close();
					}
					ofs.open(path, std::ios::app);
					if (!ofs.is_open())
					{
						bRet = false;
						throw bRet;
					}
				}
			}
			bRet = true;
		}
		catch (bool)
		{
		}

		return *this;
	}

	//得到第一个写入文件路径
	std::string CTinyLog<char>::GetFirstWriteFilePath() const
	{
		std::string path;

		try
		{
			std::string strPathFromat = GetCurrentFilePathFormat();
			std::size_t nPos = strPathFromat.rfind("%d");
			if (nPos == strPathFromat.npos)
			{
				path = "";
				throw path;
			}

			std::string strTempPath;
			char szNumber[32] = {0};
			std::ifstream file;

			for (std::size_t i = m_nFileIndex; i < m_nFileCount + 1; ++i)
			{
				memset(szNumber, 0, 32);
				itoa(i, szNumber, 10);
				strTempPath = strPathFromat;
				strTempPath.replace(nPos, 2, szNumber);

				file.open(strTempPath, std::ios::app);
				if (file.is_open())
				{
					file.seekg(0, std::ios::end);
					if (file.tellg() < m_nMaxFileSize)
					{
						m_nFileIndex = i;
						path = strTempPath;
						break;
					}
				}
				else
				{
					m_nFileIndex = i;
					path = strTempPath;
					break;
				}
			}
		}
		catch (const std::string&)
		{
		}

		return path;
	}

	//得到下一个写入文件路径
	std::string CTinyLog<char>::GetNextWriteFilePath() const
	{
		std::string path;
		std::string strFilePathFormat;
		std::size_t nPos = 0;
		char szNum[32] = {0};

		if (m_nFileIndex > m_nFileCount-1)
		{
			return path;
		}
		strFilePathFormat = GetCurrentFilePathFormat();
		nPos = strFilePathFormat.rfind("%d");
		if (nPos != strFilePathFormat.npos)
		{
			++m_nFileIndex;
			itoa(m_nFileIndex, szNum, 10);
			path = strFilePathFormat;
			path.replace(nPos, 2, szNum);
		}
		return path;
	}

	//得到文件路径格式
	std::string CTinyLog<char>::GetCurrentFilePathFormat() const
	{
		//文件路径格式
		std::string strFilePathFormat;

		try
		{
			if (m_strFileDir.empty() ||
				m_strFileNameFormat.empty() ||
				m_strFileExtendName.empty())
			{
				strFilePathFormat = "";
				throw strFilePathFormat;
			}
			//获取本地时间
			time_t timet;
			struct tm* pTime = NULL;
			char szTime[256] = {0};

			time(&timet);
			pTime = localtime(&timet);
			sprintf(szTime, "%d-%02d-%02d", 1900 + pTime->tm_year, 1 + pTime->tm_mon, pTime->tm_mday);
			strFilePathFormat = m_strFileDir + szTime + m_strFileNameFormat + m_strFileExtendName;
		}
		catch (const std::string&)
		{
		}

		return strFilePathFormat;
	}

	//设置文件目录
	bool CTinyLog<char>::SetFileDir(const std::string& strFileDir)
	{
		if (!strFileDir.empty() &&
			(strFileDir.back() == '\\' ||
			strFileDir.back() == '/'))
		{
			m_strFileDir = strFileDir;
			return true;
		}
		return false;
	}

	//设置文件扩展名
	bool CTinyLog<char>::SetFillExtendName(const std::string& strFileExtendName)
	{
		if (strFileExtendName.size() > 1 &&
			strFileExtendName.front() == '.')
		{
			m_strFileExtendName = strFileExtendName;
			return true;
		}
		return false;
	}

	//设置文件名称格式
	bool CTinyLog<char>::SetFileNameFormat(const std::string& strFileNameFormat)
	{
		if (strFileNameFormat.size() > 1 &&
			strFileNameFormat.find("%d") != strFileNameFormat.npos)
		{
			m_strFileNameFormat = strFileNameFormat;
			return true;
		}
		return false;
	}

	//设置最大文件大小(字节)
	void CTinyLog<char>::SetMaxFileSize(std::size_t size)
	{
		m_nMaxFileSize = size;
	}

	//设置最大写入文件大小(字节)
	void CTinyLog<char>::SetMaxWriteFileSize(std::size_t size)
	{
		m_nMaxWriteFileSize = size;
	}

	//设置最大文件个数
	void CTinyLog<char>::SetMaxFileCount(std::size_t count)
	{
		m_nFileCount = count;
	}

	//设置日志等级
	void CTinyLog<char>::SetLogLevel(LogLevel emLogLevel)
	{
		m_emLogLevel = emLogLevel;
	}


	//////////////////////////////////////////////////////////////////////////
	//	类说明:
	//		多线程日志类,可以在多个线程中操作日志
	//////////////////////////////////////////////////////////////////////////
	CTinyLogM<char>::CTinyLogM()
	{
		m_strFileDir = TinyLogHelper::GetCurrentDir<std::string>();
		m_strFileDir += "/";
		SetFillExtendName(".log");
		SetFileNameFormat("_%d");

		SetMaxFileSize(1 * 1024 * 1024);//1 MB
		SetMaxWriteFileSize(4 * 1024);//4 KB
		SetMaxFileCount(10);
		m_nFileIndex = 1;
		m_emLogLevel = LogLevelInfo;
		m_nLogBufferLength = 0;
	}

	CTinyLogM<char>::~CTinyLogM()
	{
		WriteToFile();
	}

	//添加日志记录
	CTinyLogM<char>& CTinyLogM<char>::operator <<(const char* pszMessage)
	{
		time_t timet;
		struct tm* pTime = NULL;
		char szTime[256] = {0};
		int nCharNum = 0;

		time(&timet);
		pTime = localtime(&timet);
		nCharNum = sprintf(szTime, "%02d-%02d-%02d\t", pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
		if (nCharNum > 0)
		{
			std::string s;
			s = s + szTime + pszMessage;
			m_lock.Lock();
			m_lstLogBuffer.push_back(s);
			m_nLogBufferLength += (s.size() + 2);
			m_lock.UnLock();
		}

		if (m_nLogBufferLength > m_nMaxWriteFileSize)
		{
			WriteToFile();
		}

		return *this;
	}

	//添加调试日志
	void CTinyLogM<char>::Debug(const char* pszMessage)
	{
		if (m_emLogLevel == LogLevelDebug)
		{
			*this << pszLogLevelString[m_emLogLevel] << "\t" << pszMessage;
		}
	}

	//添加信息日志
	void CTinyLogM<char>::Info(const char* pszMessage)
	{
		if (m_emLogLevel == LogLevelInfo ||
			m_emLogLevel == LogLevelDebug)
		{
			*this << pszLogLevelString[m_emLogLevel] << "\t" << pszMessage;
		}
	}

	//添加错误日志
	void CTinyLogM<char>::Error(const char* pszMessage)
	{
		if (m_emLogLevel == LogLevelError ||
			m_emLogLevel == LogLevelDebug)
		{
			*this << pszLogLevelString[m_emLogLevel] << "\t" << pszMessage;
		}
	}

	//将日志缓存写入到文件中
	CTinyLogM<char>& CTinyLogM<char>::WriteToFile()
	{
		bool bRet = false;

		try
		{
			std::string path;
			std::ofstream ofs;
			
			//打开第一个写入的文件
			path = GetFirstWriteFilePath();
			if (path.empty())
			{
				bRet = false;
				throw bRet;
			}
			m_lock.Lock();
			ofs.open(path, std::ios::app);
			if (!ofs.is_open())
			{
				bRet = false;
				throw bRet;
			}
			std::size_t nFileSize = 0;
			std::list<std::string>::iterator beg, end;

			beg = m_lstLogBuffer.begin();
			end = m_lstLogBuffer.end();
			while (beg != end)
			{
				ofs.seekp(0, std::ios::end);
				nFileSize = ofs.tellp();
				if (nFileSize + beg->size() + 2 < m_nMaxFileSize)
				{
					ofs << *beg << std::endl;//回车换行
					m_nLogBufferLength -= (beg->size() + 2);
					beg = m_lstLogBuffer.erase(beg);
				}
				else
				{
					//打开下一个写入的文件
					path = GetNextWriteFilePath();
					if (path.empty())
					{
						bRet = false;
						throw bRet;
					}
					if (ofs.is_open())
					{
						ofs.close();
					}
					ofs.open(path, std::ios::app);
					if (!ofs.is_open())
					{
						bRet = false;
						throw bRet;
					}
				}
			}
			bRet = true;
		}
		catch (bool)
		{
		}

		m_lock.UnLock();
		return *this;
	}

	//得到第一个写入文件路径
	std::string CTinyLogM<char>::GetFirstWriteFilePath() const
	{
		std::string path;

		try
		{
			std::string strPathFromat = GetCurrentFilePathFormat();
			std::size_t nPos = strPathFromat.rfind("%d");
			if (nPos == strPathFromat.npos)
			{
				path = "";
				throw path;
			}

			std::string strTempPath;
			char szNumber[32] = {0};
			std::ifstream file;

			m_lock.Lock();
			for (std::size_t i = m_nFileIndex; i < m_nFileCount + 1; ++i)
			{
				memset(szNumber, 0, 32);
				itoa(i, szNumber, 10);
				strTempPath = strPathFromat;
				strTempPath.replace(nPos, 2, szNumber);

				file.open(strTempPath, std::ios::app);
				if (file.is_open())
				{
					file.seekg(0, std::ios::end);
					if (file.tellg() < m_nMaxFileSize)
					{
						m_nFileIndex = i;
						path = strTempPath;
						break;
					}
				}
				else
				{
					m_nFileIndex = i;
					path = strTempPath;
					break;
				}
			}
			m_lock.UnLock();
		}
		catch (const std::string&)
		{
		}

		return path;
	}

	//得到下一个写入文件路径
	std::string CTinyLogM<char>::GetNextWriteFilePath() const
	{
		std::string path;
		std::string strFilePathFormat;
		std::size_t nPos = 0;
		char szNum[32] = {0};

		if (m_nFileIndex > m_nFileCount-1)
		{
			return path;
		}
		strFilePathFormat = GetCurrentFilePathFormat();
		nPos = strFilePathFormat.rfind("%d");
		if (nPos != strFilePathFormat.npos)
		{
			m_lock.Lock();
			++m_nFileIndex;
			m_lock.UnLock();
			itoa(m_nFileIndex, szNum, 10);
			path = strFilePathFormat;
			path.replace(nPos, 2, szNum);
		}
		return path;
	}

	//得到文件路径格式
	std::string CTinyLogM<char>::GetCurrentFilePathFormat() const
	{
		//文件路径格式
		std::string strFilePathFormat;

		try
		{
			if (m_strFileDir.empty() ||
				m_strFileNameFormat.empty() ||
				m_strFileExtendName.empty())
			{
				strFilePathFormat = "";
				throw strFilePathFormat;
			}
			//获取本地时间
			time_t timet;
			struct tm* pTime = NULL;
			char szTime[256] = {0};

			time(&timet);
			pTime = localtime(&timet);
			sprintf(szTime, "%d-%02d-%02d", 1900 + pTime->tm_year, 1 + pTime->tm_mon, pTime->tm_mday);
			strFilePathFormat = m_strFileDir + szTime + m_strFileNameFormat + m_strFileExtendName;
		}
		catch (const std::string&)
		{
		}

		return strFilePathFormat;
	}

	//设置文件目录
	bool CTinyLogM<char>::SetFileDir(const std::string& strFileDir)
	{
		if (!strFileDir.empty() &&
			(strFileDir.back() == '\\' ||
			strFileDir.back() == '/'))
		{
			m_lock.Lock();
			m_strFileDir = strFileDir;
			m_lock.UnLock();
			return true;
		}
		return false;
	}

	//设置文件扩展名
	bool CTinyLogM<char>::SetFillExtendName(const std::string& strFileExtendName)
	{
		if (strFileExtendName.size() > 1 &&
			strFileExtendName.front() == '.')
		{
			m_lock.Lock();
			m_strFileExtendName = strFileExtendName;
			m_lock.UnLock();
			return true;
		}
		return false;
	}

	//设置文件名称格式
	bool CTinyLogM<char>::SetFileNameFormat(const std::string& strFileNameFormat)
	{
		if (strFileNameFormat.size() > 1 &&
			strFileNameFormat.find("%d") != strFileNameFormat.npos)
		{
			m_lock.Lock();
			m_strFileNameFormat = strFileNameFormat;
			m_lock.UnLock();
			return true;
		}
		return false;
	}

	//设置最大文件大小(字节)
	void CTinyLogM<char>::SetMaxFileSize(std::size_t size)
	{
		m_lock.Lock();
		m_nMaxFileSize = size;
		m_lock.UnLock();
	}

	//设置最大写入文件大小(字节)
	void CTinyLogM<char>::SetMaxWriteFileSize(std::size_t size)
	{
		m_lock.Lock();
		m_nMaxWriteFileSize = size;
		m_lock.UnLock();
	}

	//设置最大文件个数
	void CTinyLogM<char>::SetMaxFileCount(std::size_t count)
	{
		m_nFileCount = count;
	}

	//设置日志等级
	void CTinyLogM<char>::SetLogLevel(LogLevel emLogLevel)
	{
		m_emLogLevel = emLogLevel;
	}
}

测试:

TinyLog::CTinyLog<char> log;

	log.SetMaxFileSize(1 * 1024 * 1024);
	log.SetMaxWriteFileSize(1 * 1024 * 1024);
	log.SetLogLevel(TinyLog::LogLevelError);
	for (int i = 0; i < 60000; ++i)
	{
		log.Error("Hello Word!");
	}
	log.WriteToFile();


 

posted on 2014-05-25 19:50  dchao  阅读(570)  评论(0编辑  收藏  举报

导航