'로그'에 해당되는 글 1건

  1. 2011.05.17 Log 찍기
2011. 5. 17. 09:52

서버 프로그램을 개발하다 보면 데이터를 주고 받거나 또는 읽고 쓰거나 할 때 내 예상과 다르게 나오는 경우 어쩔 수 없이 표준출력창에 데이터를 띄우던지 아니면 로그파일을 하나 만들어서 데이터를 주기적으로 찍어 내는 일이 허다하다.

필자 역시 C/S 구조의 프로그램을 다년간 개발하면서 socket과 pthread, list, map, date, time 등등 관련해서 여러가지 클래스로 만들어 개인적으로 하나의 라이브러리로 만들어서 사용하고 있다.

그 중 log에 대한 클래스를 하나 공개한다. 공개한다고 떠들어 놨는데 뭐 사실 대단한건 아니다.
특징이라면 가변인자를 사용하였다. 훨씬 더 강력한 기능을 갖게끔 만들 수도 있지만 필자의 로그는 그닥 어렵지 않다. ㅋㅋ
참고로 필자는 본 클래스가 적재 되어있는 라이브러리의 최 상위 클래스를 Lower라는 이름으로 지칭해 놨다. 그러니 Lower를 상속 받는데 있어서 저것이 무엇이냐 묻지 말아라. 멤버라고는 public에 int 타입의 Tag라는 이름을 가진녀석 뿐이다. 뭐 가져다 사용 하려면 그냥 상속 관계를 해제해라.
마지막으로 개발 환경은 HP-UX지만 아마 리눅스나 AIX, 윈도우에서도 돌아가는데는 크게 문제 될 것이 없을 것이다.

Log.h
#ifndef __LOG__
#define __LOG__

#include "include.h"
#include "Lower.h"

#define FILE_PATH       "./../log/"
#define FILENAME_LENGTH 0x0C

#ifndef NAME_LENGTH
#define NAME_LENGTH 0x04
#endif

class Log : public Lower
{
  private :
    FILE * fdFile;
    char * cpFileName;
    char * cpMyName;

    void OpenFile();
    void CloseFile();

  public  :
    Log(const char * MyName);
    ~Log();

    void AddLog(const char * Foramt, ...);
    void DeleteFile();
};

#endif



Log.cc
#include "Log.h"

Log::Log(const char * MyName)
{
  char        caDate[9];
  time_t      tNow;
  struct tm * stTm;

  memset(caDate, 0x00, sizeof(caDate));

  time(&tNow);
  stTm = localtime(&tNow);
  sprintf(caDate, "%04d%02d%02d", stTm->tm_year + 1900, stTm->tm_mon + 1, stTm->tm_mday);

  this->cpFileName = new char[FILENAME_LENGTH];
  this->cpMyName   = new char[NAME_LENGTH];

  memset(this->cpFileName, 0x00, FILENAME_LENGTH);
  memset(this->cpMyName,   0x00, NAME_LENGTH);

  strcpy(this->cpMyName, MyName);

  strcat(this->cpFileName, (char *)FILE_PATH);
  strcat(this->cpFileName, caDate);
  strcat(this->cpFileName, "_");
  strcat(this->cpFileName, MyName);
  strcat(this->cpFileName, ".log");
}

Log::~Log()
{
  this->CloseFile();

  delete [] this->cpMyName;
  delete [] this->cpFileName;

  this->cpMyName   = (char *)NULL;
  this->cpFileName = (char *)NULL;
}

void Log::OpenFile()
{
  this->fdFile = fopen(this->cpFileName, "a+");
  if(this->fdFile == NULL) { printf("( %s )Log file create fail.\n", this->cpFileName); }
}

void Log::CloseFile()
{
  if(this->fdFile) { fclose(this->fdFile); this->fdFile = (FILE *)NULL; }
}

void Log::AddLog(const char * Format, ...)
{
  char        caData[512];
  char        caDate[19];
  char        caTemp[128];
  time_t      tNow;
  struct tm * stTm;
  va_list     vaParam;
  int         FormatLength = 0;
  int         DataLength   = 0;

  memset(caData, 0x00, sizeof(caData));
  memset(caDate, 0x00, sizeof(caDate));
  memset(caTemp, 0x00, sizeof(caTemp));

  time(&tNow);
  stTm = localtime(&tNow);
  sprintf(caDate, "%04d%02d%02d%02d%02d%02d",
      stTm->tm_year + 1900, stTm->tm_mon + 1, stTm->tm_mday, stTm->tm_hour, stTm->tm_min, stTm->tm_sec);

  strcat(caData, this->cpMyName);
  strcat(caData, "] [");
  strcat(caData, caDate);
  strcat(caData, "] ");

  FormatLength = strlen(Format);
  DataLength   = strlen(caData);

  this->OpenFile();

  va_start(vaParam, Format);

  for(int i=0; i<FormatLength; i++)
  {
    memset(caTemp, 0x00, sizeof(caTemp));

    if(Format[i] == '%')
    {
      switch(Format[++i])
      {
        case 'f' :
        {
          double fValue = va_arg(vaParam, double);
          sprintf(caTemp, "%.2f", fValue);
          break;
        }
        case 'd' :
        {
          int    iValue = va_arg(vaParam, int);
          sprintf(caTemp, "%d", iValue);
          break;
        }
        case 's' :
        {
          char * sValue = va_arg(vaParam, char *);
          sprintf(caTemp, "%s", sValue);
          break;
        }
        default :
        {
          continue;
          break;
        }
      }

      memcpy(caData + DataLength, caTemp, strlen(caTemp));
      DataLength += strlen(caTemp);
    }
    else { caData[DataLength++] = Format[i]; }
  }

  fwrite(caData, DataLength, 1, this->fdFile);

  va_end(vaParam);

  this->CloseFile();
}

void Log::DeleteFile()
{
  time_t      tNow;
  struct tm * stTm;
  char        Com[26];

  memset(Com, 0x00, sizeof(Com));

  time(&tNow);
  stTm = localtime(&tNow);

  if(stTm->tm_mon == 0 || stTm->tm_mon == 1)
    { sprintf(Com, "rm -f ./../log/%04d%02d*%s*", stTm->tm_year + 1899, stTm->tm_mon + 11, this->cpMyName); }
  else
    { sprintf(Com, "rm -f ./../log/%04d%02d*%s*", stTm->tm_year + 1900, stTm->tm_mon - 1,  this->cpMyName); }

  system(Com);
}



사실 약간은.. 아주 약간은 손 봐야 하는 부분들이 있다. 로그를 찍을 때 길이에 대한 문제라던지.. 타입에 대한 확장이라던지.. 이 소스는 필요하다면 필자가 파일로 줄 수도 있다.
파일이 필요하거든 메일이나 댓글에 굽신거려라. ㅋㅋ 농담이다. 이런 좆밥 기술 가지고 대단한 것 처럼 굴 필자가 아니다.


Posted by 뿌직