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的哲学中,所有的磁盘文件.目录.外设设备.驱动设备全部被抽象为了"文件" ...
随机推荐
- org.springframework.web.filter.DelegatingFilterProxy的理解
org.springframework.web.filter.DelegatingFilterProxy可以将filter交给spring管理. 我们web.xml中配置filter时一般采用下面这种 ...
- [学姿势]使用AngularJS+CodeIgniter框架经验谈
这篇文章作为总结总结7月份参与项目时遇到的新东西和问题,包括这两个框架(CodeIgniter.AngularJS)以及两个功能实现.有前端调试显示动态认证,也有用php实现功能模块. 1.添加设备 ...
- Spring基础知识汇总 Java开发必看
Spring简介 Spring框架由Rod Johnson开发,2004年发布了Spring框架的第一版.Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅 ...
- [iOS基础控件 - 4.1] APP列表
需求 1.以N宫格的形式展示应用信息 2.APP信息包括图标.名字.下载按钮 3.使用尽可能少的代码,从plist读取app信息,计算每个app图标的位置尺寸信息 A.思路 1.UI布局:N宫 ...
- ASP.Net 使用SqlBulkCopy批量插入
批量插入,以前我的做法是生成一堆insert into的sql语句,然后用程序一次值行,来实现. 今天看到了ASP.Net里可以使用DataTable,先将数据写入到DataTable中,然后使用Sq ...
- php中带mb的字符串处理函数
int strlen ( string $string ) int mb_strlen ( string $str [, string $encoding ] ) encoding参数为字符编码.如果 ...
- 安卓开发21:深入理解Handler
Handler相关说明: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 解释:安卓的UI线程(即OnCreate函数创建的线程)是线程非安全的.也就是说,在UI线程中,使用sleep这样 ...
- C++ 外部调用private方法
1.思考,对于C++,能不能在外部调用私有方法? 2.在Java中,子类继承不能缩小父类成员的访问权限.因为在Java中,继承只是表示Is-A关系,因此,父类提供的接口,子类必须承诺仍然提供,不能缩小 ...
- OpenCV快速遍历矩阵元素方法
OpenCV中Mat矩阵data数据的存储方式和二维数组不一致,二维数组按照行优先的顺序依次存储,而Mat中还有一个标示行步进的变量Step.使用Mat.ptr<DataTyte>(row ...
- [React Native] Build a Separator UI component
In this lesson we'll create a reusable React Native separator component which manages it's own style ...