动手编写TCP服务器系列之一:日志文件
前言
在几个月之前,笔者想自己实现一个性能比较良好的基于tcp的服务器。于是断断续续写了个把月,因为还需要找工,还有论文什么的。拖了这么久。现在开辟这样的一个博客,我想记录下自己的思路,也和大家分享自己的代码。个人觉得一个优秀的服务器,不能考虑各种通用性,平台无关性。我写的这个服务器只针对linux平台。
在写这个系列文章之前,我想把功能都独立出来。每一篇文章专注于一个功能。
本系列文章均系笔者所写,难免有一些错误或者纰漏,如果小伙伴们有好的建议或者更好的算法,请不吝赐教。
正文
目标
本篇文章主要是讲TCP Server的日志功能。那么在一个服务器当中日志功能是必不可少的。无论是定位错误或者打印一些信息等等。日志的预期目标如下图所示。
Time是记录日志时间;Level是日志级别;PID是进程ID;TID是线程ID;Function是日志所在函数;Line是文件行;File是日志文件;Message是所打印的信息。
#ifndef LOG_HPP_ #define LOG_HPP_ #include <string> #include <cstdio> #include <cstring> #include <stdarg.h> #include <syscall.h> #include <sys/time.h> #include <linux/limits.h> #define LOG_STRING_MAX 4096 #define NEWLINE "\n" #define MAX_PATHSIZE PATH_MAX #define RETURN_OK 0 #define LOG(level,fmt,...) \ do { \ if( _curPDLevel >= level ) \ { \ log(level,__func__,__FILE__,__LINE__,fmt,##__VA_ARGS__);\ } \ }while( 0 ) \ #define CHECK( cond, retCode, gotoLabel, level, fmt, ... ) \ do { \ if( !( cond ) ) \ { \ rc = ( retCode ); \ LOG( (level), fmt, ##__VA_ARGS__ ); \ goto gotoLabel; \ } \ }while( 0 ) \ enum PDLEVEL { PDSERVER=0, PDERROR, PDEVENT, PDWARNING, PDINFO, PDDEBUG }; extern PDLEVEL _curPDLevel; const char * getPDLevelDesp( PDLEVEL level ); #define PD_DFT_DIAGLEVEL PDWARNING void log( PDLEVEL level, const char * func, const char * file, unsigned int line, const char * format, ... ); void log( PDLEVEL level, const char * func, const char * file, unsigned int lne, std::string message ); #endif
#include "log.hpp" #include "latch.hpp" #include "FileOp.hpp" const static char * PDLEVELSTRING[] = { "SEVERE", "ERROR", "EVENT", "WARNING", "INFO", "DEBUG" }; const char * getLevelDesp( PDLEVEL level ) { if( (unsigned int)level > (unsigned int)PDDEBUG ) { return "Unknown level"; } return PDLEVELSTRING[(unsigned int)level]; } const static char * LOG_HEADER_FORMAT = \ "[Time] %04d-%02d-%02d-%02d.%02d.%02d [Level] %s"OSS_NEWLINE \ "[PID] %-30d[TID] %d"OSS_NEWLINE \ "[Function] %-30s[Line] %d"OSS_NEWLINE \ "[File] %s"OSS_NEWLINE\ "[Message] %s"OSS_NEWLINE OSS_NEWLINE; LEVEL _curPDLevel = DFT_DIAGLEVEL; static char _diaglogPath[ OSS_MAX_PATHSIZE+1 ] = { 0 }; Latch _logMutex; FileOperation _logFile; // open log file static int _pdLogFileReopen() { int rc = RETURN_OK; _logFile.Close(); rc = _logFile.Open( _pdDiaglogPath ); if( rc ) { printf( "Failed to open log file, errono = %d", OSS_NEWLINE, rc ); goto error; } _logFile.SeekToEnd(); done: return rc; error: goto done; } // write log file static int _logFileWrite( const char * pData ) { int rc = RETURN_OK; size_t dataSize = strlen( pData ); _logMutex.get(); if( !_logFile.IsValid() ) { // open the file rc = _logFileReopen(); if( rc ) { printf( "Failed to open log file, erroro = %d"OSS_NEWLINE, rc); goto error; } } rc = _logFile.Write( pData, dataSize ); if( rc ) { printf( "Failed to write into log file, errno = %d"OSS_NEWLINE, rc ); goto error; } done: _logMutex.release(); return rc; error: goto done; } void log( PDLEVEL level, const char * func, const char * file, unsigned int line, const char * format, ... ) { int rc = RETURN_OK; if( _curPDLevel < level ) { return; } va_list ap; char userInfo[ PD_LOG_STRING_MAX ]; char sysInfo[PD_LOG_STRING_MAX]; struct tm otm; struct timeval tv; struct timezone tz; time_t tt; gettimeofday( &tv, &tz ); tt = tv.tv_sec; localtime_r( &tt, &otm ); // create user information va_start( ap, format ); vsnprintf( userInfo, PD_LOG_STRING_MAX, format, ap ); va_end( ap ); snprintf( sysInfo, LOG_STRING_MAX, LOG_HEADER_FORMAT, otm.tm_year + 1900, otm.tm_mon + 1, otm.tm_mday, otm.tm_hour, otm.tm_min, otm.tm_sec, PDLEVELSTRING[level], getpid(), syscall(SYS_gettid), func, line, file, userInfo ); printf( "%s"NEWLINE, sysInfo); /* if( _pdDiaglogPath[0] != '\0' ) { rc = _logFileWrite( sysInfo ); if( rc ) { printf( "Failed to write into log file, errno = %d"NEWLINE, rc ); printf( "%s"NEWLINE, sysInfo ); } } */ return; } /* int main( int argc, char ** argv ) { PD_LOG( PDERROR, "%d", 1 ); return 0; } */
代码仅供参考。可能中间用到了一些锁的机制或者一些写文件的类。比如FileOp在后续的文章中会慢慢呈现出来。
作者
出处:http://www.cnblogs.com/gina
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。