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, , SEEK_END); \
fprintf(f, __VA_ARGS__);\
fprintf(f, "\r\n"); \
} \
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 = ; i < ; ++i)
{
DEMO_FILE_DEBUG("hello world %d", i);
sleep();
}
return ;
}

这样,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()
上一篇:【AGC030F】Permutation and Minimum DP


下一篇:Spring+Shiro的踩坑