- 浏览: 762846 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (1045)
- 数据结构 (36)
- UML与设计模式 (42)
- c++ (87)
- rust (36)
- Qt (41)
- boost模板元编程 (43)
- Linux (77)
- 汇编 (4)
- 其它 (2)
- 烹饪 (3)
- unix c / socket (73)
- 软件工程 (4)
- shell (53)
- Python (37)
- c++ primer 5th(c++11) (22)
- 数据库/MySQL (27)
- 数据存储 (4)
- lisp (7)
- git (4)
- Utility (3)
- CDN与DNS (54)
- Http (53)
- php (7)
- nginx/lua/openresty (41)
- redis (11)
- TCP/IP (16)
- 互联网 (6)
- kernel (2)
- go (34)
- 区块链 (43)
- 比特股 (13)
- 以太坊 (23)
- 比特币 (23)
- 密码学 (10)
- EOS (53)
- DAG (1)
- docker (1)
- filecoin (7)
- solidity (65)
- ipfs (8)
- 零知识证明 (1)
- openzeppelin (3)
- java (1)
- defi (7)
- Ton (0)
最新评论
log.h
log.cpp
main
#ifndef __LOG_H__ #define __LOG_H__ #include <stdio.h> #include <pthread.h> namespace log { #define LOG_MAX_LENGTH 4096 #define FLUSH_LINE 2 #define EMERG 8 // #define ALERT 7 // #define CRIT 6 // #define WARNING 5 // #define ERR 4 //错误 #define NOTICE 3 //注意信息 #define INFO 2 //普通信息 #define DEBUG 1 //调试信息 #define NONE 0 // static const char g_alertStr[128] = "[Alert]:" ;//比warning级别要高,表示系统可能处于异常运行状态,如连接数据库失败,无法正常向数据库进行操作等 static const char g_errorStr[128] = "[Error]:" ;//可以确定是程序上bug,需开发人员检查程序逻辑 static const char g_warningStr[128] = "[Warning]:" ;//虽不是服务器端错误,但需要高度关注 static const char g_infoStr[128] = "[Info]:" ;//一些有用信息,它比普通信息要略高,但可能没有Warning那么严重 static const char g_messageStr[128] = "[Message]:" ;//普通信息 static const char g_sqlStr[128] = "[Sql]:";//数据库操作语句 #ifndef TIME_CHN_FMT #define TIME_CHN_FMT "%Y-%m-%d %H:%M:%S" #endif /* time_t转时间字符串 */ char* timeToString(time_t tmTime, const char *fmt,char *strTime, int len); class CLog { public: //the singleton static CLog* getInstance(); //初始化 int init(const char* path,const char* fileName, short level=DEBUG,unsigned int logFileMaxNum=50,unsigned int logFileMaxSize=10*1024*1024); //关闭 int close(); //写日志 void plog(short level, const char *fmt, ...); private: CLog(); virtual ~CLog(); //检测文件大小是否超过上限 bool fileSizeOverflow(const char *fileName); //创建新文件 void createNewFile(); private: FILE *mFile; //日志文件路径 char mFilePath[1024]; //日志缓冲区 char mLogBuf[LOG_MAX_LENGTH]; //lock pthread_mutex_t mWriteLogLock; //上一条日志重复次数 int mRepeatCount; //当前日志文件大小 unsigned int mCurrLogFileSize; //日志文件大小上限 unsigned int mLogFileMaxSize; //当前的日志级别 int mLogLevel; //是否已关毕 bool mClosed; //日志的最大文件数 unsigned int mLogFileMaxNum; //日志的当前文件数 unsigned int mLogFileCurrNum; }; }//end of namespace log #endif
log.cpp
#include "log.h" #include <iostream> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <stdarg.h> #include <string.h> using std::cout; using std::endl; namespace log { /* 时间转字符串 */ char* timeToString(time_t tmTime, const char *fmt,char *strTime, int len) { struct tm gmTime; localtime_r(&tmTime, &gmTime); strftime(strTime, (size_t) len, fmt, &gmTime); return strTime; } /* the singleton */ CLog* CLog::getInstance() { static CLog log; return &log; } CLog::CLog() { mFile = NULL; mRepeatCount = 0; mCurrLogFileSize = 0; mLogFileMaxSize = 0; mLogFileMaxNum = 0; memset(mLogBuf, 0, sizeof(mLogBuf)); mClosed = false; mLogFileCurrNum = 0; } CLog::~CLog() { close(); } /* 关闭 */ int CLog::close() { if(mClosed){ return -1; } if (mFile) { fflush(mFile); fclose(mFile); } pthread_mutex_destroy(&mWriteLogLock); mClosed = true; return 0; } /* 初始化 */ int CLog::init(const char *path, const char *fileName, short level, unsigned int logFileMaxNum, unsigned int logFileMaxSize) { if (path == NULL || fileName == NULL || logFileMaxNum<1 || level < NONE || logFileMaxSize<1){ return -1; } if(pthread_mutex_init(&mWriteLogLock, NULL)!=0) { pthread_mutex_destroy(&mWriteLogLock); return -1; } mLogFileMaxNum = logFileMaxNum; mLogFileMaxSize = logFileMaxSize; if(access(path,F_OK)<0) { #ifdef _WIN32 mkdir(path); #else mkdir(path,0777); #endif } char fileFullName[256]; memset(fileFullName,0,sizeof(fileFullName)); strcpy(fileFullName,path); strcat(fileFullName,fileName); memset(mFilePath, 0, sizeof(mFilePath)); strncpy(mFilePath, fileFullName, sizeof(mFilePath)-1); //备份老日志,创建新日志。 if(fileSizeOverflow(fileFullName)){ createNewFile(); } mFile = fopen(fileFullName, "a+"); if (mFile == NULL){ return -1; } mLogLevel = level; fprintf(mFile, "\n\n\n\n\n"); fprintf(mFile, "--------------------------------------------------------\n"); fprintf(mFile, " 日志建立日期: %s %s\n", __DATE__, __TIME__); fprintf(mFile, "--------------------------------------------------------\n"); fprintf(mFile, "\n"); fflush(mFile); return 0; } /* 写日志 */ void CLog::plog(short level, const char *fmt, ...) { //与配置文件中的日志级别对比,选择输出日志 if (0 == mLogLevel || level < mLogLevel){ return; } if (NULL == mFile) { mFile = fopen(mFilePath, "a+"); if (NULL == mFile){ return; } mCurrLogFileSize = 0; } pthread_mutex_lock(&mWriteLogLock); static int lastBufLen = 0; static char lastBuf[LOG_MAX_LENGTH]; static int flushCount = 0; time_t t = time(NULL); char timeStr[64]; memset(timeStr,0,sizeof(timeStr)); timeToString(t, TIME_CHN_FMT, timeStr, sizeof(timeStr)-1); char printf_buf[LOG_MAX_LENGTH]; memset(printf_buf,0,sizeof(printf_buf)); va_list args; va_start(args, fmt); vsprintf(printf_buf, fmt, args); va_end(args); int len = strlen(printf_buf) + 1; if (len == lastBufLen) { if (strcmp(lastBuf, printf_buf) == 0) { ++mRepeatCount; pthread_mutex_unlock(&mWriteLogLock); return; } } else { if (mRepeatCount > 0){ mCurrLogFileSize += fprintf(mFile, "[%s]: 上一条日志重复%u次。\n", timeStr, mRepeatCount); } lastBufLen = len; mRepeatCount = 0; memcpy(lastBuf, printf_buf, len); } mCurrLogFileSize += fprintf(mFile, "[%s] ", timeStr); mCurrLogFileSize += fprintf(mFile, "%s", printf_buf); if (INFO < level) { fflush(mFile); }else if (++flushCount >= FLUSH_LINE) { flushCount = 0; fflush(mFile); } if (mCurrLogFileSize > mLogFileMaxSize) { createNewFile(); mFile = fopen(mFilePath, "a+"); if (mFile) { mCurrLogFileSize = 0; timeToString(t, TIME_CHN_FMT, timeStr, sizeof(timeStr)-1); mCurrLogFileSize += fprintf(mFile, "[%s]: ", timeStr); mCurrLogFileSize += fprintf(mFile, "%s", printf_buf); } } //如果是调试模式,则会将日志输出在终端上 if(mLogLevel==DEBUG){ cout << printf_buf << endl; } pthread_mutex_unlock(&mWriteLogLock); } /* 重命名旧文件,创建新文件 */ void CLog::createNewFile() { char newFullName[1024]; memset(newFullName,0,sizeof(newFullName)); //如果是第一次则先遍历一次 if(mLogFileCurrNum==0) { for(unsigned int i=1;i<=mLogFileMaxNum;i++) { snprintf(newFullName,sizeof(newFullName), "%s.%02d", mFilePath, i); //不存在,则创建 if((access(newFullName,F_OK))<0) { mLogFileCurrNum = i; break; } //如果文件存在,则继续找,如果找到最后也存在则删除第一个 if(i==mLogFileMaxNum) { snprintf(newFullName,sizeof(newFullName), "%s.%02d", mFilePath, 1); unlink(newFullName); mLogFileCurrNum = 1; } } }else { mLogFileCurrNum++; if(mLogFileCurrNum>mLogFileMaxNum){ mLogFileCurrNum = 1; } snprintf(newFullName,sizeof(newFullName), "%s.%02d", mFilePath, mLogFileCurrNum); //已存在,则删除 if((access(newFullName,F_OK))>=0){ unlink(newFullName); } fclose(mFile); mFile = NULL; } if (0 != rename(mFilePath, newFullName)){ return; } int ret = creat(mFilePath, 0664); ::close(ret); } /* 检测文件大小是否超过上限 */ bool CLog::fileSizeOverflow(const char *fileName) { if (NULL == fileName){ return false; } char path[1024]; memset(path,0,sizeof(path)); strncpy(path, fileName, sizeof(path)-1); path[sizeof(path)-1] = '\0'; FILE *fp = fopen(path, "r"); if (fp == NULL){ return false; } int ret = fseek(fp, 0, SEEK_END); if (0 != ret) { fclose(fp); return false; } mCurrLogFileSize = ftell(fp); if (mCurrLogFileSize < mLogFileMaxSize) { fclose(fp); return false; } mCurrLogFileSize = 0; fclose(fp); return true; } }//end of namespace log
main
#include "log.h" #include <unistd.h> using namespace log; int main() { CLog::getInstance()->init("/usr/local/code/MyLog_debug/","test.log"/*,1,10,1024*1024*/); int i = 0; while(true) { i++; CLog::getInstance()->plog(NOTICE,"%s h:%d\n",g_messageStr,i); usleep(1000); } }
发表评论
-
滑动窗口与拥塞控制
2017-09-29 14:47 759滑动窗口:用作流量控制: 1.发送端和接收端各维护一个独立的发 ... -
rawsocket发送tcp包
2017-09-25 11:52 983testTcp.h #ifndef TESTTCP_H ... -
柔性数组
2017-09-20 09:53 506#include <iostream> #i ... -
rawsocket发送dns包
2017-09-14 15:18 614#include <stdio.h> #in ... -
rawsocket发送icmp包
2017-09-06 09:54 659#include <stdio.h> #in ... -
查看glibc版本
2016-12-07 14:13 548strings /lib64/libc.so.6 |grep ... -
netfilter
2016-10-04 20:31 478http://blog.chinaunix.net/uid-2 ... -
gdb的简单使用
2016-09-19 15:18 417注意编译的时间加上-g参数 1.调试运行 gdb a.out ... -
TCP各状态的意义
2016-03-01 14:06 421各个状态的意义如下: LISTEN - 侦听来自远方TCP端 ... -
trim
2015-05-14 14:45 364/* trim from start */ ... -
TIMEWAIT与CLOSEWAIT
2015-03-17 11:32 660http://blog.csdn.net/kobejayand ... -
TcpClient
2015-01-16 17:46 471TcpClient.h #ifndef TCPCLIENT ... -
信号量
2014-09-26 10:20 682#include <semaphore.h> ... -
共享内存
2014-09-17 10:39 596SharedMemory.h #ifndef SHARED ... -
记录锁
2014-09-11 16:32 437#include <errno.h> #in ... -
popen
2014-09-06 14:50 640#include <stdio.h> #in ... -
大小端存储
2014-09-05 09:29 603#include <stdio.h> i ... -
条件变量(cond)
2014-09-01 11:02 878#include <pthread.h> # ... -
读写锁
2014-09-01 10:33 729#include <pthread.h> # ... -
trylock
2014-09-01 10:07 667#include <pthread.h> # ...
相关推荐
log4cplus是C++编写的开源的日志系统,功能非常全面,用到自己开发的工程中会比较专业的,:),本文介绍了log4cplus基本概念,以及如何安装,配置。 ### 简介 ### log4cplus是C++编写的开源的日志系统,前身是java...
Log4j和Log4j2的区别 Log4j和Log4j2是两个常用的日志记录工具,它们都来自Apache开源项目。虽然它们都是日志记录工具,但是它们之间有很多区别。下面我们将从配置文件类型、核心JAR包、文件渲染和Log调用四个方面来...
5. 关键配置来了:`<param name="DatePattern" value="'.'yyyy-MM-dd'.txt'" />`,这将使日志文件名为`log.yyyy-MM-dd.txt`的形式,便于识别和清理。 6. 最后,添加`...
Log4j是一个广泛使用的Java日志记录框架,它允许开发者在应用程序中轻松地记录各种级别的日志信息,如DEBUG、INFO、WARN、ERROR等。在2021年底,一个重大的安全漏洞(CVE-2021-44228)被发现在Log4j2的早期版本中,...
**log4cplus日志封装log** 在软件开发过程中,日志记录是一项至关重要的任务,它可以帮助开发者追踪程序运行状态,定位错误,以及进行性能分析。`log4cplus`是一个专门为C++设计的开源日志系统,它提供了一种高效、...
Log4cxx是Apache软件基金会的一个开源项目,它是C++版的log4j,提供了一套强大的日志处理机制。本文将详细讨论如何将log4cxx封装为通用LOG宏,以及其配置文件的详细内容。 首先,让我们了解log4cxx的基本概念。Log4...
分别有disruptor-3.3.4.jar(Log4j2异步日志的底层实现)、log4j-api-2.19.0.jar(log4j门面)、log4j-core-2.19.0.jar(log4j实现)、log4j-slf4j-impl-2.19.0.jar(SLF4J与Log4j绑定)、slf4j-api-1.7.30.jar(SLF...
Log4perl是Perl编程语言中一个强大的日志记录框架,其设计灵感来源于Java的Log4j库。在Perl社区中,Log4perl被广泛应用于各种项目,为开发者提供了灵活、可扩展的日志处理机制。"Log-Log4perl-1.36.tar.gz"这个...
`LogFileAppender`将日志信息写入名为`log-file.txt`的文件,`ConsoleAppender`则将日志输出到控制台。日志格式由`PatternLayout`定义,可以自定义显示内容。`LevelRangeFilter`用于过滤日志级别,只允许`DEBUG`至`...
针对Log4j 2 远程代码执行漏洞,需要用到的升级资源包,适用于maven资源库,包括log4j,log4j-core,log4j-api,log4j-1.2-api,log4j-jpa等全套2.15.0 maven资源库jar包。如果是maven本地仓库使用,需要将zip包解压...
### Log4j2简介 Log4j2是Apache软件基金会推出的日志框架,它是Log4j 1.x的重构版本,旨在提供更为高效且灵活的日志解决方案。与Log4j 1.x相比,Log4j2在设计上进行了重大改进,并解决了Logback等其他日志框架中...
Log4j、Log4j2和Fastjson是Java开发中常用的三个库,它们在软件开发中扮演着重要的角色。Log4j是Apache的一个开源项目,主要用于日志记录,提供了灵活的日志配置,允许开发者根据需求调整日志输出的级别和格式。Log4...
自己编译好的log4cpp的DLL 和 LIB 封装了一个使用类,从本地读取配置log级别等信息,可输出多个种类的日志文件,输出示例如下 [2017-02-20 16:09:51.910](NOTICE)Sys : 进入了CPfy_log4cppDlg::OnBnClickedButton1...
Apache log4j2零日漏洞,根据 log4j-2.15.0-rc2 版本编译生成log4j-api-2.15.0.jar 1.解压你的jar jar xvf XXX.jar 2. 删除旧版本jar cd ./BOOT-INF/lib rm -rf log4j-api-*.jar 3. 上传新版本log4j-api-2.15.0....
《log4j-2.18.0:修复重大安全漏洞的紧急更新》 在IT领域,安全性始终是首要关注的问题。近期,一个名为“log4j2”的严重安全漏洞引发了广泛关注,它影响了所有log4j2版本,从2.0开始直到2.18.0版本之前。这个漏洞...
Log4j是Java编程语言中最常用的日志记录框架之一,由Apache软件基金会开发。它提供了灵活的日志记录功能,使得开发者能够轻松地控制日志信息的输出格式、输出位置以及输出级别。此次提及的`log4j-api-2.12.4.jar`和`...
Apache log4j2零日漏洞,根据 log4j-2.15.0-rc2 版本编译生成log4j-api-2.15.0.jar 1.解压你的jar jar xvf XXX.jar 2. 删除旧版本jar cd ./BOOT-INF/lib rm -rf log4j-api-*.jar 3. 上传新版本log4j-api-...
`log4z`提供了丰富的日志级别,包括`LOG_TRACE`、`LOG_DEBUG`、`LOG_INFO`、`LOG_WARNING`、`LOG_ERROR`和`LOG_FATAL`。根据项目需求,可以选择性地开启或关闭不同级别的日志。 ```cpp #include "log4z.h" void ...
本教程将详细阐述如何使用四个关键组件——Maven、SpringMVC、MyBatis和Log4j——来搭建一个强大的Web应用框架,旨在提高开发效率并优化项目管理。 **Maven** 是一个流行的项目管理和综合工具,它通过统一的构建...
Log4j和Log4j2是两种广泛使用的Java日志框架,它们提供了灵活的日志配置和高性能的日志处理能力。本文将详细介绍如何在SpringBoot项目中配置Log4j和Log4j2。 ### SpringBoot与Log4j Log4j是Apache的一个开源项目,...