本人一直使用的日志类,支持3种输出方式(windows窗体,udp,常规文件),并格式化输出:
1 2/**//* 3 nvlog.h 4 ---------------- 5 application logger 6 2003.10 created scott 7 2005.09.10 rebuild scott 8 created RegFileWriter,UdpWriter,WindowWriter to distinguish log data type 9 2005.09.22 modified RegFileWriter::RegFileWriter() scott 10 2005.11.10 scott add __FILE__,__LINE__ 11*/ 12 13#ifndef _NVLOG 14#define _NVLOG 15 16#ifdef _UNIX 17 #include <unistd.h> 18 #include <signal.h> 19 #include <sys/socket.h> 20 #include <fcntl.h> 21 #include <netinet/in.h> 22 #include <arpa/inet.h> 23#endif 24 25#ifdef WIN32 26 #include <windows.h> 27#include <winsock.h> 28#include <io.h> 29#endif 30 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <string> 35#include <string.h> 36#include <stdarg.h> 37#include <vector> 38#include <algorithm> 39 40#include "nvlock.h" 41#include "nvcalendar.h" 42 43class NVLog{ 44public: 45 enum WriterType{ 46 UDP, 47 REGFILE, 48 WINDOW, 49 UNKNOWN 50 }; 51 52 class LogWriter{ 53 public: 54 LogWriter(){ 55 _type = UNKNOWN; 56 } 57 58 virtual ~LogWriter(){ 59 60 } 61 62 virtual int Write(const char * data,unsigned int len){ 63 return 0; 64 } 65 virtual bool Open(){ 66 return true; 67 } 68 virtual void Close(){ 69 } 70 71 WriterType GetType(){ 72 return _type; 73 } 74 protected: 75 WriterType _type; 76 }; 77 #ifdef WIN32 78 class WindowWriter:public LogWriter{ 79 public: 80 81 virtual int Write(const char * data,unsigned int len){ 82 if( _refind){ 83 return Write2(_win_title.c_str(),data,len); 84 } 85 return SendMessageToWindow(_hwnd,data,len); 86 } 87 88 int Write2(const char * wintitle,const char * data,unsigned int len){ 89 HWND hwnd = FindWindow(0,wintitle); 90 len = SendMessageToWindow(hwnd,data,len); 91 // CloseHandle(hwnd); 92 return len; 93 } 94 95 virtual bool Open(){ 96 if( _refind){ //需要发送时发现 97 return true; 98 } 99 _hwnd = FindWindow(0,_win_title.c_str()); 100 if( !_hwnd){ 101 //MessageBox(NULL,"cannot find window",_win_title.c_str(),MB_OK); 102 return false; 103 } 104 return true; 105 } 106 virtual void Close(){ 107 if( _hwnd ){ 108 //CloseHandle(_hwnd); 109 } 110 111 } 112 113 WindowWriter(const char * wintitle,bool refind=false){ 114 _win_title = wintitle; 115 _hwnd = NULL; 116 _type = WINDOW; 117 _refind = refind; 118 } 119 120 protected: 121 int SendMessageToWindow(HWND hwnd ,const char * data,unsigned int len){ 122 if( hwnd == NULL){ 123 return 0; 124 } 125 COPYDATASTRUCT cds; 126 cds.lpData =(void*)data; 127 cds.cbData = len; 128 SendMessage(hwnd,WM_COPYDATA ,(UINT)hwnd,(long)&cds); 129 return len; 130 } 131 private: 132 std::string _win_title; 133 HWND _hwnd; 134 bool _refind; 135 }; 136 #endif 137 138 class RegFileWriter:public LogWriter{ 139 public: 140 typedef void (*OnReachedMaxFileSizeCB)(std::string &file); 141 RegFileWriter(const char * file){ 142 _cb_maxsize = NULL; 143 _fp = NULL ; 144 _file = file; 145 _type = REGFILE; 146 _cur_size = 0; 147 SetMaxFileSize(); 148 } 149 virtual void OnReachedMaxFileSize(){ 150 Close(); 151 Open(); 152 } 153 //void SetRoundTime(unsigned int round_time); //达到指定时间循环到文件头部 154 void SetMaxFileSize(unsigned int max_size = 1024*1024*2,OnReachedMaxFileSizeCB cb=NULL){ 155 _max_size = max_size; 156 _cb_maxsize = cb; 157 158 } 159 virtual bool Open(){ 160 _fp = fopen(_file.c_str(),"w"); 161 if( !_fp){ 162 return false; 163 } 164 //fseek(fp,0,SEEK_END); 165 _cur_size = 0;//ftell(fp); 166 return true; 167 } 168 169 virtual int Write(const char * data,unsigned int len){ 170 int ret; 171 if( _cur_size >= _max_size){ 172 OnReachedMaxFileSize(); 173 } 174 if( _fp == NULL){ 175 return -1; 176 } 177 ret = fwrite(data,len,1,_fp); 178 fflush(_fp); 179 _cur_size += len; 180 return len; 181 } 182 183 void Close(){ 184 if( _fp ){ 185 fclose(_fp); 186 } 187 _fp = NULL; 188 } 189 190 private: 191 unsigned int _cur_size,_max_size; 192 OnReachedMaxFileSizeCB _cb_maxsize; 193 194 FILE * _fp; 195 std::string _file; 196 }; 197 class Socket{ 198 public: 199 Socket(){ 200 _sock = -1; 201 } 202 203 204 protected: 205 std::string _host; 206 unsigned short _port; 207 int _sock; 208 }; 209 class UdpWriter:public Socket,public LogWriter{ 210 public: 211 212 ~UdpWriter(){ 213 Close(); 214 } 215 216 UdpWriter(const char * dest,unsigned short port){ 217 _host = dest; 218 _port = port; 219 _type = UDP; 220 } 221 222 virtual int Write(const char * data,unsigned int len){ 223 if( _sock < 0 ){ 224 return 0; 225 } 226 return send(_sock,data,len,0); 227 } 228 229 virtual bool Open(){ 230 sockaddr_in sa; 231 #ifdef WIN32 232 WORD wVersionRequested; 233 WSADATA wsaData; 234 int err; 235 wVersionRequested = MAKEWORD( 2, 2 ); 236 err = WSAStartup( wVersionRequested, &wsaData ); 237 if ( err != 0 ) { 238 return false; 239 } 240 #endif 241 sa.sin_family = AF_INET; 242 sa.sin_port = htons(_port); 243 sa.sin_addr.s_addr = inet_addr(_host.c_str()); 244 _sock = socket(AF_INET,SOCK_DGRAM,0); 245 if( _sock <0 ){ 246 return false; 247 } 248 connect(_sock,(sockaddr*)&sa,sizeof(sa)); 249 return true; 250 } 251 252 virtual void Close(){ 253 if( _sock >= 0 ){ 254#ifdef WIN32 255 closesocket (_sock); 256#endif 257#ifdef _UNIX 258 close(_sock); 259#endif 260 _sock = -1; 261 } 262 } 263 }; 264 265 266 enum LEVEL{ 267 LOG_ERROR =0x01, 268 LOG_WARNING =0x02, 269 LOG_MESSAGE =0x04, 270 LOG_DEBUG =0x08, 271 LOG_ALL =LOG_ERROR|LOG_WARNING|LOG_MESSAGE|LOG_DEBUG 272 }; 273 274 bool SetWriter(LogWriter * w){ 275 _writer_lock.Lock(); 276 _writer_list.push_back(w); 277 _writer_lock.Unlock(); 278 return true; 279 } 280 281 void RemoveWriter(LogWriter*w){ 282 std::vector<LogWriter* >::iterator itr; 283 _writer_lock.Lock(); 284 itr = std::find(_writer_list.begin(),_writer_list.end(),w); 285 if(itr != _writer_list.end()){ 286 _writer_list.erase(itr); 287 } 288 _writer_lock.Unlock(); 289 } 290 291 NVLog(){ 292 SetFormat(); 293 SetLevel(); 294 } 295 ~NVLog(){ 296 297 } 298 299 void SetLevel(int level = LOG_ERROR|LOG_WARNING|LOG_MESSAGE|LOG_DEBUG){ 300 _level = level; 301 } 302 #define LOG_MAX_BUFF_SIZE 1024*60 303 void Error(const char * fmt,){ 304 va_list marker; 305 char buff[LOG_MAX_BUFF_SIZE]; 306 va_start(marker,fmt); 307 vsprintf(buff,fmt,marker); 308 va_end(marker); 309 PrintString(LOG_ERROR,buff); 310 } 311 void Debug(const char * fmt,){ 312 va_list marker; 313 char buff[LOG_MAX_BUFF_SIZE]; 314 va_start(marker,fmt); 315 vsprintf(buff,fmt,marker); 316 va_end(marker); 317 PrintString(LOG_DEBUG,buff); 318 } 319 void Warning(const char * fmt,){ 320 va_list marker; 321 char buff[LOG_MAX_BUFF_SIZE]; 322 va_start(marker,fmt); 323 vsprintf(buff,fmt,marker); 324 va_end(marker); 325 PrintString(LOG_WARNING,buff); 326 } 327 void Message(const char * fmt,){ 328 va_list marker; 329 char buff[LOG_MAX_BUFF_SIZE]; 330 va_start(marker,fmt); 331 vsprintf(buff,fmt,marker); 332 va_end(marker); 333 PrintString(LOG_MESSAGE,buff); 334 } 335 void Print(int level,const char * fmt,){ 336 va_list marker; 337 char buff[LOG_MAX_BUFF_SIZE]; 338 va_start(marker,fmt); 339 vsprintf(buff,fmt,marker); 340 va_end(marker); 341 PrintString(level,buff); 342 } 343 344 void SetFormat(const char *format="<TIME>\t<LEVEL>\t<MESSAGE>\n"){ 345 _format = format; 346 } 347private: 348 void PrintString(int level,const char * data); 349private: 350 std::vector<LogWriter* > _writer_list; 351 NVLock _writer_lock; 352 std::string _format; // "<LOGLEVEL><LINENO><TIME><MESSAGE>\n" 353 unsigned int _level; 354}; 355 356inline 357void NVLog::PrintString(int level,const char * data){ 358 char *levelname; 359 if( !(level & _level) ){ 360 return; 361 } 362 363 switch(level){ 364 case LOG_ERROR: 365 levelname = "ERROR"; 366 break; 367 case LOG_WARNING: 368 levelname = "WARNING"; 369 break; 370 case LOG_MESSAGE: 371 levelname = "MESSAGE"; 372 break; 373 case LOG_DEBUG: 374 levelname = "DEBUG"; 375 break; 376 default: 377 return; 378 } 379 if( _format == "" ){ 380 return ; 381 } 382 383 std::string format; 384 char * mark; 385 char * occur; 386 format = _format; 387 mark = "<LEVEL>"; 388 int len; 389 len = strlen(mark); 390 if( occur = (char*)strstr( format.c_str(),(const char*)mark) ) { 391 format.replace( occur-format.c_str(),len,levelname); 392 } 393 mark = "<TIME>"; 394 len = strlen(mark); 395 if( occur = (char*)strstr( format.c_str(),(const char*)mark) ) { 396 format.replace( occur-format.c_str(),len,NVCalendar::GetCurTimeStr().c_str()); 397 } 398 mark = "<MESSAGE>"; 399 len = strlen(mark); 400 if( occur = (char*)strstr( format.c_str(),mark) ) { 401 format.replace( occur-format.c_str(),len,data); 402 } 403 std::vector<LogWriter* >::iterator itr; 404 _writer_lock.Lock(); 405 for( itr= _writer_list.begin();itr!=_writer_list.end();itr++){ 406 (*itr)->Write(format.c_str(),format.size()); 407 } 408 _writer_lock.Unlock(); 409} 410 411 412 413#define NVLOG_ADD_UDP_WRITER(log,host,port) \ 414 NVLog::UdpWriter * w = new NVLog::UdpWriter(host,port);\ 415 w->Open();\ 416 (log).SetWriter(w); 417 418#endif 419 420
|