• 參考mudo logging写的win下logging


    #pragma once
    #include <boost/noncopyable.hpp>
    #include <boost/scoped_ptr.hpp>
    #include <boost/ptr_container/ptr_vector.hpp>
    #include <boost/thread.hpp>
    #include <boost/thread/mutex.hpp>
    
    class CountDownLatch : boost::noncopyable
    {
    public:
    
    	explicit CountDownLatch(int count);
    
    	void wait();
    
    	void countDown();
    
    	int getCount();
    
    private:
    	boost::mutex			m_Mutex;
    	boost::condition_variable m_ConditionVar;
    	int count_;
    };
    

    #include "stdafx.h"
    #include "CountDownLatch.h"
    
    
    CountDownLatch::CountDownLatch(int count)
    	: count_(count)
    {
    }
    
    void CountDownLatch::wait()
    {
    	boost::mutex::scoped_lock lock(m_Mutex);
    	while (count_ > 0) {
    		m_ConditionVar.wait(lock);
    	}
    }
    
    void CountDownLatch::countDown()
    {
    	boost::mutex::scoped_lock lock(m_Mutex);
    	--count_;
    	if (count_ == 0) {
    		m_ConditionVar.notify_all();
    	}
    }
    
    int CountDownLatch::getCount()
    {
    	boost::mutex::scoped_lock lock(m_Mutex);
    	return count_;
    }
    

    #pragma once
    #include <string>
    #include <boost/noncopyable.hpp>
    using namespace std;
    const int kSmallBuffer = 4000;
    const int kLargeBuffer = 4000*1000;
    
    template<int SIZE>
    class FixedBuffer : boost::noncopyable
    {
    public:
    	FixedBuffer()
    		: cur_(data_)
    	{
    		setCookie(cookieStart);
    	}
    
    	~FixedBuffer()
    	{
    		setCookie(cookieEnd);
    	}
    
    	void append(const char*  buf, size_t len)
    	{
    		if (static_cast<size_t>(avail()) > len)
    		{
    			memcpy(cur_, buf, len);
    			cur_ += len;
    		}
    	}
    
    	const char* data() const { return data_; }
    	int length() const { return static_cast<int>(cur_ - data_); }
    
    	// write to data_ directly
    	char* current() { return cur_; }
    	int avail() const { return static_cast<int>(end() - cur_); }
    	void add(size_t len) { cur_ += len; }
    
    	void reset() { cur_ = data_; }
    	void bzero() { memset(data_, 0, sizeof(data_)); }
    	void setCookie(void (*cookie)()) { cookie_ = cookie; }
    	string asString() const { return string(data_, length()); }
    
    private:
    	const char* end() const { return data_ + sizeof data_; }
    	// Must be outline function for cookies.
    	static void cookieStart();
    	static void cookieEnd();
    
    	void (*cookie_)();
    	char data_[SIZE];
    	char* cur_;
    };
    

    #pragma once
    #include <boost/date_time/posix_time/posix_time.hpp> 
    #include "boost/date_time/gregorian/gregorian.hpp"
    #include "boost/atomic/atomic.hpp"
    #include <queue>
    #include <string>
    #include <boost/bind.hpp>
    #include <boost/noncopyable.hpp>
    #include <boost/scoped_ptr.hpp>
    #include <boost/ptr_container/ptr_vector.hpp>
    #include <boost/thread.hpp>
    #include <boost/thread/mutex.hpp>
    #include "FixedBuffer.h"
    #include "CountDownLatch.h"
    
    enum LoggingEnum{
    	LOG_INFO,
    	LOG_DBBUG,
    	LOG_ERROR,
    	LOG_WARNNING,
    	LOG_END
    };
    
    enum GLogColor {
    	COLOR_DEFAULT,
    	COLOR_RED,
    	COLOR_GREEN,
    	COLOR_YELLOW
    };
    
    class Logging
    {
    public:
    	Logging();
    	~Logging();
    	void	WriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...);
    	void	WriteMsg(LoggingEnum eLoggingEnum, char* fun, int line, char* msg);
    
    private:
    	int		CreateLogFile(LoggingEnum aLoggingEnum);
    	void	Write(LoggingEnum eLoggingEnum, char* msg, int msgLen);
    	void threadFunc();
    private:
    	bool running_;
    	FILE*					m_File[LOG_END];
    	typedef boost::posix_time::ptime PTIME;
    	std::string					m_AppPreStr;
    	typedef FixedBuffer<kLargeBuffer> Buffer;
    	typedef boost::ptr_vector<Buffer> BufferVector;
    	typedef BufferVector::auto_type BufferPtr;
    	BufferPtr currentBuffer_;
    	BufferPtr nextBuffer_;
    	BufferVector buffers_;
    	boost::thread			m_Thread;
    	boost::mutex			m_Mutex;
    	boost::condition_variable m_ConditionVar;
    	CountDownLatch latch_;
    };

    #include "Logging.h"
    #include <iomanip>
    #include <sstream>
    #include <fcntl.h>
    #include <io.h>
    #include <Windows.h>
    #include "SSActive.h"
    
    Logging g_Logging;
    string LOGPreStr[LOG_END] = {"LOG_INFO", "LOG_DBBUG", "LOG_ERROR", "LOG_WARNNING"};
    
    #ifdef _WINDOWS
    // Returns the character attribute for the given color.
    WORD GetColorAttribute(GLogColor color) {
    	switch (color) {
    	case COLOR_RED:    return FOREGROUND_RED;
    	case COLOR_GREEN:  return FOREGROUND_GREEN;
    	case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
    	default:           return 0;
    	}
    }
    #else
    // Returns the ANSI color code for the given color.
    const char* GetAnsiColorCode(GLogColor color) {
    	switch (color) {
    	case COLOR_RED:     return "1";
    	case COLOR_GREEN:   return "2";
    	case COLOR_YELLOW:  return "3";
    	case COLOR_DEFAULT:  return "";
    	};
    	return NULL; // stop warning about return type.
    }
    
    #endif  // OS_WINDOWS
    
    GLogColor GLogColorVec[LOG_END] = {COLOR_GREEN, COLOR_DEFAULT, COLOR_RED, COLOR_YELLOW};
    
    Logging::Logging():latch_(1){
    	currentBuffer_.reset(new Buffer);
    	currentBuffer_->bzero();
    
    	nextBuffer_.reset(new Buffer);
    	nextBuffer_->bzero();
    
    	buffers_.reserve(16);
    
    	boost::mutex::scoped_lock lock(m_Mutex);
    	char szAppPath[256] = "";
    	::GetModuleFileNameA(0, szAppPath, 256);
    	m_AppPreStr = szAppPath;
    	m_AppPreStr = m_AppPreStr.substr(m_AppPreStr.rfind("\") + 1);
    	m_AppPreStr = m_AppPreStr.substr(0, m_AppPreStr.size()-4);
    
    	int n32Res = 0;
    	for (int i = LOG_INFO; i < LOG_END; ++i){
    		m_File[i] = NULL;
    	}
    
    	n32Res = CreateLogFile(LOG_INFO);
    	if (n32Res != 0){
    		printf("Createfile(i) failed", 0);
    	}
    
    	lock.unlock();
    
    	running_ = true;
    	m_Thread = boost::thread(&Logging::threadFunc, this);
    	latch_.wait();
    }
    
    void Logging::WriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...){
    	if (eLoggingEnum < LOG_INFO || eLoggingEnum > LOG_WARNNING){
    		eLoggingEnum = eLoggingEnum;
    	}
    
    	char tmp[1024] = {0};
    	PTIME nowTime = boost::posix_time::microsec_clock::local_time();
    	sprintf(tmp, "%s.%d %s:%d ", boost::posix_time::to_iso_string(nowTime).c_str(), boost::this_thread::get_id(), fun, line);
    	int curPos = strlen(tmp);
    
    	va_list pArg = NULL;
    	va_start(pArg, msg);
    	vsprintf(tmp+curPos, msg, pArg);
    	va_end(pArg);
    
    	curPos = strlen(tmp);
    	char end[] = "
    ";
    	sprintf(tmp + curPos, "%s", end);
    
    	int totlen = curPos + 1;
    	boost::mutex::scoped_lock lock(m_Mutex);
    	if (currentBuffer_->avail() > totlen)
    	{
    		currentBuffer_->append(tmp, totlen);
    	}
    	else
    	{
    		buffers_.push_back(currentBuffer_.release());
    
    		if (nextBuffer_)
    		{
    			currentBuffer_ = boost::ptr_container::move(nextBuffer_);
    		}
    		else
    		{
    			currentBuffer_.reset(new Buffer); // Rarely happens
    		}
    		currentBuffer_->append(tmp, totlen);
    		m_ConditionVar.notify_all();
    	}
    }
    
    Logging::~Logging(){
    	running_ = false;
    	m_ConditionVar.notify_all();
    	m_Thread.join();
    
    	for (INT32 i = 0; i < 4; ++i){
    		if (NULL != m_File[i]){
    			fclose(m_File[i]);
    		}
    	}
    }
    
    
    int Logging::CreateLogFile(LoggingEnum aLoggingEnum){
    	string strPre;
    	switch (aLoggingEnum){
    	case LOG_DBBUG:
    		strPre = "DBBUG";
    		break;
    	case LOG_INFO:
    		strPre = "INFO";
    		break;
    	case LOG_WARNNING:
    		strPre = "WARNNING";
    		break;
    	case LOG_ERROR:
    		strPre = "ERROR";
    		break;
    	}
    	char str[128];
    	sprintf(str, "./Log/%s-%s-%d-%s", m_AppPreStr.c_str(), strPre.c_str() ,boost::this_thread::get_id(), boost::posix_time::to_iso_string(boost::posix_time::microsec_clock::local_time()).c_str());
    	string fileName(str);
    	fileName += ".log";
    	int fd = open(fileName.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0664);
    	if (fd == -1){
    		printf("%s create(%d) file error
    ", __FUNCTION__, aLoggingEnum);
    		return -1;
    	}
    
    	m_File[aLoggingEnum] = fdopen(fd, "a");
    	if (NULL == m_File[aLoggingEnum]){
    		printf("%s open file(%d) failed
    ", __FUNCTION__, aLoggingEnum);
    		return -1;
    	}
    
    	return 0;
    }
    
    void Logging::threadFunc()
    {
    	assert(running_ == true);
    	latch_.countDown();
    	BufferPtr newBuffer1(new Buffer);
    	BufferPtr newBuffer2(new Buffer);
    	newBuffer1->bzero();
    	newBuffer2->bzero();
    	BufferVector buffersToWrite;
    	buffersToWrite.reserve(16);
    
    	while (running_)
    	{
    		assert(newBuffer1 && newBuffer1->length() == 0);
    		assert(newBuffer2 && newBuffer2->length() == 0);
    		assert(buffersToWrite.empty());
    
    		{
    			boost::mutex::scoped_lock lock(m_Mutex);
    			if (buffers_.empty())  // unusual usage!
    			{
    				m_ConditionVar.wait(lock);
    			}
    
    			buffers_.push_back(currentBuffer_.release());
    			currentBuffer_ = boost::ptr_container::move(newBuffer1);
    			buffersToWrite.swap(buffers_);
    			if (!nextBuffer_)
    			{
    				nextBuffer_ = boost::ptr_container::move(newBuffer2);
    			}
    		}
    
    		assert(!buffersToWrite.empty());
    
    		if (buffersToWrite.size() > 25)
    		{
    			buffersToWrite.erase(buffersToWrite.begin()+2, buffersToWrite.end());
    		}
    
    		for (size_t i = 0; i < buffersToWrite.size(); ++i)
    		{
    			fwrite(buffersToWrite[i].data(), buffersToWrite[i].length(), 1, stderr);
    			fflush(stderr);
    
    			fwrite(buffersToWrite[i].data(), 1, buffersToWrite[i].length(), m_File[0]);
    			fflush(m_File[0]);
    		}
    
    		if (buffersToWrite.size() > 2)
    		{
    			// drop non-bzero-ed buffers, avoid trashing
    			buffersToWrite.resize(2);
    		}
    
    		if (!newBuffer1)
    		{
    			assert(!buffersToWrite.empty());
    			newBuffer1 = buffersToWrite.pop_back();
    			newBuffer1->reset();
    		}
    
    		if (!newBuffer2)
    		{
    			assert(!buffersToWrite.empty());
    			newBuffer2 = buffersToWrite.pop_back();
    			newBuffer2->reset();
    		}
    
    		buffersToWrite.clear();
    	}
    }
    
    临时还没想清楚,假设写多个日志等级,logging的锁 应该怎样加。
  • 相关阅读:
    静态类、抽象类的笔记
    第一篇
    流复制操作
    速记服务器状态码
    访问修饰符
    jquery对象、js全局变量等tips
    Caching and Indexing
    Using X++ copy the favorites from one user to another
    SID
    Using X++ get Language List from Dynamics AX 2009
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7044982.html
Copyright © 2020-2023  润新知