There was a need that at start of next day, log messages get logged into next file in sequence which means one file on per day basis, keeping in mind not to compromise performance. The logic is that when ever a call to SetFileDescriptorToFile, i.e. open file, is made (which is usually once a day), store the base name of file in m_FileBaseName, find the epoch end of time of the day (that is time since Jan 1 1970 00:00:00 UTC/GMT) and store it in m_DayEndTime. Whenever a call to GetFD, i.e. give file descriptor to log message, is made, make a time() API call (give current time since epoch) and see, whether the current time epoch value exceed epoch end of time of the day, if no just return the current descriptor or else open the next file in sequence using base file name.
m_DayEndTime, i.e. epoch end of time of the day is calculated as follows:
time_t tLocal = time(NULL); // give current time in UTC/GMT timezone
tm tmGMT;
memcpy(&tmGMT, gmtime(&tLocal), sizeof(tm));
time_t tGMT = mktime(&tmGMT);
int timeZoneDiff = tLocal - tGMT; // get timezone difference of local timezone and UTC/GMT timezone
int tTimeZoneAdj = tLocal + timeZoneDiff; // get current time in local timezone
const int PER_DAY_TIME = 24*60*60;
int DayRemTime = PER_DAY_TIME-(tTimeZoneAdj % PER_DAY_TIME);
int m_DayEndTime = tLocal+DayRemTime;
tm *_tm=localtime(&tLocal);
File name in sequece using base file name is created as follow:
char name[255];
sprintf(name, "%s/%s%04d%02d%02d", DIR, (char *)m_FileBaseName.c_str(),
_tm->tm_year+1900,
_tm->tm_mon+1,
_tm->tm_mday);
The decision of whether to log message in current open file or should be logged into next file in sequence is made as follows:
time_t t = time(NULL);
if(t > m_DayEndTime) {
SetFileDescriptorToFile((char *)m_FileBaseName.c_str());
}
The whole code is as follows:
class CLogFile {
private:
string m_FileBaseName;
time_t m_DayEndTime;
FILE *FileDescriptor;
void SetFileDescriptorToFile(char *filename) {
if(NULL != this->FileDescriptor &&
stdout != this->FileDescriptor &&
stderr != this->FileDescriptor) {
fclose(this->FileDescriptor);
}
m_FileBaseName=filename;
time_t t = time(NULL);
#define PER_DAY_TIME 24*60*60
int remainingDaytime=PER_DAY_TIME-(t % PER_DAY_TIME);
m_DayEndTime=t+remainingDaytime;
tm *_tm=localtime(&t);
#define DIR "Logs"
if(_chdir(DIR) != 0) {
if(_mkdir(DIR) != 0) {
this->FileDescriptor=stderr;
cerr "Cannot create directory for Logs, using stderr" endl;
return;
}
} else {
_chdir("..");
}
char name[255];
sprintf(name, "%s/%s%04d%02d%02d", DIR,
(char *)m_FileBaseName.c_str(),
_tm->tm_year+1900,
_tm->tm_mon+1,
_tm->tm_mday);
if((this->FileDescriptor=fopen(name, "a+")) == NULL) {
this->FileDescriptor=stderr;
throw "Can not open logfile";
}
else {
setbuf(this->FileDescriptor, NULL);
}
}
FILE *GetFD() {
if(stdout == this->FileDescriptor ||
stderr == this->FileDescriptor) {
return this->FileDescriptor;
}
time_t t = time(NULL);
if(t > m_DayEndTime) {
SetFileDescriptorToFile((char *)m_FileBaseName.c_str());
}
return this->FileDescriptor;
}
};
m_DayEndTime, i.e. epoch end of time of the day is calculated as follows:
time_t tLocal = time(NULL); // give current time in UTC/GMT timezone
tm tmGMT;
memcpy(&tmGMT, gmtime(&tLocal), sizeof(tm));
time_t tGMT = mktime(&tmGMT);
int timeZoneDiff = tLocal - tGMT; // get timezone difference of local timezone and UTC/GMT timezone
int tTimeZoneAdj = tLocal + timeZoneDiff; // get current time in local timezone
const int PER_DAY_TIME = 24*60*60;
int DayRemTime = PER_DAY_TIME-(tTimeZoneAdj % PER_DAY_TIME);
int m_DayEndTime = tLocal+DayRemTime;
tm *_tm=localtime(&tLocal);
File name in sequece using base file name is created as follow:
char name[255];
sprintf(name, "%s/%s%04d%02d%02d", DIR, (char *)m_FileBaseName.c_str(),
_tm->tm_year+1900,
_tm->tm_mon+1,
_tm->tm_mday);
The decision of whether to log message in current open file or should be logged into next file in sequence is made as follows:
time_t t = time(NULL);
if(t > m_DayEndTime) {
SetFileDescriptorToFile((char *)m_FileBaseName.c_str());
}
The whole code is as follows:
class CLogFile {
private:
string m_FileBaseName;
time_t m_DayEndTime;
FILE *FileDescriptor;
void SetFileDescriptorToFile(char *filename) {
if(NULL != this->FileDescriptor &&
stdout != this->FileDescriptor &&
stderr != this->FileDescriptor) {
fclose(this->FileDescriptor);
}
m_FileBaseName=filename;
time_t t = time(NULL);
#define PER_DAY_TIME 24*60*60
int remainingDaytime=PER_DAY_TIME-(t % PER_DAY_TIME);
m_DayEndTime=t+remainingDaytime;
tm *_tm=localtime(&t);
#define DIR "Logs"
if(_chdir(DIR) != 0) {
if(_mkdir(DIR) != 0) {
this->FileDescriptor=stderr;
cerr "Cannot create directory for Logs, using stderr" endl;
return;
}
} else {
_chdir("..");
}
char name[255];
sprintf(name, "%s/%s%04d%02d%02d", DIR,
(char *)m_FileBaseName.c_str(),
_tm->tm_year+1900,
_tm->tm_mon+1,
_tm->tm_mday);
if((this->FileDescriptor=fopen(name, "a+")) == NULL) {
this->FileDescriptor=stderr;
throw "Can not open logfile";
}
else {
setbuf(this->FileDescriptor, NULL);
}
}
FILE *GetFD() {
if(stdout == this->FileDescriptor ||
stderr == this->FileDescriptor) {
return this->FileDescriptor;
}
time_t t = time(NULL);
if(t > m_DayEndTime) {
SetFileDescriptorToFile((char *)m_FileBaseName.c_str());
}
return this->FileDescriptor;
}
};
No comments:
Post a Comment