• linux基于file的logger


    我们可能会遇到这样的问题:即写出的代码可能需要编译成动态连接库并在不同运行环境下运行,而这些运行环境下log的输出方式可能不同,一种运行环境的log方式在另一种运行环境下可能无法输出。而为保证多种运行环境下的运行正确,我们不能在程序中使用特定运行环境的log机制,于是我们需要找到一种能够在多种运行环境下均能使用的log方式。

    有两种办法可以解决这个问题,一种是写一个抽象层的log库,用插件的方式在不同运行环境中加载为当时运行环境编写的log适配插件。另一种方式是将log输出到一个各种运行环境都能看到的地方,这里选择了file,之后为特殊运行环境单独写一个log读取器,将log内容重新输出到当时运行环境中。

    我这里演示后一种方式:创建一个如下名为demo_file_logger.h的文件

    /**
     * demo_file_logger.h
     */
    #ifndef DEMO_FILE_LOGGER_H
    #define DEMO_FILE_LOGGER_H
    
    
    #include <sys/file.h>
    #include <stdio.h>
    #include <assert.h>
    class DemoFileLogger
    {
    public:
      static DemoFileLogger& ref()
      {
        static DemoFileLogger self;
        return self;
      }
    
      ~DemoFileLogger()
      {
        if (ok())
        {
          fclose(file);
          file = nullptr;
        }
      }
    
      FILE* lock()
      {
        flock(file->_fileno, LOCK_EX);
        return file;
      }
    
      void unlock()
      {
        flock(file->_fileno, LOCK_UN);
      }
    
      bool ok()
      {
        return file != nullptr;
      }
    
    private:
      DemoFileLogger()
      {
        file = fopen(logFileName, "a");
        assert(file);
      }
    
    private:
      static constexpr const char* logFileName { "/tmp/demo_file_log.log" };
      FILE* file { nullptr };
    };
    
    #define DEMO_FILE_DEBUG(...) if (DemoFileLogger::ref().ok()) { 
      auto f = DemoFileLogger::ref().lock(); 
      if (f) { 
        fseek(f, 0, SEEK_END); 
        fprintf(f, __VA_ARGS__);
        fprintf(f, "
    "); 
      } 
      DemoFileLogger::ref().unlock(); }
    #define DEMO_FILE_INFO DEMO_FILE_DEBUG
    #define DEMO_FILE_WARNING DEMO_FILE_DEBUG
    #define DEMO_FILE_ERROR DEMO_FILE_DEBUG
    
    
    #endif /* DEMO_FILE_LOGGER_H */

    之后在另一个头文件demo_debug.h中使用开关ENABLE_DEMO_FILE_LOG来开启FILE LOG的功能

    /**
     * demo_debug.h
     */
    
    #ifndef DEMO_DEBUG_H
    #define DEMO_DEBUG_H
    
    #ifdef ENABLE_DEMO_FILE_LOG
    #include "demo_debug_file.h"
    #else   // ENABLE_DEMO_FILE_LOG
    #include "demo_debug_disable.h
    #endif  // ENABLE_DEMO_FILE_LOG
    
    #endif  // DEMO_DEBUG_H

    我们可以在其他程序代码里使用我们的log宏:

    /**
     * main.cpp
     */
    
    #include <unistd.h>
    
    #define ENABLE_DEMO_FILE_LOG
    #include "demo_debug.h"
    
    int main(int argc, char* argv[])
    {
      for (int i = 0; i < 100; ++i)
      {
        DEMO_FILE_DEBUG("hello world %d", i);
        sleep(1);
      }
      return 0;
    }

    这样,log就保存到了/tmp/demo_file_log.log中,我们可以用一个log读取器去实时读取这个log,并且清空这个临时文件,以保证其不会占用过多系统资源,下面是一个python写的示例:

    #!/usr/bin/env python
    
    def __main():
        import fcntl
        import time
        f = open("/tmp/demo_file_log.log", "a+")
        if f:
            while True:
                f.seek(0, 2)
                fl = f.tell()
                f.seek(0)
                fcntl.flock(f.fileno(), fcntl.LOCK_SH)
                if fl > 0:
                    reading = True
                    while reading:
                        s = f.read(1024)
                        print(s)
                        if f.tell() >= fl:
                            reading = False
                fcntl.flock(f.fileno(), fcntl.LOCK_UN)
    
                fcntl.flock(f.fileno(), fcntl.LOCK_EX)
                reading = True
                curpos = f.tell()
                f.seek(0, 2)
                fl = f.tell()
                f.seek(curpos, 0)
                if fl - curpos > 0:
                    while reading:
                        s = f.read(1024)
                        print(s)
                        if f.tell() >= fl:
                            reading = False
                f.truncate(0)
                fcntl.flock(f.fileno(), fcntl.LOCK_UN)
                time.sleep(0.01)
    
    if __name__ == "__main__":
        __main()
  • 相关阅读:
    从C,C++,JAVA和C#看String库的发展(一)----C语言和C++篇
    Intent----android中的伟大邮差
    一步一步掌握线程机制(五)---等待与通知机制
    一步一步掌握线程机制(四)---同步方法和同步块
    一步一步掌握线程机制(三)---synchronized和volatile的使用
    利用单例模式解决全局访问问题
    一步一步掌握java的线程机制(二)----Thread的生命周期
    一步一步掌握java的线程机制(一)----创建线程
    如何快速学会android的四大基础----Service篇
    前端工程师必备实用网站
  • 原文地址:https://www.cnblogs.com/astreye/p/6264158.html
Copyright © 2020-2023  润新知