现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

C++第三方日志库Pantheios

2013-12-13 13:00 工业·编程 ⁄ 共 10686字 ⁄ 字号 暂无评论

  在项目实践中发现一个好的日志记录非常重要,你需要借助Logging才能跟踪软件中的错误。所以这里研究下第三方C++库Pantheios的使用。Pantheios的架构分为前端和后端,具体概念介绍参考资料,这里只给出实际如何使用的源码示例。

这里使用的环境:

[1]Windows XP SP3

[2]Visual Studio2008 + SP1

[3]pantheios-1.0.1-beta213

[4] stlsoft-1.9.111

[5]pantheios-libselw-1.9.6.52

配置Pantheios使用环境

第一步:从参考资料[1]下载pantheios-1.0.1-beta213.zip压缩包,并解压。

为pantheios配置系统环境变量,例如

PANTHEIOS_ROOT=E:\SDK\pantheios-1.0.1-beta213

其中“E:\SDK\pantheios-1.0.1-beta213”是解压后的位置

第二步:从参考资料[2]下载stlsoft-1.9.111-hdrs.zip压缩包,并解压。

为stlsoft配置系统环境变量,例如

STLSOFT=E:\SDK\stlsoft-1.9.111

里面只有些头文件,但是我们只需要头文件就足够了。

第三步:启动Visual Studio 2008 命令行,它的位置在[开始]->[ Microsoft Visual Studio 2008]->[ Visual Studio Tools]->[Visual Studio 2008 Command Prompt]

    在VS2008命令行中转到“E:\SDK\pantheios-1.0.1-beta213\build\vc9”路径,输入命令“NMAKE   BUILD”开始建立Pantheios库和样例,等待编译、链接完成。

第四步:在VS2008里配置头文件路径和库文件路径

我这里分别是“E:\SDK\pantheios-1.0.1-beta213\include”

“E:\SDK\stlsoft-1.9.111\include”

“E:\SDK\pantheios-1.0.1-beta213\lib”

Pantheios调用示例

        项目运行时,Explicitly方式,需要输入依赖库名称,这时你需要“Pantheios Library Selector Tool”在参考资料[4]中下载。参考资料[5]把链接库列表从应用程序中复制出来,张贴到你的项目依赖项(库)中,实际使用碰到了很多问题(例如复制到剪贴板按钮失灵,依赖库找不到、依赖库冲突)所以本文不采用这种方式

这里由简入繁,举了三个实例来说明Pantheios的使用,它们均是在VS2008的 Win32 Console Application向导中建立和测试通过的。

第一个例子,输出日志到文件中

只有一个源文件源码如下,编译顺利的话可以直接运行:

// testFile.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
 
//指定链接库.begin 
#include <pantheios/implicit_link/core.h> 
#include <pantheios/implicit_link/fe.simple.h> 
#include <pantheios/implicit_link/be.file.h> 
//指定链接库.end 
 
#define PANTHEIOS_NO_INCLUDE_OS_AND_3PTYLIB_STRING_ACCESS // Faster compilation 
 
/* Pantheios Header Files */ 
#include <pantheios/pantheios.hpp>            // Pantheios C++ main header 
#include <pantheios/backends/bec.file.h>      // be.file header 
 
/* Standard C/C++ Header Files */ 
#include <exception>                          // for std::exception 
#include <new>                                // for std::bad_alloc 
#include <string>                             // for std::string 
#include <stdlib.h>                           // for exit codes 
 
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("testFile"); 
#define PSTR(x)         PANTHEIOS_LITERAL_STRING(x) 
 
int _tmain(int argc, _TCHAR* argv[]) 

    try 
    { 
        //设置文件名 
        pantheios_be_file_setFilePath(PSTR("kagula-%D-%T.log"),  
            PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BEID_ALL); 
 
        //打印到文件 
        pantheios::log_NOTICE(PSTR("stmt 1")); 
        pantheios::log_NOTICE(PSTR("stmt 2")); 
        pantheios::log_NOTICE(PSTR("stmt 3")); 
        pantheios::log_DEBUG(PSTR("exiting main()")); 
 
        return EXIT_SUCCESS; 
    } 
    catch(std::bad_alloc&) 
    { 
        pantheios::log_ALERT(PSTR("out of memory")); 
    } 
    catch(std::exception& x) 
    { 
        pantheios::log_CRITICAL(PSTR("Exception: "), x); 
    } 
    catch(...) 
    { 
        //如果只是打印一条字符串形式的信息,建议用下面这种形式打印日志! 
        pantheios::logputs(pantheios::emergency, PSTR("Unexpected unknown error")); 
    } 
     
    return EXIT_FAILURE; 

第二个例子,输出日志到Windows控制台

有三个源文件组成,stdafx.h文件插入了“MY_PROCESS_ID”宏,定义当前进程名称。

implicit_link.cpp文件,用来指定链接库和日志输出等级,第三个文件T2.cpp是示例代码,列举了不同水平的信息输出,和如何格式化输出信息。

stdafx.h源码

#pragma once 
 
#include "targetver.h" 
 
#include <stdio.h> 
#include <tchar.h> 
 
// TODO: reference additional headers your program requires here 
#define MY_PROGRAM_ID "MyProgramID" 
implicit_link.cpp源码

#include "stdafx.h" 
 
#include <pantheios/implicit_link/core.h> 
 
//如果定义了USER_SPECIFIED_LEVEL宏定义,则使用用户自定义的输出等级 
//如果不定义“USER_SPECIFIED_LEVEL”宏,表示所有等级的信息都输出 
#define USER_SPECIFIED_LEVEL 
 
#ifndef USER_SPECIFIED_LEVEL 
  #include <pantheios/implicit_link/fe.simple.h> 
#endif 
 
//一旦加入下面这条include语句,程序的log输出就会转到Windows控制台 
//在本例中,这条语句是必须的。 
#include <pantheios/implicit_link/be.WindowsConsole.h> 
 
#ifdef USER_SPECIFIED_LEVEL 
PANTHEIOS_CALL(int) pantheios_fe_init(void*   reserved,void**  ptoken) 

    *ptoken = NULL; 
    return 0; 

 
PANTHEIOS_CALL(void) pantheios_fe_uninit(void* token) 
{} 
 
PANTHEIOS_CALL(PAN_CHAR_T const*)  pantheios_fe_getProcessIdentity  (void *  token)  

    return PANTHEIOS_LITERAL_STRING(MY_PROGRAM_ID); 

 
PANTHEIOS_CALL(int) pantheios_fe_isSeverityLogged(void* token 
                                                  , int   severity 
                                                  , int   backEndId) 

    //数值越小说明要输出的信息越重要,常用的越先级大小如下 
    //SEV_CRITICAL=2 < SEV_ERROR=3 < SEV_WARNING=4 < SEV_INFORMATIONAL=6 
    if(severity <= pantheios::SEV_INFORMATIONAL) 
        return 1;//允许输出 
    return 0;  

 
#endif 

T2.cpp源码
// T2.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
 
#include <pantheios/pantheios.hpp>            // Pantheios C++ main header 
#include <pantheios/inserters/processid.hpp>  // for pantheios::processId 
#include <pantheios/inserters/threadid.hpp>   // for pantheios::threadId 
#include <pantheios/inserters/integer.hpp>    //for pantheios::integer 
#include <pantheios/inserters/real.hpp>       //for pantheios::real 
#include <pantheios/inserters/blob.hpp>       // for pantheios::blob 
#include <pantheios/inserters/hex_ptr.hpp>    // for pantheios::hex_ptr 
 
#include <pantheios/backend.h> 
#include <pantheios/backends/bec.WindowsConsole.h> 
 
#define PSTR(x)         PANTHEIOS_LITERAL_STRING(x) 
 
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING(MY_PROGRAM_ID); 
 
int _tmain(int argc, _TCHAR* argv[]) 

    //输出当前进程ID 
    pantheios::log_NOTICE(PSTR("process id: ["), pantheios::processId, PSTR("]")); 
 
    //输出当前线程ID 
    pantheios::log_NOTICE(PSTR("thread id: ["), pantheios::threadId, PSTR("]")); 
 
    //演示:不同等级输出 
    //典型的输出格式为“MY_PROGRAM_ID.线程ID 时分秒毫秒 等级 日志信息” 
    //建议把MY_PROGRAM_ID替换为你的进程ID 
    pantheios::log_DEBUG(PSTR("debug")); 
    pantheios::log_INFORMATIONAL(PSTR("informational")); 
    pantheios::log_NOTICE(PSTR("notice")); 
    pantheios::log_WARNING(PSTR("warning")); 
    pantheios::log_ERROR(PSTR("error")); 
    pantheios::log_CRITICAL(PSTR("critical")); 
    pantheios::log_ALERT(PSTR("alert")); 
    pantheios::log_EMERGENCY(PSTR("emergency")); 
 
    //演示int、float格式化输出 
    int   i=123; 
    float f=4.567f;  
 
    pantheios::log_INFORMATIONAL("[[ i=", pantheios::integer(i),  
        " f=",pantheios::real(f),"]]"); 
 
    pantheios::pantheios_logprintf(pantheios::SEV_INFORMATIONAL,PSTR("int=%d, float=%.2g"),i,f); 
 
 
    //演示二进制格式化输出 
    pantheios::uint8_t  bytes[20]; 
    for(size_t i = 0; i < STLSOFT_NUM_ELEMENTS(bytes); ++i) 
    { 
      bytes[i] = static_cast<pantheios::uint8_t>(i); 
    } 
     
    //默认打印格式如右"bytes: [03020100070605040b0a09080f0e0d0c13121110]" 
    pantheios::log_NOTICE(PSTR("bytes: ["), pantheios::blob(bytes, sizeof(bytes)), PSTR("]")); 
 
    //四字节为一组当中以空格分隔,打印格式如右 "bytes: [03020100 07060504 0b0a0908 0f0e0d0c 13121110]" 
    pantheios::log_NOTICE(PSTR("bytes: ["), pantheios::blob(bytes, sizeof(bytes), 4, PSTR(" ")), PSTR("]")); 
 
    // 每字节以空格分隔,四个为一行,每行以换行符结尾和两个空格结尾 
    // 打印格式如下 
    // "bytes: [00 01 02 03 
    //   04 05 06 07 
    //   08 09 0a 0b 
    //   0c 0d 0e 0f 
    //   10 11 12 13]" 
    pantheios::log_NOTICE(PSTR("bytes: ["), pantheios::blob(bytes, sizeof(bytes), 1, PSTR(" "), 4, PSTR("\n  ")), PSTR("]")); 
 
 
    //演示打印十六进制指针 
    //打印格式如右"pv: [0x0012fed0]" 
    pantheios::log_NOTICE(PSTR("pv: ["), pantheios::hex_ptr(&i), PSTR("]")); 
 
    return EXIT_SUCCESS; 

第三个例子,输出日志到多种流中
主要有两个源文件组成

implicit_link.cpp
#include "stdafx.h" 
 
#include <pantheios/implicit_link/core.h> 
#include <pantheios/implicit_link/be.N.h> 
#include <pantheios/implicit_link/be.WindowsConsole.h> 
#include <pantheios/implicit_link/be.file.h> 
 
PANTHEIOS_CALL(int) pantheios_fe_init(void*   reserved,void**  ptoken) 

    *ptoken = NULL; 
    return 0; 

 
PANTHEIOS_CALL(void) pantheios_fe_uninit(void* token) 
{} 
 
PANTHEIOS_CALL(PAN_CHAR_T const*)  pantheios_fe_getProcessIdentity  (void *  token)  

    return PANTHEIOS_LITERAL_STRING("example"); 

 
PANTHEIOS_CALL(int) pantheios_fe_isSeverityLogged(void* token 
                                                  , int   severity 
                                                  , int   backEndId) 

    //数值越小说明要输出的信息越重要,常用的越先级大小如下 
    //SEV_CRITICAL=2 < SEV_ERROR=3 < SEV_WARNING=4 < SEV_INFORMATIONAL=6 < SEV_DEBUG=7 
    //backEndId=0的时候必须返回1,这样才会进一步调用这个函数,这时会传入详细的backEndId值(1或2)。 
    if( backEndId==0 ) 
        return 1; 
 
    //Windows控制台中只记录SEV_INFORMATIONAL以上级别的信息 
    if(severity <= pantheios::SEV_INFORMATIONAL && backEndId==1) 
        return 1;//允许输出 
 
    //文件流中只记录严重错误的信息 
    if(severity <= pantheios::SEV_ERROR && backEndId==2) 
        return 1;//允许输出 
 
    return 0;  

testPantheios.cpp
// testPantheios.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
 
#include <pantheios/util/test/compiler_warnings_suppression.first_include.h> 
 
#define PANTHEIOS_NO_INCLUDE_OS_AND_3PTYLIB_STRING_ACCESS // Faster compilation 
 
/* Pantheios Header Files */ 
#include <pantheios/pantheios.hpp>                  // Pantheios C++ main header 
#include <pantheios/backends/be.N.h>                // pan_be_N_t声明 
#include <pantheios/backends/bec.WindowsConsole.h>  // Include the API for bec.WindowsConsole 
#include <pantheios/backends/bec.file.h>            // be.file header 
 
/* Standard C/C++ Header Files */ 
#include <exception>                                // for std::exception 
#include <new>                                      // for std::bad_alloc 
#include <string>                                   // for std::string 
#include <stdlib.h>                                 // for exit codes 
 
/* Windows Header Files */ 
# include <windows.h>                               // for console colour constants 
 
#include <pantheios/util/test/compiler_warnings_suppression.last_include.h> 
 
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("example"); 
#define PSTR(x)         PANTHEIOS_LITERAL_STRING(x) 
 
/* /////////////////////////////////////////////////////////////////////////
* Logging management
*/ 
enum beid_target 

    beid_Console =   1, 
    beid_File =   2 
}; 
 
pan_be_N_t  PAN_BE_N_BACKEND_LIST[] = 

    PANTHEIOS_BE_N_STDFORM_ENTRY(beid_Console, pantheios_be_WindowsConsole, 0), 
    PANTHEIOS_BE_N_STDFORM_ENTRY(beid_File, pantheios_be_file, 0), 
    PANTHEIOS_BE_N_TERMINATOR_ENTRY 
}; 
 
int _tmain(int argc, _TCHAR* argv[]) 

    try 
    { 
        //设置文件输出流 
        //如果遇到同名文件,原文件的内容会被重写 
        pantheios_be_file_setFilePath(PSTR("kagula.log"),  
            PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BEID_ALL); 
 
        //同时输出到两个目标(文件流和Windows控制台)中 
        //我重载了pantheios_fe_isSeverityLogged这样两个目标流的输出等级可以分别控制 
        pantheios::log_DEBUG(PSTR("stmt log_DEBUG"));   //没有输出 
        pantheios::log_NOTICE(PSTR("stmt log_NOTICE")); //只输出到控制台 
        pantheios::log_ERROR( PTSTR(L"stmt 3"));        //输出到控制台和文件流中,log_ERROR不加L会乱码奇怪 
        pantheios::log_EMERGENCY(PTSTR(L"stmt 4"));     //输出到控制台和文件流中,log_EMERGENCY不加L会乱码奇怪 
 
        return EXIT_SUCCESS; 
    } 
    catch(std::bad_alloc&) 
    { 
        pantheios::log(pantheios::alert, PSTR("out of memory")); 
    } 
    catch(std::exception& x) 
    { 
        pantheios::log_CRITICAL(PSTR("Exception: "), x); 
    } 
    catch(...) 
    { 
        pantheios::logputs(pantheios::emergency, PSTR("Unexpected unknown error")); 
    } 
 
    return EXIT_FAILURE; 

给我留言

留言无头像?