ACE日志系统

引用于:http://blog.csdn.net/focusonace/article/details/3108873

    http://peirenlei.iteye.com/blog/305036

介绍了ACE中日志系统(Logging Facility)的基本使用

一、简介

ACE有自己的Logging Facility,与log4cplus相似,ACE日志系统具有线程安全、灵活、分级显示等特点,可以面向程序调试、运行、测试、和维护等全生命周期,可以选择将信息输出到屏幕、文件、系统日志(如Windows下的Event log)、甚至是远程服务器。除此之外,ACE日志系统支持回调函数以及运行时刻动态配置(Runtime Configuration ),本文主要参考了《ACE Programmer‘s Guide,The: Practical Design Patterns for Network and Systems Programming》。

二、ACE日志系统的基本使用

首先通过一个引例介绍如何调用ACE Log Macro:
#include < ace/Log_Msg.h >
int ACE_TMAIN (int, ACE_TCHAR *[]){  ACE_DEBUG ((LM_INFO, ACE_TEXT ("Hi ACE Logging Facility!\n")));  return 0;}
程序需要包含头文件:Log_Msg.h,该文件定义了各种有用的日志输出宏,宏ACE_TMAIN 是ACE定义的wide-character-enabled entry point ,ACE日志系统缺省输出到stderr,所以对于Console类型的应用程序,会直接输出到屏幕。运行该程序时屏幕上会显示: Hi ACE Logging Facility!
可以看出ACE日志系统的宏调用非常简单: ACE_XXX((severity, formatting-args));
其中,ACE_XXX表示日志输出宏(ACE Logging Macros),包括:ACE_ERROR((level, string, ...))ACE_DEBUG((level, string, ...))ACE_TRACE(string)ACE_ASSERT(test)ACE_HEX_DUMP((level, buffer, size [,text]))ACE_RETURN(value)ACE_ERROR_RETURN((level, string, ...), value)ACE_ERROR_INIT( value, flags )ACE_ERROR_BREAK((level, string, ...))
severity即输出的严重等级(Severity Level),包括: LM_SHUTDOWN = 01,系统死机级别  LM_TRACE = 02,跟踪级别  LM_DEBUG = 04,DEBUG级别  LM_INFO = 010,常规信息级别  LM_NOTICE = 020,注意级别  LM_WARNING = 040,警告级别  LM_STARTUP = 0100,启动级别  LM_ERROR = 0200,错误级别  LM_CRITICAL = 0400,危急级别  LM_ALERT = 01000,可修复的警告级别  LM_EMERGENCY = 02000,全局警告级别 
formatting-args是要输出的内容,格式类似于printf函数的输出格式:
Code        Argument Type   Displays
A           ACE_timer_t     浮点数a           —              导致程序终止(Abort)c           char            单个字符C           char*           字符串(narrow characters)i,d         int             10进制整数I           —              缩进e,E,f,F,g,G double          双精度浮点数l           —              行号M           —              severity level的名称m           —              错误号(errorno)N           —              文件名n           —              ACE_Log_Msg::open()指定的程序名o           int             八进制整数P           —              当前进程IDp           ACE_TCHAR*      字符串,后接错误号,同perrorQ           ACE_UINT64      64位无符号十进制整数r           void (*)()      函数调用R           int             十进制整数S           int             数字对应的信号名称s           ACE_TCHAR*      ACE_TCHAR类型的字符串T           —              当前时间(hour:minute:sec.usec)D           —              时戳(month/day/year/hour:minute:sec.usec)t           —              当前线程IDu           int             无符号十进制整数w           wchar_t         Single wide characterW           wchar_t*        Wide-character stringx,X         int             十六进制数@           void*           指针(十六进制)%           N/A             %
我们可以通过一些例子来进一步了解如何使用这些宏、Severity Level和格式,在开始之前,首先澄清一个概念:一些日志系统(如log4cplus)是靠宏名来区分日志信息类型的,比如:    LOG4CPLUS_DEBUG(Logger::getRoot(),"some text")   /* DEDUG 类型 */    LOG4CPLUS_ERROR(Logger::getRoot(),"some text")   /* ERROR 类型 */    ACE的日志系统不是靠宏名本身,而是靠宏的第一个参数,即Severity Level来区分日志信息类型:
    ACE_DEBUG((LM_DEBUG, ACE_TEXT ("some text\n"))); /* DEDUG 类型 */    ACE_ERROR((LM_DEBUG, ACE_TEXT ("some text\n"))); /* DEDUG 类型 */    ACE_DEBUG((LM_ERROR, ACE_TEXT ("some text\n"))); /* ERROR 类型 */    ACE_ERROR((LM_ERROR, ACE_TEXT ("some text\n"))); /* ERROR 类型 */
从这个角度考虑,宏ACE_DEBUG和ACE_ERROR没有什么区别,几乎可以混用,这两个宏的区别主要体现在两方面:
a) 语义上的差别b) 语句执行完后,op_status不同,比如:
    ACE_Log_Msg *lm = ACE_LOG_MSG;    ACE_DEBUG ((LM_ERROR, ACE_TEXT ("some text\n")));    ACE_ASSERT( 0 == lm->op_status() );  /* ACE_DEBUG执行完后,op_status 是0 */    ACE_ERROR ((LM_ERROR, ACE_TEXT ("some text\n")));    ACE_ASSERT( -1 == lm->op_status() ); /* ACE_ERROR执行完后,op_status 是-1 */    下面举一些典型用例:
【use-case1】 如何在编译时刻Enabling 或Disabling Logging Macros
在#include < ace/Log_Msg.h >之前定义一些宏,可以在编译时刻Enable/Disable logging Macros
/* disable ACE_DEBUG and ACE_ERROR */#define ACE_NLOGGING
/* enable ACE_DEBUG and ACE_ERROR(缺省) */#undef ACE_NLOGGING
/* enable ACE_ASSERT(缺省) */#undef ACE_NDEBUG
/* disable ACE_ASSERT */#define ACE_NDEBUG
/* enable ACE_TRACE */#define ACE_NTRACE 0
/* disable ACE_TRACE(缺省) */#define ACE_NTRACE 1
【use-case2】格式使用
a) 打印完结果后终止(Abort)
    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("begin %a end \n")));
输出以下信息后提示Abort信息:begin Aborting... end
b) 缩进
int ACE_TMAIN (int, ACE_TCHAR *[]){    ACE_TRACE("main");    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%Itext\n")));    return 0;}
输出:(700) calling main in file `D:\aceprj\testlog\main.cpp‘ on line 24    text(700) leaving main
(其中,700是ACE_TRACE控制输出的当前线程ID)
c) HEX Dump(调试时候比较有用)    char szBuf[128] = "hello world!";    ACE_HEX_DUMP((LM_DEBUG, szBuf, 128,"szBuf: "));
输出:
szBuf:  - HEXDUMP 128 bytes68 65 6c 6c 6f 20 77 6f  72 6c 64 21 00 00 00 00   hello world!....00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
d)函数调用
void foo(void){    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("in func foo\n")));}
int ACE_TMAIN (int, ACE_TCHAR *[]){    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("call function %r\n"),foo));    return 0;}
输出:in func foocall function
e) 进制转换    ACE_UINT64 uint64A = 210113198510308319;    int hexA = 0xBEEE3F;    int octA = 9;    ACE_timer_t tmInterval = 0.000001;        ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("UINT64: %Q\n"),uint64A));    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("HEX: %X, hex: %x\n"),hexA,hexA));    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Ptr in hex:%@\n"),&hexA));    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Octal number of 9:%o\n"),octA));    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("timer‘s Interval: %A\n"),tmInterval));
输出:UINT64: 210113198510308319HEX: BEEE3F, hex: beee3fPtr in hex:0012FE30Octal number of 9:11timer‘s Interval: 0.000001
f)综合使用    ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%D, %M, [%t], Line:%l\n")));    ACE_DEBUG ((LM_ERROR, ACE_TEXT ("%D, %M, [%t], Line:%l\n")));    输出:    Mon Mar 20 2005 20:02:16.912000, LM_DEBUG, [3296], Line:24    Mon Mar 20 2006 20:02:16.912000, LM_ERROR, [3296], Line:25        【use-case3】宏使用
a) ACE_RETURN
int foo(void){    ACE_RETURN(3);}
int ACE_TMAIN (int, ACE_TCHAR *[]){    foo();    ACE_ASSERT( 3 == ACE_LOG_MSG->op_status() );    return 0;}
输出:(无任何输出)
b) ACE_ERROR_RETURN
int foo(void){    ACE_ERROR_RETURN((LM_DEBUG,"Return error\n"), 3);}
int ACE_TMAIN (int, ACE_TCHAR *[]){    foo();    ACE_ASSERT( 3 == ACE_LOG_MSG->op_status() );    return 0;}
输出:Return error
c) ACE_ERROR_BREAK
    int i = 0;
    while(1)    {        if( i > 10 )        {            ACE_ERROR_BREAK((LM_DEBUG,"break from while\n"));        }
        i++;    }
    ACE_DEBUG((LM_DEBUG, "i = %d\n", i));
输出:break from whilei = 11
【use-case4】 如何在运行时刻Enabling 或Disabling Logging Severities
由于缺省情况下在进程范围内所有logging severities都会被输出,因此需要通过priority_mask、ACE_Log_Msg::enable_debug_messages、ACE_Log_Msg::disable_debug_messages来过滤输出。
其中priority_mask的用法如下:
    /* Get the current ACE_Log_Priority mask. */    u_long priority_mask (MASK_TYPE = THREAD);
    /* Set the ACE_Log_Priority mask, returns original mask. */    u_long priority_mask (u_long, MASK_TYPE = THREAD);
这里MASK_TYPE可选择:ACE_Log_Msg::PROCESS(作用范围是进程)或ACE_Log_Msg::THREAD(作用范围是线程)
enable_debug_messages/disable_debug_messages的用法如下:
    static void disable_debug_messages    (ACE_Log_Priority priority = LM_DEBUG);
    static void enable_debug_messages    (ACE_Log_Priority priority = LM_DEBUG);
这里输入参数可选择任意需要打开或屏蔽的logging severity,不像函数名称暗示的那样只能控制LM_DEBUG类型,另外由于是静态函数,enable_debug_messages/disable_debug_messages的设置对整个进程有效。
注意一下priority_mask与enable_debug_messages/disable_debug_messages的区别:priority_mask将进程(或线程)的logging severitys用其第一个参数所代替,清除之前的设置。enable_debug_messages将进程的logging severitys用其参数去累加,不清除之前的设置。disable_debug_messages将进程的logging severitys用其参数去屏蔽,不清除之前的设置。
a) 整个进程仅允许输出LM_ERROR和LM_WARNING    ACE_DEBUG((LM_DEBUG, "Debug Text1\n"));    ACE_DEBUG((LM_ERROR, "Error Text1\n"));        ACE_LOG_MSG->priority_mask (LM_ERROR | LM_WARNING, ACE_Log_Msg::PROCESS);        ACE_DEBUG((LM_DEBUG, "Debug Text2\n"));    ACE_DEBUG((LM_ERROR, "Error Text2\n"));    或者:    ACE_DEBUG((LM_DEBUG, "Debug Text1\n"));    ACE_DEBUG((LM_ERROR, "Error Text1\n"));
    /* 禁用了进程所有的logging severitys */    ACE_LOG_MSG->priority_mask (0, ACE_Log_Msg::PROCESS);    ACE_Log_Msg::enable_debug_messages (LM_ERROR);    ACE_Log_Msg::enable_debug_messages (LM_WARNING);
    ACE_DEBUG((LM_DEBUG, "Debug Text2\n"));    ACE_DEBUG((LM_ERROR, "Error Text2\n"));        输出:Debug Text1Error Text1Error Text2
b) 每个线程控制各自的logging severity
#include < ace/Task.h >    /* for ACE_Thread_Manager */#include < ace/Log_Msg.h >
void service(void){ ACE_LOG_MSG->priority_mask (LM_INFO, ACE_Log_Msg::THREAD); ACE_DEBUG((LM_DEBUG, "in service, MsgType:%M,  ThreadID: %t\n")); ACE_DEBUG((LM_INFO,  "in service, MsgType:%M,  ThreadID: %t\n"));}
void worker(void){
 ACE_LOG_MSG->priority_mask (LM_DEBUG, ACE_Log_Msg::THREAD); ACE_DEBUG((LM_DEBUG, "in worker,  MsgType:%M, ThreadID: %t\n")); ACE_DEBUG((LM_INFO,  "in worker,  MsgType:%M, ThreadID: %t\n"));}
int ACE_TMAIN (int, ACE_TCHAR *[]){  ACE_LOG_MSG->priority_mask (0, ACE_Log_Msg::PROCESS);
 ACE_Thread_Manager::instance ()->spawn ((ACE_THR_FUNC)service); ACE_Thread_Manager::instance ()->spawn_n (3, (ACE_THR_FUNC)worker); ACE_Thread_Manager::instance ()->wait();
 return 0;}
输出:in service, MsgType:LM_INFO,  ThreadID: 3428in worker,  MsgType:LM_DEBUG, ThreadID: 2064in worker,  MsgType:LM_DEBUG, ThreadID: 1240in worker,  MsgType:LM_DEBUG, ThreadID: 1800

ACE通过全局单体实例 ACE_LOG_MSG 管理和控制输出,我们可以利用这个实例把输出重定向

到文件,也可以重定向到标志输出 
其中还可以控制什么级别的消息可被输出,简单使用如下:

ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR); 
  设置输出到标准错误输出 
  ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR); 
  关闭输出到标志错误输出 
  ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM); 
  ofstream myostream (filename, ios::out | ios::trunc); 
  ACE_LOG_MSG->msg_ostream (&myostream); 
  设置输出到文件 
  u_long priority_mask =ACE_LOG_MSG->priority_mask (ACE_Log_Msg::PROCESS); 
  ACE_SET_BITS (priority_mask,LM_DEBUG |LM_INFO); 
  设置只记录LM_DEBUG 或者LM_INFO级别的消息 
  ACE_CLR_BITS (priority_mask,LM_DEBUG | LM_INFO);                    
  清除设置条件 
ACE_LOG_MSG还有一个非常有意思的功能,能以16进制方式输出内存中的块 ,简单使用如下: 
      ACE_LOG_MSG->log_hexdump (LM_DEBUG, 
                                (char *) array, 
                                sizeof array);

下面附上一个使用例子,例子来源于ACE包中的例子程序 
#include "ace/OS_main.h" 
#include "ace/streams.h" 
#include "ace/Log_Msg.h" 
int 
ACE_TMAIN (int, ACE_TCHAR *[]) 

  // 这个消息将输出到STDERR 
  ACE_DEBUG ((LM_DEBUG, 
              "first message/n")); 
  ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR); 
  // 这个消息将不被输出,因为标志位清除了 
  ACE_DEBUG ((LM_DEBUG, 
              "second message/n")); 
  ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM); 
  //这个消息将不被输出,因为流的实体尚未定义 
  ACE_DEBUG ((LM_DEBUG, 
              "third message/n")); 
  //建立一个流实体,指向d:/output.log文件 
  const char *filename = "d://output.log"; 
  ofstream myostream (filename, ios::out | ios::trunc); 
  if (myostream.bad ()) 
    return 1; 
  // 设置输出到流 
  ACE_LOG_MSG->msg_ostream (&myostream); 
  //这个消息将输出到文件中 
  ACE_DEBUG ((LM_DEBUG, 
              "fourth message/n")); 
  ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR); 
  // 这个消息将同时输出到文件和STDERR 
  ACE_DEBUG ((LM_DEBUG, 
              "fifth message/n")); 
  return 0; 
}

时间: 2024-08-06 09:33:36

ACE日志系统的相关文章

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

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

【Yii系列】错误处理和日志系统

缘起 跟随上一章的脚步,上一章中,我们主要讲解了在用户发起请求,解析请求,服务器反馈请求以及session的一些知识点,这过程中,难免会遇到一些问题,比方说数据库查询失败,用户输入导致脚本出错,网络问题等等突发情况,对于突发情况,做过软件的一般都知道,会有错误处理和日志去记录下这个过程,同样的,Yii也提供了类似的功能帮助我们去抓住错误,记录错误,并且对相应错误做出对应处理. 错误处理 Yii 内置了一个error handler错误处理器. 所有非致命PHP错误(如,警告,提示)会转换成可获取

DNS的视图功能以及日志系统

实验环境:RHEL5.8 32Bit DNS的视图功能以及日志系统详解 DNS的主配置文件中的allow-recursion参数用来定义能够和DNS服务器进行递归的客户端来源,allow-query参数用来定义允许到DNS服务器上面发起查询请求的客户端,allow-transfer参数用来定义允许和DNS服务器进行区域传送的客户端,区域传送主要有两种方式,axfr和ixfr,使用dig命令也可以模拟实现区域传送: 如果我们的DNS服务器允许进行递归.发起查询请求以及进行区域传送的客户端比较多的话

Linux上的日志系统

Syslog Syslog-ng 日志系统:syslogd() A: B: D: syslog服务: syslogd:系统,非内核产生的信息 klogd:内核,专门负责记录内科产生的日志 kernel –物理终端(dev/console)--/var/log/dmesg 日志需求滚动(日志切割): messages message.1  message.2 /sbin/init /var/log/messages,系统保准错误日志,非内核产生引导信息:各子系统产生的信息: /var/log/ma

日志系统之基于flume收集docker容器日志

最近我在日志收集的功能中加入了对docker容器日志的支持.这篇文章简单谈谈策略选择和处理方式. 关于docker的容器日志 docker 我就不多说了,这两年火得发烫.最近我也正在把日志系统的一些组件往docker里部署.很显然,组件跑在容器里之后很多东西都会受到容器的制约,比如日志文件就是其中之一. 当一个组件部署到docker中时,你可以通过如下命令在标准输出流(命令行)中查看这个组件的日志: docker logs ${containerName} 日志形如: 但这种方式并不能让你实时获

日志系统之扩展Flume-LineDeserializer

本人博客文章如未特别注明皆为原创!如有转载请注明出处:http://blog.csdn.net/yanghua_kobe/article/details/46595401 继续闲聊日志系统,在之前的博文里已提到我们在日志收集上的选择是flume-ng.应用程序将日志打到各自的日志文件或指定的文件夹(日志文件按天滚动),然后利用flume的agent去日志文件中收集. Deserializer简介 flume将一条日志抽象成一个event.这里我们从日志文件中收集日志采用的是定制版的SpoolDi

atitit. 日志系统的原则and设计and最佳实践(1)-----原理理论总结.

atitit. 日志系统的原则and设计and最佳实践总结. 1. 日志系统是一种不可或缺的单元测试,跟踪调试工具 1 2. 日志系统框架通常应当包括如下基本特性 1 1. 所输出的日志拥有自己的分类. 2 2. 日志按照某种标准分成不同级别. 2 3. 支持多线程. 2 4. 稳定性. 2 3. 一个理想的日志模式 2 4. 判断指定的方法是否被调用了 3 5. 给方法的输入输出加上日志通过Aop 3 6. 日志易读,易解析  对日志感兴趣的可以分为两类: 3 7. 输出日志使用的性能 3 8

MySQL日志系统

body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10px; padding-bottom: 10px; background-color: white; padding: 30px } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom:

使用Slf4j集成Log4j2构建项目日志系统的完美解决方案

一.背景 最近因为公司项目性能需要,我们考虑把以前基于的log4j的日志系统重构成基于Slf4j和log4j2的日志系统,因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见几种日志系统,而使用log4j2而不是log4j是因为Log4j 1.x 在高并发情况下出现死锁导致cpu使用率异常飙升,而Log4j2.0基于LMAX Disruptor的异步日志在多线程环境下性能会远远优于Log4j 1.x和logback(官方数据是10倍以上). 关于slf4j的原理以及优点