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()
linux基于file的logger的更多相关文章
- Linux -- 基于zookeeper的java api(二)
Linux -- 基于zookeeper的java api(二) 写一个关于基于集群的zookeeper的自定义实现HA 基于客户端和监控器:使用监控的方法查看每个注册过的节点的状态来做出操作. Wa ...
- Linux -- 基于zookeeper的java api(一)
Linux -- 基于zookeeper的java api 首先启动你所有的 zkService.sh 查看状态:检查是否启动正确 [root@hu-hadoop2 ~]# zkServer.sh s ...
- linux -- 基于zookeeper搭建yarn的HA高可用集群
linux -- 基于zookeeper搭建yarn的HA高可用集群 实现方式:配置yarn-site.xml配置文件 <configuration> <property> & ...
- linux C file format analysis
c语言文件格式 source file file.c C source, ASCII text pretreatment 预处理文件 file.i C source, ASCII text assem ...
- linux move file / folder bash command
linux move file / folder bash command mv $ which mv $ man mv # mv [-f] source target/ target folder ...
- Linux基于Docker的Redis主从复制、哨兵模式搭建
本教程基于CentOS7,开始本教程前,请确保您的Linux系统已安装Docker. 1.使用docker下载redis镜像 docker pull redis 安装完成后,使用docker imag ...
- 基于File NIO写的一个文件新增内容监控器
基于File NIO写的一个文件新增内容监控器 需求说明 监控一个文件,如果文件有新增内容,则在控制台打印出新增内容. 代码示例 FileMoniter文件监控器类 package com.black ...
- 嵌入式Linux基于framebuffer的jpeg格式本地LCD屏显示
在基于Linux的视频监控采集系统中,摄像头采集到的一帧视频图像数据一般都是经过硬件自动压缩成jpeg格式的,然后再保存到摄像头设备的缓冲区.如果要把采集到的jpeg格式显示在本地LCD屏上,由于我们 ...
- Linux Kernel File IO Syscall Kernel-Source-Code Analysis(undone)
目录 . 引言 . open() syscall . close() syscall 0. 引言 在linux的哲学中,所有的磁盘文件.目录.外设设备.驱动设备全部被抽象为了"文件" ...
随机推荐
- Mongodb千万级数据在python下的综合压力测试及应用探讨
http://rfyiamcool.blog.51cto.com/1030776/1329351
- wuzhicms 自定义SQL 标签
{wz:sql sql="select * from wz_guestbook"} {loop $rs $r} {$r[title]} {/loop} {/wz} 自定义统计条数: ...
- C++11 并发指南------std::thread 详解
参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Int ...
- 命令ls
ls -a 显示所有文件,包括隐藏文件(.开头的文件,配置文件常为隐藏文件)ls -l 显示详细信息ls -R 递归显示子目录结构ls -ld 显示目标目录的详细信息(并不返回目录里的内容)
- Android 网络权限配置
Android开发应用程序时,如果应用程序需要访问网络权限,需要在 AndroidManifest.xml 中加入以下代码 <uses-permission android:name=”andr ...
- hbase0.96与hive0.12整合高可靠文档及问题总结
本文链接:http://www.aboutyun.com/thread-7881-1-1.html 问题导读:1.hive安装是否需要安装mysql?2.hive是否分为客户端和服务器端?3.hive ...
- hdoj 5500 Reorder the Books
Reorder the Books Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 转载.NET 4.0中的泛型的协变和逆变
先做点准备工作,定义两个类:Animal类和其子类Dog类,一个泛型接口IMyInterface<T>, 他们的定义如下: public class Animal { } public ...
- 有return的情况下try catch finally的执行顺序(最有说服力的总结)
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
- PHP+MySQL开发技术详解—学习笔记
1. PHP is Hypertext Preproocessor. 2. Hello World: <?php Echo ‘Hello World!’; ?> 3. ...