开源日志系统log4cplus(七)

经过短暂的熟悉过程,log4cplus已经被成功应用到了我的项目中去了,效果还不错,:)除了上文提及的
功能之外,下面将介绍log4cplus提供的线程和套接字的使用情况。

### NDC ###
首先我们先了解一下log4cplus中嵌入诊断上下文(Nested Diagnostic Context),即NDC。对log系统而言,
当输入源可能不止一个,而只有一个输出时,往往需要分辩所要输出消息的来源,比如服务器处理来自不同
客户端的消息时就需要作此判断,NDC可以为交错显示的信息打上一个标记(stamp), 使得辨认工作看起来
比较容易些,呵呵。这个标记是线程特有的,利用了线程局部存储机制,称为线程私有数据(Thread-specific
 Data,或TSD)。 看了一下源代码,相关定义如下,包括定义、初始化、获取、设置和清除操作:
linux pthread

#   define LOG4CPLUS_THREAD_LOCAL_TYPE pthread_key_t*
#   define LOG4CPLUS_THREAD_LOCAL_INIT ::log4cplus::thread::createPthreadKey()
#   define LOG4CPLUS_GET_THREAD_LOCAL_VALUE( key ) pthread_getspecific(*key)
#   define LOG4CPLUS_SET_THREAD_LOCAL_VALUE( key, value ) pthread_setspecific(*key, value)
#   define LOG4CPLUS_THREAD_LOCAL_CLEANUP( key ) pthread_key_delete(*key)

win32

#   define LOG4CPLUS_THREAD_LOCAL_TYPE DWORD
#   define LOG4CPLUS_THREAD_LOCAL_INIT TlsAlloc()
#   define LOG4CPLUS_GET_THREAD_LOCAL_VALUE( key ) TlsGetValue(key)
#   define LOG4CPLUS_SET_THREAD_LOCAL_VALUE( key, value ) \       TlsSetValue(key, static_cast(value))
#   define LOG4CPLUS_THREAD_LOCAL_CLEANUP( key ) TlsFree(key)

使用起来比较简单,在某个线程中:

    NDC& ndc = log4cplus::getNDC();
    ndc.push("ur ndc string");
    LOG4CPLUS_DEBUG(logger, "this is a NDC test");
     
    ndc.pop();
        
    LOG4CPLUS_DEBUG(logger, "There should be no NDC");
    ndc.remove();

   
当设定输出格式(Layout)为TTCCLayout时,输出如下:

10-21-04 21:32:58, [3392] DEBUG test  - this is a NDC test
10-21-04 21:32:58, [3392] DEBUG test <> - There should be no NDC...
也可以在自定义的输出格式中使用NDC(用%x) ,比如:

     
  std::string pattern = "NDC:[%x]  - %m %n";
  std::auto_ptr _layout(new PatternLayout(pattern));
     
 LOG4CPLUS_DEBUG(_logger, "This is the FIRST log message")
  NDC& ndc = log4cplus::getNDC();
  ndc.push("ur ndc string"); 
  LOG4CPLUS_WARN(_logger, "This is the SECOND log message")
  ndc.pop();
 ndc.remove(); 
    

   
输出如下:

NDC:[]  - This is the FIRST log message...
NDC:[ur ndc string]  - This is the SECOND log message...
另外一种更简单的使用方法是在线程中直接用NDCContextCreator:

    NDCContextCreator _first_ndc("ur ndc string");
    LOG4CPLUS_DEBUG(logger, "this is a NDC test")

   
不必显式地调用push/pop了,而且当出现异常时,能够确保push与pop的调用是匹配的。

    
### 线程 ###
线程是log4cplus中的副产品, 而且仅作了最基本的实现,使用起来也异常简单,只要且必须要
在派生类中重载run函数即可:

class TestThread : public AbstractThread
{
public:
    virtual void run();
};
                
void TestThread::run()

   /* do sth. */ 
    
}

log4cplus的线程没有考虑同步、死锁,有互斥,实现线程切换的小函数挺别致的:

void log4cplus::thread::yield()
{
#if defined(LOG4CPLUS_USE_PTHREADS)
    ::sched_yield();
#elif defined(LOG4CPLUS_USE_WIN32_THREADS)
    ::Sleep(0);
#endif
}

### 套接字 ###
套接字也是log4cplus中的副产品,在namespace log4cplus::helpers中,实现了C/S方式的日志记录。
1. 客户端程序需要做的工作:

/* 定义一个SocketAppender类型的挂接器 */SharedAppenderPtr _append(new SocketAppender(host, 8888, "ServerName"));
/* 把_append加入到logger中 */Logger::getRoot().addAppender(_append);
/*  SocketAppender类型不需要Layout, 直接调用宏就可以将信息发往loggerServer了 */LOG4CPLUS_INFO(Logger::getRoot(), "This is a test: ")

【注】 这里对宏的调用其实是调用了SocketAppender::append,里面有一个数据传输约定,即先发送
一个后续数据的总长度,然后再发送实际的数据:


     
    SocketBuffer buffer = convertToBuffer(event, serverName);
    SocketBuffer msgBuffer(LOG4CPLUS_MAX_MESSAGE_SIZE);
    msgBuffer.appendSize_t(buffer.getSize());
    msgBuffer.appendBuffer(buffer);        

2. 服务器端程序需要做的工作:

/* 定义一个ServerSocket */ServerSocket serverSocket(port);
 
/* 调用accept函数创建一个新的socket与客户端连接 */Socket sock = serverSocket.accept();

此后即可用该sock进行数据read/write了,形如:

SocketBuffer msgSizeBuffer(sizeof(unsigned int));
if(!clientsock.read(msgSizeBuffer))
{
    return;
}
unsigned int msgSize = msgSizeBuffer.readInt();
SocketBuffer buffer(msgSize);
if(!clientsock.read(buffer))
{
    return;
}

为了将读到的数据正常显示出来,需要将SocketBuffer存放的内容转换成InternalLoggingEvent格式:

spi::InternalLoggingEvent event = readFromBuffer(buffer);

然后输出:

Logger logger = Logger::getInstance(event.getLoggerName());
logger.callAppenders(event);

【注】 read/write是按照阻塞方式实现的,意味着对其调用直到满足了所接收或发送的个数才返回。
时间: 2024-07-28 14:07:10

开源日志系统log4cplus(七)的相关文章

开源日志系统log4cplus(一)

log4cplus是C++编写的开源的日志系统,功能非常全面,用到自己开发的工程中会比较专业的,:),本文介绍了log4cplus基本概念,以及如何安装,配置.  ### 简介 ### log4cplus是C++编写的开源的日志系统,前身是java编写的log4j系统.受Apache Software License 保护.作者是Tad E. Smith.log4cplus具有线程安全.灵活.以及多粒度控制的特点,通过将信息划分 优先级使其可以面向程序调试.运行.测试.和维护等全生命周期: 你可

开源日志系统log4cplus(四)

将log信息记录到文件应该说是日志系统的一个基本功能,log4cplus在此基础上,提供了更多的功能,可以按照你预先设定的大小来决定是否转储,当超过该大小,后续log信息会另存到新文件中,依次类推:或者按照日期来决定是否转储.本文将详细介绍这些用法. ### 如何将log记录到文件 ### 我们在例5中给出了一个将log记录到文件的例子,用的是FileAppender类实现的,log4cplus提供了三个类用于 文件操作,它们是FileAppender类.RollingFileAppender类

开源日志系统log4cplus(五)

日志系统的另一个基本功能就是能够让使用者按照自己的意愿来控制什么时候,哪些log信息可以输出. 如果能够让用户在任意时刻设置允许输出的LogLevel的信息就好了,log4cplus通过LogLevelManager. LogLog.Filter三种方式实现了上述功能. ### 优先级控制 ### 在研究LogLevelManager之前,首先介绍一下log4cplus中logger的存储机制,在log4cplus中,所有 logger都通过一个层次化的结构(其实内部是hash表)来组织的,有一

开源日志系统log4cplus(三)

本文介绍了三种控制输出格式的布局管理器的概念和使用情况,通过掌握这些知识,可以更有效地控制log系统输出尽可能贴近你需求的信息来. ### 如何控制输出消息的格式 ### 前面已经讲过,log4cplus通过布局器(Layouts)来控制输出的格式,log4cplus提供了三种类型的Layouts, 分别是SimpleLayout.PatternLayout.和TTCCLayout.其中: 1. SimpleLayout 是一种简单格式的布局器,在输出的原始信息之前加上LogLevel和一个"-

开源日志系统log4cplus(二)

本文介绍了使用log4cplus有六个步骤,并提供了一些例子引导你了解log4cplus的基本使用. ### 基本使用 ### 使用log4cplus有六个基本步骤: 1. 实例化一个appender对象 2. 实例化一个layout对象 3. 将layout对象绑定(attach)到appender对象 4. 实例化一个logger对象,调用静态函数:log4cplus::Logger::getInstance("logger_name") 5. 将appender对象绑定(atta

Logback 1.0.1发布 开源日志系统

Logback 是一个作为log4j项目的继任者,是由Log4j的创始人Ceki Gulcu设计成一款开源日志系统. Logback 配备基本架构以通用于不同情况下的需求,它分为三个模块:Core module.Classic module 和 Access module.Core module核心模块是为其他两个模块设计的一个基础模块.Classic module类似于log4j的改进版本,实现了SLF4J API使你可以很容易地在logback和其它日志系统(log4j 或 JDK14 )之

开源日志系统比较

原文地址:http://www.cnblogs.com/ibook360/p/3159544.html 1. 背景介绍   许多公司的平台每天会产生大量的日志(一般为流式数据,如,搜索引擎的pv,查询等),处理这些日志需要特定的日志系统,一般而言,这些系统需要具有以下特征: (1) 构建应用系统和分析系统的桥梁,并将它们之间的关联解耦: (2) 支持近实时的在线分析系统和类似于Hadoop之类的离线分析系统: (3) 具有高可扩展性.即:当数据量增加时,可以通过增加节点进行水平扩展. 本文从设计

通用的应用程序高级日志系统

日志模块 本文介绍的日志系统包括七个 C++ 类:CLog, CFuncLog, IStoreLog, CWinLog, CFileLog, CAutoCritic, CLogSimpleLock.CLog 是所有日志模块中最主要的一个类,在大多数情况下,这个类在应用程序中最好是单实例的.但并不是必须的.重要性其次的一个类是 CFuncLog,这个类用于对函数调用的进入和退出进行记录.当然开发人员也可以使用这个类对任何数据进行日志记录.该类重载了 << 操作符,所以使用很方便. 下图是本文介绍

日志系统之Flume采集加morphline解析

概述 这段时间花了部分时间在处理消息总线跟日志的对接上.这里分享一下在日志采集和日志解析中遇到的一些问题和处理方案. 日志采集-flume logstash VS flume 首先谈谈我们在日志采集器上的选型.由于我们选择采用ElasticSearch作为日志的存储与搜索引擎.而基于ELK(ElasticSearch,Logstash,Kibana)的技术栈在日志系统方向又是如此流行,所以把Logstash列入考察对象也是顺理成章,Logstash在几大主流的日志收集器里算是后起之秀,被Elas