晓寒的小屋

随笔分类

随笔档案

相册

最新评论

阅读排行榜

评论排行榜

程序员博客   首页  新随笔  订阅  管理  登录 
 
晓寒 阅读(2009) 评论(8)
类图:
 
序列图:

下面是代码:
CHLogger.h
/**
*  @file     CHLogger.h
*  @class    CHLogger
*  @author   flyingleaf
*  @version  1.0.0.0
*  @date     2006-08-11
*  @brief    您可以任使用此文件,但是需要保留本声明
*  @notice   1、使用<<输出日志时没有时间戳
             2、logger和使用的stream之间是关联:logger不负责stream的生命周期 
*/


#ifndef _XHJ_CHLogger_h_
#define _XHJ_CHLogger_h_

#include 
<string>
#include 
<fstream>
#include 
<CHMutex.h>
#include 
<CHStream.h>
#include 
<vector>
#include 
<CHTime.n>

using namespace std;

namespace XHJ   
{
    
class CHLogger
    
{
    
public:  
        
//日志级别
        typedef enum
        
{
            InfoLevel    
= 1,    //信息级别
            WarningLevel = 2,    //告警级别
            ErrorLevel   = 4     //error级别
        }
LogLevel;

        CHLogger(
const char* fileName = "CHLogger.debug"): 
            m_LogLevel(LogLevel::InfoLevel)
        
{
        }


        
~CHLogger()
        
{
        }


        
void AddStream(CHLogStream*);
        
void RemoveStream(const CHLogStream*);
        
void ClearStream();

        
virtual void Info(const string&);
        
virtual void Warning(const string&);
        
virtual void Error(const string&);

        
//设置告警级别
        void SetLogLevel(const LogLevel& );

        
//只有信息级别的时候,通过该接口的信息才能够显示
        CHLogger& operator << ( const string& );

        CHLogger
& operator << ( ostream& (&)(ostream&) );

    
protected:
        
void WriteLog(const string&const LogLevel& level = InfoLevel);   

    
private:    
        LogLevel m_LogLevel;       
//告警级别

        vector
<CHLogStream*> m_Streams;
        CHMutex m_instanceMutex;                
    }
;   

}

#endif

CHLogger.cpp
#include "StdAfx.h"
#include 
"CHlogger.h"

namespace XHJ
{
    
//可以添加重复的
    void CHLogger::AddStream(CHLogStream* stream)
    
{
        Lock 
lock(m_instanceMutex);


        m_Streams.push_back(stream);
    }

    
    
//删除所有同名字的
    void CHLogger::RemoveStream(const CHLogStream* stream)
    
{
        Lock 
lock(m_instanceMutex);
        
        vector
<CHLogStream*>::iterator pos = m_Streams.begin();
        
for( ;    pos != m_Streams.end();    )
        
{
            
if((*pos)->StreamName() == stream->StreamName())
            
{
                pos 
= m_Streams.erase(pos);
                
continue;
            }


            
++pos;
        }

    }


    
void CHLogger::ClearStream()
    
{
        Lock 
lock(m_instanceMutex);

        m_Streams.clear();
    }


    
void CHLogger::WriteLog(const string& message,const LogLevel& level)
    
{
        
//告警级别不够的,不输出
        if(level < m_LogLevel) return;

        
for(vector<CHLogStream*>::iterator pos = m_Streams.begin();
            pos 
!= m_Streams.end();
            
++pos)
        
{
            (
*pos)->WriteData(message.c_str());
        }

    }


    
void CHLogger::SetLogLevel(const LogLevel& level)
    
{
        Lock 
lock(m_instanceMutex);

        m_LogLevel 
= level;
    }



    
void CHLogger::Info(const string& message)
    
{
        Lock sync(m_instanceMutex);

        WriteLog(CHTime::now().toString() 
+ " info:    " + message);
    }


    CHLogger  
& CHLogger::operator << ( const string& message)
    
{     
        Lock 
lock(m_instanceMutex);

        WriteLog(message);

        
return *this;
    }


    CHLogger
& CHLogger::operator << ( ostream& (&)(ostream&) )
    
{
        Lock 
lock(m_instanceMutex);

        WriteLog(
" ");

        
return (*this);
    }


    
void CHLogger::Warning(const string& message)
    
{
        Lock sync(m_instanceMutex);

        WriteLog(CHTime::now().toString() 
+ " warning: " + message,WarningLevel);
    }


    
void CHLogger::Error(const string& message)
    
{
        Lock sync(m_instanceMutex);

        WriteLog(CHTime::now().toString() 
+ " error:   " + message , ErrorLevel);
    }

}

CHLogStream.h 没有cpp
/**
*  @file     CHLogStream.h
*  @class    CHLogStream
*  @author   flyingleaf
*  @version  1.0.0.0
*  @date     2006-08-11
*  @brief    您可以任使用此文件,但是需要保留本声明
*/


#ifndef _XHJ_CHStream_h_
#define _XHJ_CHStream_h_
#include 
<windows.h>
#include 
<string>

using namespace std;

namespace XHJ
{
    
class CHLogStream
    
{
    
public:
        CHLogStream(
void{ m_StreamName = "CHLogStream" ;}
        
virtual ~CHLogStream(void){};

        
virtual void Init()=0;
        
virtual void WriteData(const char*)=0;
        
virtual void WriteData(void*)=0;

        
string StreamName()const return m_StreamName;}
        
void SetStreamName(const string& name) { m_StreamName = name;}

    
private:
        
string m_StreamName;
    }
;

    
class CHConLogStream:public CHLogStream
    
{
    
public:
        CHConLogStream(
const string& name = "CHConLogStream")
        
{
            SetStreamName(name);
        }


        
void Init()
        
{
        }


        
void WriteData(const char* data)
        
{
            cout 
<< data;
        }


        
void WriteData(void* data)
        
{
            cout 
<< data;
        }

    }
;
}

#endif

CHTime在评论中贴,否则篇幅过长,怕贴不出来了 :P

评论列表
晓寒
re: 基础库___日志输出
测试该logger
    //声明一个log实例并设置告警级别
    CHLogger logger;
    logger.SetLogLevel(CHLogger::LogLevel::InfoLevel);

    
//添加输出方式
    CHLogStream* stream = new CHConLogStream;
    logger.AddStream(stream);

    
//测试输出
    logger << "hello" << "您好" << endl << endl;
    logger.Info(
"dd ");
    logger.Warning(
"dds ");
    logger.Error(
"asd ");

    
//更改告警级别,再次测试
    logger.SetLogLevel(CHLogger::LogLevel::WarningLevel);
    logger.Info(
"dd ");
    logger.Warning(
"dds ");
    logger.Error(
"asd ");

    
//释放输出资源
    delete stream;
晓寒
re: 基础库___日志输出
chtime.h
/**
*  @file     CHTime.h
*  @class    CHTime
*  @author   flyingleaf
*  @version  1.0.0.0
*  @date     2006-08-11
*  @brief    您可以任使用此文件,但是需要保留本声明
*/

#ifndef _XHJ_CHTime_h_
#define _XHJ_CHTime_h_
#include 
<windows.h>
#include 
<string>
#include 
<sstream>
#include 
<iostream>
#include 
<time.h>
#include 
<sys/timeb.h>

using namespace std;

namespace XHJ
{
    
class CHTime
    
{
    
public:
        CHTime(
void): m_Seconds(0){}

        
~CHTime(void){}

        
static CHTime now();
        
static CHTime seconds(__int64);
        
static CHTime milliSeconds(__int64);
        
static CHTime microSeconds(__int64);

        __int64 toSeconds() 
const;
        __int64 toMilliSeconds() 
const;
        __int64 toMicroSeconds() 
const;

        std::
string toString() const

        CHTime 
operator-(const CHTime& ts) const
        
{
            
return CHTime(m_Seconds - ts.m_Seconds);
        }


        CHTime 
operator+(const CHTime& ts) const
        
{
            
return CHTime(m_Seconds + ts.m_Seconds);
        }


        CHTime
& operator+=(const CHTime& ts)
        
{
            m_Seconds 
+= ts.m_Seconds;
            
return *this;
        }


        CHTime
& operator-=(const CHTime& ts)
        
{
            m_Seconds 
-= ts.m_Seconds;
            
return *this;
        }


        
bool operator<(const CHTime& ts) const
        
{
            
return m_Seconds < ts.m_Seconds;
        }


        
bool operator<=(const CHTime& ts) const
        
{
            
return m_Seconds <= ts.m_Seconds;
        }


        
bool operator>(const CHTime& ts) const
        
{
            
return m_Seconds > ts.m_Seconds;
        }


        
bool operator>=(const CHTime& ts) const
        
{
            
return m_Seconds >= ts.m_Seconds;
        }


        
bool operator==(const CHTime& ts) const
        
{
            
return m_Seconds == ts.m_Seconds;
        }


        
bool operator!=(const CHTime& ts) const
        
{
            
return m_Seconds != ts.m_Seconds;
        }


        
double operator/(const CHTime& ts) const
        
{
            
return (double)m_Seconds / (double)ts.m_Seconds;
        }


        CHTime
& operator*=(int ts)
        
{
            m_Seconds 
*= ts;
            
return *this;
        }


        CHTime 
operator*(int ts) const
        
{
            CHTime t;
            t.m_Seconds 
= m_Seconds * ts;
            
return t;
        }


        CHTime
& operator/=(int ts)
        
{
            m_Seconds 
/= ts;
            
return *this;
        }


        CHTime 
operator/(int ts) const
        
{
            CHTime t;
            t.m_Seconds 
= m_Seconds / ts;
            
return t;
        }


        CHTime
& operator*=(__int64 ts)
        
{
            m_Seconds 
*= ts;
            
return *this;
        }


        CHTime 
operator*(__int64 ts) const
        
{
            CHTime t;
            t.m_Seconds 
= m_Seconds * ts;
            
return t;
        }


        CHTime
& operator/=(__int64 ts)
        
{
            m_Seconds 
/= ts;
            
return *this;
        }


        CHTime 
operator/(__int64 ts) const
        
{
            CHTime t;
            t.m_Seconds 
= m_Seconds / ts;
            
return t;
        }


        CHTime
& operator*=(double ts)
        
{
            m_Seconds 
= static_cast<__int64>(static_cast<double>(m_Seconds) * ts);
            
return *this;
        }


        CHTime 
operator*(double ts) const
        
{
            CHTime t;
            t.m_Seconds 
= static_cast<__int64>(static_cast<double>(m_Seconds) * ts);
            
return t;
        }


        CHTime
& operator/=(double ts)
        
{
            m_Seconds 
= static_cast<__int64>(static_cast<double>(m_Seconds) / ts);
            
return *this;
        }


        CHTime 
operator/(double ts) const
        
{
            CHTime t;
            t.m_Seconds 
= static_cast<__int64>(static_cast<double>(m_Seconds) / ts);
            
return t;
        }


    
private:

        CHTime(__int64);

        __int64 m_Seconds;
    }
;
}


#endif

.cpp
#include "StdAfx.h"
#include 
"CHTime.h"

namespace XHJ
{
    CHTime CHTime::now()
    
{
        
struct _timeb tb;
        _ftime(
&tb);
        
return CHTime(static_cast<__int64>(tb.time) * (1000000+ 
            tb.millitm 
* 1000);
    }


    CHTime CHTime::seconds(__int64 t)
    
{
        
return CHTime(t * (1000000));
    }


    CHTime CHTime::milliSeconds(__int64 t)
    
{
        
return CHTime(t * (1000));
    }


    CHTime CHTime::microSeconds(__int64 t)
    
{
        
return CHTime(t);
    }



    __int64 CHTime::toSeconds() 
const
    
{
        
return m_Seconds / 1000000;
    }


    __int64 CHTime::toMilliSeconds() 
const
    
{
        
return m_Seconds / 1000;
    }


    __int64 CHTime::toMicroSeconds() 
const
    
{
        
return m_Seconds;
    }


    std::
string    CHTime::toString() const
    
{
        time_t time 
= static_cast<long>(m_Seconds / 1000000);

        
struct tm* t = localtime(&time);


        
//由于localtime得到的年份是1900年以后经过了多少年,所以需要+1900,同样
        
//月是从0-11因此,月份也需要+1
        char buf[60];
        sprintf(buf,
"%.4d年%.2d月%.2d日 %.2d:%.2d:%.2d"
            t
->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour, t->tm_min,t->tm_sec);

        std::ostringstream os;
        os 
<< buf << ".";
        os.fill(
'0');
        os.width(
3);
        os 
<< static_cast<long>(m_Seconds % 1000000 / 1000);
        
return os.str();
    }


    CHTime::CHTime(__int64 usec) :    m_Seconds(usec)
    
{
    }


    std::ostream
& operator<<(std::ostream& outconst CHTime& tm)
    
{
        
return out << tm.toMicroSeconds() / 1000000;
    }

}
sjdev
re: 基础库___日志输出
这么长,我都懒得看
你用两句话简明扼要说说算了
晓寒
to[sjdev]
不是有类图和序列图吗?@_@

套用你的话:这么长,我都懒得解释。
你随便看两眼算了。 呵呵
晓寒
to[浪迹天涯]
呵呵,我在类图中就表现出来不负责他们的生存周期了。因为他们可能有别的用处呢。

所以我也在头文件中说明了一下。 不过还是谢谢你的热情。
晓寒
re: 基础库___日志输出
再次向你表示感谢。但是我这里不用判断吧。因为CHLogStream类是为我的CHLogger类服务的,而在CHLogger类中穿入参数的时候,使用的是string的c_str().
我的测试是,
logger.Error(NULL);会编译通过。但是,在执行的时候更本不能进入Error函数。看调用堆栈是NULL向string转型的时候出错,所以我想责任应该在使用者,既然看到参数是string类型,就不应该再拿NULL来使用。

呵呵,一己之谈,不知道对否。

晓寒
re: 基础库___日志输出
hehe,我同意你的观点。但是CHLogger类是个基础库,而CHLogStream是为CHLogger服务,且只为CHLogger服务的。当时把CHLogger的输出方式作为一个类来实现,是听取了[jzhang]网友的意见,使用策略模式来写。所以,CHLogStream是logger的一种表达,如果其他人如果也想使用这个的话,那就。。。。了。

还有一点,我认为很多检查不是必须的,特别是基础库。例如c语言的strcpy,他就没有检查越界阿,是否是空串等,这需要使用者自己来保证的。

有一点我做的不好,就是文档很少,其实写这个库(暂且称之为库吧 -_-!),我还是很自私的:主要是为了我自己的使用方便 :P 所以没有文档,只有简单的注释。
写这些类的初衷是总结一下自己以前使用到的基础东西,并且锻炼一下自己的设计模式思路。

呵呵,谢谢你的建议和意见。让我有所收获。
fiestay
re: 基础库___日志输出
还有一点,我认为很多检查不是必须的,特别是基础库。例如c语言的strcpy,他就没有检查越界阿,是否是空串等,这需要使用者自己来保证的。 

作为基础库要做比较严格的判断的,你举的strcpy的例子恰好可以作为反例,strcpy判断不严格的后果就是导致缓冲区溢出的几率大大增多:)

发表评论
切换编辑模式