• 使用Line Pos Info 和 Modern C++ 改进打印日志记录


    使用Line Pos Info 和 Modern C++ 改进打印日志记录

    使用跟踪值:不管自己是多么的精通,可能仍然使用调试的主要方法之一 printf , TRaCE, outputDebugString, 等…然后扫描输出, 同时调试。

    添加有关行号和日志消息来源的文件的信息是一种非常有效的方法,可以为你节省大量时间,在这篇文章将描述一个在visual Studio中特别有用的技巧,在其他IDE/编译器中有所帮助。

    还将展示现在C++和C++20如何使代码更好。

    常规

    在调试C++代码时,将值输出到控制台或输出到窗口并扫描日志非常方便。

     std::cout << "myval: " << val << endl; 

    可以通过添加LINE和FILE信息轻松增强此技术,这样就可以看到那条消息的来源。扫描大量日志时,这可能非常方便。

    为什么会这么重要呢?就每个人来说,当我们试图查找某些日志输出的来源时,我们已经失去了很多时间。当我们看到一条消息时,我们会复制他,搜索解决方案,然后通常在滚动后终于找到了正确的代码行。那么有没有更为简便的方法呢?

    将使用“标准”C++实现此代码,然后转到现代C++,最后看看C++20将会发生什么?

    log4cpp 中添加需要打印的行号,文件名,函数名 (标准C++)

    使用log4cpp中的Category的debug, error, info , warn 等方法输出,需要调试的信息:

    root.debug(“Message”);

    但最后用宏包装上面的函数:

    #define logWarn(msg) my_logWarn(__LINE__,__FILE__,__FUNCTION__,msg)

    通过logWarn(msg)使用;

    上面代码调用logWarn(msg)内部调用的函数my_llogWarn。

    为什么定义一个宏?当然,方便。否则,必须手动传递行号和文件名。无法在内部获取文件和行,my_logWarn 因为它始终指向实现的源代码my_logWarn而不是调用它的代码。

    什么是 __ FILE __ 和 __ LINE __ ? 在vistual Studio 中,这下可以在代码中使用的预定义宏。顾名思义,他们会扩展到源代码的文件名和给定翻译单元中的确定行。要控制 __ FILE __ 宏, 可以使用编译器选项 /FC 。该选项使文件名更长(完整路径)或更短(相对于解决方案目录),请注意,/FC使用“编译并继续“时暗示。

    注意, __ FILE __ 并且 __ LINE __ 也由标准制定,因此其他编译器也应该实现它。

     void my_logWarn(int line,const char *filename,const char *funcName, const char *msg)
     {
          Mylog *log = Mylog::getInstance();
          
          string tempMsg = msg;
          tempMsg = tempMsg + " doucument name:" + std::string(filename) + " this is line: " + std::to_string(line) + " func name: " + string(funcName);
          
          log->Warn(tempMsg.c_str());
     }

    C++ 20

    在C++20中有std::source_location

    新的库类型声明如下:

     struct source_location{
         static constexpr source_location current () noexcept;
         constexpr uint_lest32_t line() const noexcept;
         constexpr uint_lest32_t column() const noexcept;
         constexpr const char * filename() const noexcept;
         constexpr const char *function_name() const noexcept;
     }

    一个基本的使用例子:

     #include <iostream>
     #include <string_view>
     #include <experimental/source_location>
     ​
     using namespace std;
     using namespace std::experimental; 
     ​
     void log(const string_view& message, 
           const source_location& location = source_location::current())
     {
         std::cout << "info:"
                   << location.file_name() << ":"
                   << location.line() << " "
                   << location.function_name() << " "
                   << message << '
    ';         
     }
     ​
     int main()
     {
         log("Hello world!");
     ​
         // another log
         log("super extra!");
     }
    

      

    总结

    简单介绍了增强的printf样式和日志记录

    起初,使用的主要是C风格的标准代码,后来使用了现代C++进行更新,最后了使用了C++20中的source_location引入的新类型实现。

    随着soure_location使我们可以跳过使用__ FILE __ 和 __ LINE __ 预定义宏,不过,日志宏(#define Log(…)) 是有帮助的,因为他可以隐藏于位置信息缺省参数。

    base C++:

    #pragma once
    
    #define logInfo(msg)
        my_logInfo(__LINE__,__FILE__,__FUNCTION__,msg)
    #define logWarn(msg)
        my_logWarn(__LINE__,__FILE__,__FUNCTION__,msg)
    #define logError(msg)
        my_logError(__LINE__,__FILE__,__FUNCTION__,msg)
    #define logDebug(msg)
        my_logDebug(__LINE__,__FILE__,__FUNCTION__,msg)
    #include <stdlib.h>
    #include <iostream>
    #include <string>
    using std::cout;
    using std::endl;
    using std::string;
    
    #include <log4cpp/Category.hh>
    #include <log4cpp/Priority.hh>
    #include <log4cpp/FileAppender.hh>
    #include <log4cpp/RollingFileAppender.hh>
    #include <log4cpp/OstreamAppender.hh>
    #include <log4cpp/PatternLayout.hh>
    
    using namespace log4cpp;
    class Mylog
    {
    public:
        void Warn(const char *msg);
        void Error(const char *msg);
        void Debug(const char * msg);
        void Info(const char * msg);
        
        static Mylog * getInstance()
        {
            if(_pInstance == nullptr){
                _pInstance = new Mylog();
            }
            return _pInstance;
        }
        static void destory()
        {
    
            if(_pInstance)
            {
                
                Category::shutdown();
            }
        }
    private:
        Mylog():root(Category::getRoot()){
            PatternLayout * ptnLayout1 = new PatternLayout();
            ptnLayout1->setConversionPattern("%d [%p] %m%n");
            PatternLayout * ptnLayout2 = new PatternLayout();
            ptnLayout2->setConversionPattern("%d [%p] %m%n");
            PatternLayout * ptnLayout3 = new PatternLayout();
            ptnLayout3->setConversionPattern("%d [%p] %m%n");
    
            OstreamAppender * ostreamAppender = new OstreamAppender("ostreamAppender",&cout);
            ostreamAppender->setLayout(ptnLayout1);
    
            FileAppender *fileAppender = new FileAppender("fileAppender","davarain.log");
            fileAppender->setLayout(ptnLayout2);
    
            RollingFileAppender * rollingAppender = new RollingFileAppender("rollingAppender","rollingAppender.log",5*1024,2);
            rollingAppender->setLayout(ptnLayout3);
    
            root.setAppender(ostreamAppender);
            root.addAppender(fileAppender);
            root.addAppender(rollingAppender);
    
            root.setPriority(Priority::DEBUG);
            cout << "Mylog()" << endl;
        }
        ~Mylog()
        {
            cout << "~Mylog()" << endl;
        }
    private:
        Category & root;
        static Mylog * _pInstance;
    };
    
    Mylog * Mylog::_pInstance = nullptr;
    
    void Mylog::Info(const char *msg)
    {
        root.info(msg);
    }
    void Mylog::Warn(const char *msg)
    {
        root.warn(msg);
    }
    void Mylog::Debug(const char *msg)
    {
        root.debug(msg);
    }
    void Mylog::Error(const char *msg)
    {
        root.error(msg);
    }
    void my_logInfo(int line, const char *filename, const char *funcName, const char *msg)
    {
        Mylog *log = Mylog::getInstance();  
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + std::string(filename) + " this is line: " + std::to_string(line) + " func name: " + string(funcName);
        log->Info(tempMsg.c_str());
    }
    void my_logError(int line,const char *filename,const char *funcName, const char *msg)
    {
        Mylog *log = Mylog::getInstance();
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + std::string(filename) + " this is line: " + std::to_string(line) + " func name: " + string(funcName);
        log->Error(tempMsg.c_str());
    }
    void my_logWarn(int line,const char *filename,const char *funcName, const char *msg)
    {
        Mylog *log = Mylog::getInstance();
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + std::string(filename) 
                  + " this is line: " + std::to_string(line) + " func name: " + string(funcName);
        log->Warn(tempMsg.c_str());
    void my_logDebug(int line, const char *filename, const char *funcName,const char *msg)
    {
        Mylog *log = Mylog::getInstance();
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + std::string(filename) + " this is line: " + std::to_string(line) + " func name: " + string(funcName);
        log->Debug(tempMsg.c_str());
    }
    

      C++20:

    #pragma once
    /*
    #define logInfo(msg) 
        my_logInfo(__LINE__,__FILE__,__FUNCTION__,msg)
    #define logWarn(msg)
        my_logWarn(__LINE__,__FILE__,__FUNCTION__,msg)
    #define logError(msg)
        my_logError(__LINE__,__FILE__,__FUNCTION__,msg)
    #define logDebug(msg)
        my_logDebug(__LINE__,__FILE__,__FUNCTION__,msg)
    */
    #include <stdlib.h>
    #include <iostream>
    #include <string>
    #include <experimental/source_location>
    using std::cout;
    using std::endl;
    using std::string;
    using namespace std::experimental;
    
    #include <log4cpp/Category.hh>
    #include <log4cpp/Priority.hh>
    #include <log4cpp/FileAppender.hh>
    #include <log4cpp/RollingFileAppender.hh>
    #include <log4cpp/OstreamAppender.hh>
    #include <log4cpp/PatternLayout.hh>
    
    using namespace log4cpp;
    class Mylog
    {
    public:
        void Warn(const char *msg);
        void Error(const char *msg);
        void Debug(const char * msg);
        void Info(const char * msg);
        
        static Mylog * getInstance()
        {
            if(_pInstance == nullptr){
                _pInstance = new Mylog();
            }
            return _pInstance;
        }
        static void destory()
        {
    
            if(_pInstance)
            {
                
                Category::shutdown();
            }
        }
    private:
        Mylog():root(Category::getRoot()){
            PatternLayout * ptnLayout1 = new PatternLayout();
            ptnLayout1->setConversionPattern("%d [%p] %m%n");
            PatternLayout * ptnLayout2 = new PatternLayout();
            ptnLayout2->setConversionPattern("%d [%p] %m%n");
            PatternLayout * ptnLayout3 = new PatternLayout();
            ptnLayout3->setConversionPattern("%d [%p] %m%n");
    
            OstreamAppender * ostreamAppender = new OstreamAppender("ostreamAppender",&cout);
            ostreamAppender->setLayout(ptnLayout1);
    
            FileAppender *fileAppender = new FileAppender("fileAppender","davarain.log");
            fileAppender->setLayout(ptnLayout2);
    
            RollingFileAppender * rollingAppender = new RollingFileAppender("rollingAppender","rollingAppender.log",5*1024,2);
            rollingAppender->setLayout(ptnLayout3);
    
            root.setAppender(ostreamAppender);
            root.addAppender(fileAppender);
            root.addAppender(rollingAppender);
    
            root.setPriority(Priority::DEBUG);
            cout << "Mylog()" << endl;
        }
        ~Mylog()
        {
            cout << "~Mylog()" << endl;
        }
    private:
        Category & root;
        static Mylog * _pInstance;
    };
    
    Mylog * Mylog::_pInstance = nullptr;
    
    void Mylog::Info(const char *msg)
    {
        root.info(msg);
    }
    void Mylog::Warn(const char *msg)
    {
        root.warn(msg);
    }
    void Mylog::Debug(const char *msg)
    {
        root.debug(msg);
    }
    void Mylog::Error(const char *msg)
    {
        root.error(msg);
    }
    void logInfo(const char *msg,const source_location& location= source_location::current())
    {
        Mylog *log = Mylog::getInstance();  
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + location.file_name() + " this is line: " + std::to_string(location.line()) + " func name: " + location.function_name();
        log->Info(tempMsg.c_str());
    }
    void logError(const char *msg, const source_location& location = source_location::current())
    {
        Mylog *log = Mylog::getInstance();
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + location.file_name() + " this is line: " + std::to_string(location.line()) + " func name: " + location.function_name();
        log->Error(tempMsg.c_str());
    }
    void logWarn(const char *msg,const source_location& location = source_location::current())
    {
        Mylog *log = Mylog::getInstance();
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + location.file_name() + " this is line: " + std::to_string(location.line()) + " func name: " + location.function_name();
        log->Warn(tempMsg.c_str());
    }
    void logDebug(const char *msg,const source_location& location = source_location::current())
    {
        Mylog *log = Mylog::getInstance();
        string tempMsg = msg;
        tempMsg = tempMsg + " doucument name:" + location.file_name() + " this is line: " + std::to_string(location.line()) + " func name: " + location.function_name();
        log->Debug(tempMsg.c_str());
    }
    

      

     

  • 相关阅读:
    响应式页面@media介绍和移动端单位介绍
    jQuery的位置信息和事件
    jQuery的文档操作和操作input的value值,ajax
    jQuery的选择器和属性操作
    虚拟机linux桥接联网问题
    Linux基础知识与命令1(su passwd)
    操作系统基础知识笔记1
    Algs4-2.3.10快排100万元素对比次数超1000亿次的概率
    Algs4-2.3.9请说明Quick.sort()在处理只有两种、三种主键值时的行为
    Algs4-2.3.8Quick.sort()在处理N个全部重复的元素时比较次数
  • 原文地址:https://www.cnblogs.com/Davirain/p/11073602.html
Copyright © 2020-2023  润新知