撰写日志类

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 这个代码我用工业现场24X7值守的程序纪录各种信息, 简单易用;一般用一个全局日志对象, 有临界排斥可以多线程安全使用。
  /* 
Log File Library(WIN98/NT/2000) 

Compile by: BC++ 5; C++ BUILDER; VC++; VC.NET; 

copyright(c) 2004.5 - 2005.3  llbird wushaojian@21cn.com 
 http://blog.csdn.net/wujian53 
 
 
*/ 

 
/* 
Use:
//这个代码我用工业现场24X7值守的程序纪录各种信息, 简单易用;
//一般用一个全局日志对象, 有临界排斥可以多线程安全使用。
//有两个类
class LogFile;//用户定义日志文件名
class LogFileEx;//有日志文件名自动生成功能 , 可分年月日频率生成文件名, 可指定日志存放的目录

LogFile gLog("My.Log");
gLog.Log("test", 4);//记录日志
gLog.Log("系统启动");

LogFileEx gLog(".", LogFileEx :: YEAR);//一年生成一个日志文件
LogFileEx gLog(".\\Log", LogFileEx :: MONTH);//一月生成一个日志文件
LogFileEx gLog(".\\Log", LogFileEx :: DAY);//一天生成一个日志文件
//注意日志所属目录创建失败会自动退出, 请注意目录的合法性, 文件生成频率看情况掌握
//24小时运行的程序可以每天生成一个日志文件, 以免内容过多
 */ 

 
#ifndef _LOGFILE_H
  #define    _LOGFILE_H  
 
#include 
  <   assert.h   >  
#include 
  <   time.h   >  
#include 
  <   stdio.h   >  
#include 
  <   windows.h   >  
 
 
class    LogFile
  {
 protected :

 CRITICAL_SECTION _csLock;
  char   *  _szFileName;
 HANDLE _hFile;

  bool  OpenFile() // 打开文件, 指针到文件尾 
 
  {
   if (IsOpen())
    return   true ;

   if ( ! _szFileName)
    return   false ;

  _hFile  =   CreateFile(
   _szFileName, 
   GENERIC_WRITE,
   FILE_SHARE_READ  |  FILE_SHARE_WRITE,
   NULL,
   OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL,
   NULL 
  );

   if ( ! IsOpen()  &&  GetLastError()  ==   2 ) // 打开不成功, 且因为文件不存在, 创建文件 
 
   _hFile  =   CreateFile(
    _szFileName, 
    GENERIC_WRITE,
    FILE_SHARE_READ  |  FILE_SHARE_WRITE,
    NULL,
    OPEN_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL 
   );  

   if (IsOpen())
   SetFilePointer(_hFile,  0 , NULL, FILE_END);

   return  IsOpen();
 } 

 
 DWORD Write(LPCVOID lpBuffer, DWORD dwLength)
  {
  DWORD dwWriteLength  =   0 ;

   if (IsOpen())
   WriteFile(_hFile, lpBuffer, dwLength,  & dwWriteLength, NULL);

   return  dwWriteLength;
 } 

 
  virtual   void  WriteLog( LPCVOID lpBuffer, DWORD dwLength) // 写日志, 可以扩展修改 
 
  {
  time_t now;
   char  temp[ 21 ];
  DWORD dwWriteLength;

   if (IsOpen())
   {
   time( & now);
   strftime(temp,  20 ,  " %Y-%m-%d %H:%M:%S " , localtime( & now));

   WriteFile(_hFile,  " \xd\xa#----------------------------- " ,  32 ,  & dwWriteLength, NULL);
   WriteFile(_hFile, temp,  19 ,  & dwWriteLength, NULL);
   WriteFile(_hFile,  " -----------------------------#\xd\xa " ,  32 ,  & dwWriteLength, NULL);
   WriteFile(_hFile, lpBuffer, dwLength,  & dwWriteLength, NULL);
   WriteFile(_hFile,  " \xd\xa " ,  2 ,  & dwWriteLength, NULL);
   
   FlushFileBuffers(_hFile);

  } 

 } 

 
   void  Lock()   { ::EnterCriticalSection( & _csLock); } 
   void  Unlock()  { ::LeaveCriticalSection( & _csLock); } 
 
 public :
  
 LogFile( const   char   * szFileName  =   " Log.log " ) // 设定日志文件名 
 
  {
  _szFileName  =  NULL;
  _hFile  =  INVALID_HANDLE_VALUE;
  ::InitializeCriticalSection( & _csLock);

  SetFileName(szFileName);
 } 

 
  virtual   ~ LogFile()
  {
  ::DeleteCriticalSection( & _csLock);
  Close();

   if (_szFileName)
   delete []_szFileName;
 } 

 
  const   char   *  GetFileName()
  {
   return  _szFileName;
 } 

 
  void  SetFileName( const   char   * szName) // 修改文件名, 同时关闭上一个日志文件 
 
  {
  assert(szName);

   if (_szFileName)
   delete []_szFileName;

  Close();

  _szFileName  =   new   char [strlen(szName)  +   1 ];
  assert(_szFileName);
  strcpy(_szFileName, szName);
 } 

 
  bool  IsOpen()
  {
   return  _hFile  !=  INVALID_HANDLE_VALUE;
 } 

 
  void  Close()
  {
   if (IsOpen())
   {
   CloseHandle(_hFile);
   _hFile  =  INVALID_HANDLE_VALUE;
  } 

 } 

 
  void  Log(LPCVOID lpBuffer, DWORD dwLength) // 追加日志内容 
 
  {
  assert(lpBuffer);
  __try
   {
   Lock();

    if ( ! OpenFile())
     return ;

   WriteLog(lpBuffer, dwLength);
  } 

  __finally
   {
   Unlock();
  } 
 
 } 

 
  void  Log( const   char   * szText)
  {
  Log(szText, strlen(szText));
 } 

 
 private : // 屏蔽函数 
 

 LogFile( const  LogFile & );
 LogFile & operator   =  ( const  LogFile & );
;

  class    LogFileEx :    public    LogFile
  {
 protected :

  char   * _szPath;
  char  _szLastDate[ 9 ];
  int  _iType;

  void  SetPath( const   char   * szPath)
  {
  assert(szPath);

  WIN32_FIND_DATA wfd;
   char  temp[MAX_PATH  +   1 ]  =   { 0 } ;

   if (FindFirstFile(szPath,  & wfd)  ==  INVALID_HANDLE_VALUE  &&  CreateDirectory(szPath, NULL)  ==   0 )
   {
   strcat(strcpy(temp, szPath),  "  Create Fail. Exit Now! Error ID : " );
   ltoa(GetLastError(), temp  +  strlen(temp),  10 );
   MessageBox(NULL, temp,  " Class LogFileEx " , MB_OK);
   exit( 1 );
  } 

   else 
    {
   GetFullPathName(szPath, MAX_PATH, temp, NULL);
   _szPath  =   new   char [strlen(temp)  +   1 ];
   assert(_szPath);
   strcpy(_szPath, temp);
  } 

 } 

 
 public :

  enum  LOG_TYPE {YEAR  =   0 , MONTH  =   1 , DAY  =   2 } ;

 LogFileEx( const   char   * szPath  =   " . " , LOG_TYPE iType  =  MONTH)
  {
  _szPath  =  NULL;
  SetPath(szPath);
  _iType  =  iType;
  memset(_szLastDate,  0 ,  9 );
 } 

 
  ~ LogFileEx()
  {
   if (_szPath)
   delete []_szPath;
 } 

 
  const   char   *  GetPath()
  {
   return  _szPath;
 } 

 
  void  Log(LPCVOID lpBuffer, DWORD dwLength)
  {
  assert(lpBuffer);

   char  temp[ 10 ];
   static   const   char  format[ 3 ][ 10 ]  =   { " %Y " ,  " %Y-%m " ,  " %Y%m%d " } ;
  
  __try
   {
   Lock();
   
   time_t now  =  time(NULL);

   strftime(temp,  9 , format[_iType], localtime( & now));

    if (strcmp(_szLastDate, temp)  !=   0 ) // 更换文件名 
 
    {
    strcat(strcpy(_szFileName, _szPath),  " \\ " );
    strcat(strcat(_szFileName, temp),  " .log " );
    strcpy(_szLastDate, temp);
    Close();
   } 

 
    if ( ! OpenFile())
     return ;
   
   WriteLog(lpBuffer, dwLength);
  } 

  __finally
   {
   Unlock();
  } 

 } 

 
  void  Log( const   char   * szText)
  {
  Log(szText, strlen(szText));
 } 

 
 private : // 屏蔽函数 
 

 LogFileEx( const  LogFileEx & );
 LogFileEx & operator   =  ( const  LogFileEx & );

;

  #endif  
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
6月前
|
存储 数据采集 Kubernetes
一文详解K8s环境下Job类日志采集方案
本文介绍了K8s中Job和Cronjob控制器用于非常驻容器编排的场景,以及Job容器的特点:增删频率高、生命周期短和突发并发大。文章重点讨论了Job日志采集的关键考虑点,包括容器发现速度、开始采集延时和弹性支持,并对比了5种采集方案:DaemonSet采集、Sidecar采集、ECI采集、同容器采集和独立存储采集。对于短生命周期Job,建议使用Sidecar或ECI采集,通过调整参数确保数据完整性。对于突发大量Job,需要关注服务端资源限制和采集容器的资源调整。文章总结了不同场景下的推荐采集方案,并指出iLogtail和SLS未来可能的优化方向。
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
46 2
|
2月前
|
存储 运维 监控
超级好用的C++实用库之日志类
超级好用的C++实用库之日志类
41 0
|
6月前
|
Java 计算机视觉 Python
我的自描外挂制作日志——FPS类游戏的自瞄【优化改进1】
我的自描外挂制作日志——FPS类游戏的自瞄【优化改进1】
125 1
|
3月前
|
数据采集 监控 Kubernetes
Job类日志采集问题之iLogtail以减小容器发现和开始采集的延时如何优化
Job类日志采集问题之iLogtail以减小容器发现和开始采集的延时如何优化
|
3月前
|
数据采集 Kubernetes Java
Job类日志采集问题之在日志中添加容器的元信息标签,如何操作
Job类日志采集问题之在日志中添加容器的元信息标签,如何操作
|
3月前
|
存储 容器
Job类日志采集问题之DaemonSet采集方式的参数以减小采集延时如何调整
Job类日志采集问题之DaemonSet采集方式的参数以减小采集延时如何调整
|
3月前
|
容器
Job类日志采集问题之ECI产品采集方式对于弹性扩缩容是如何支持的
Job类日志采集问题之ECI产品采集方式对于弹性扩缩容是如何支持的
|
3月前
|
存储 数据采集 容器
Job类日志采集问题之DaemonSet采集方式在Job日志采集上如何表现
Job类日志采集问题之DaemonSet采集方式在Job日志采集上如何表现
|
3月前
|
存储 Kubernetes 数据处理
Job类日志采集问题之为什么Job容器的日志采集要考虑容器发现速度和开始采集延时,如何理解
Job类日志采集问题之为什么Job容器的日志采集要考虑容器发现速度和开始采集延时,如何理解