xlogger is used to log any information to a log file. It can log by setting level log. See test.cpp
//
//
#include "xlogger.h"
////////////////////////////////////////////////////////////////////////////////
// xlogger.h
// Author: Seree Rakwong
// Date: 5-NOV-10
// Purpose: Log a file
#ifndef xlogger_h
#define xlogger_h
#include <fstream>
#include <map>
#include <string>
#include <pthread.h>
const char DDMMYY_HHMMSS[] = "%d/%m/%y %H:%M:%S";
const char DMY_HMS[] = "%d%m%y_%H%M%S";
class xlogger : public std::ofstream {
private:
std::map<int, std::string> level2name_map_;
std::map<std::string, int> name2level_map_;
int cur_level_;
std::string filename_;
std::string datetime_format_;
unsigned long log_size_;
pthread_mutex_t write_mutex_;
public:
xlogger();
xlogger(const char *filename);
virtual ~xlogger();
public:
void open(const char *filename);
void open(const std::string& filename);
int write(int level, const char *format, ...);
void set_level(int level, const std::string& lv_name);
const int current_level() const;
int& current_level();
const std::string& datetime_format() const;
std::string& datetime_format();
const unsigned long log_size() const;
unsigned long& log_size();
protected:
std::string current_time(const char *format = DDMMYY_HHMMSS);
};
#endif // xlogger_h
/////////////////////////////////////////////////////////////////////////
// xlogger.cpp
// Author: Seree Rakwong
// Date: 5-NOV-10
// Purpose: Log a file
#include "xlogger.h"
#include <cstdarg>
#include <cstdio>
#include <ctime>
#ifdef DEBUG
#include <iostream>
using std::cout;
using std::endl;
#endif
using std::ofstream;
using std::string;
using std::map;
extern int errno;
xlogger::xlogger()
: filename_(),
cur_level_(0),
datetime_format_(DDMMYY_HHMMSS),
log_size_(1048576) {
pthread_mutex_init(&write_mutex_, 0);
}
xlogger::xlogger(const char *filename)
: ofstream(filename, ios_base::out|ios_base::app),
filename_(filename),
cur_level_(0),
datetime_format_(DDMMYY_HHMMSS),
log_size_(1048576) {
pthread_mutex_init(&write_mutex_, 0);
}
xlogger::~xlogger() {
pthread_mutex_destroy(&write_mutex_);
close();
}
void xlogger::open(const char *filename) {
ofstream::open(filename, ios_base::out|ios_base::app);
filename_ = filename;
}
void xlogger::open(const string& filename) {
ofstream::open(filename.c_str(), ios_base::out|ios_base::app);
filename_ = filename;
}
void xlogger::set_level(int level, const string& name) {
level2name_map_[level] = name;
name2level_map_[name] = level;
}
const int xlogger::current_level() const {
return cur_level_;
}
int& xlogger::current_level() {
return cur_level_;
}
const string& xlogger::datetime_format() const {
return datetime_format_;
}
string& xlogger::datetime_format() {
return datetime_format_;
}
string xlogger::current_time(const char *format) {
char buffer[80];
time_t raw_time;
struct tm *time_info_ptr = 0;
time(&raw_time);
time_info_ptr = localtime(&raw_time);
string fmt(format);
if(fmt.length() > 0) {
strftime(buffer, 80, fmt.c_str(), time_info_ptr);
}
else {
strftime(buffer, 80, datetime_format_.c_str(), time_info_ptr);
}
string tmp(buffer);
return tmp;
}
int xlogger::write(int level, const char *format, ...) {
if(level > cur_level_) return 0;
char buffer[1024];
va_list args;
va_start(args, format);
int rc = vsprintf(buffer, format, args);
va_end(args);
// return failed if it's negative number
if(rc < 0) return rc;
// get level name
map<int, string>::iterator it = level2name_map_.find(level);
// write the buffer to output stream
string str(current_time(DDMMYY_HHMMSS));
if(it != level2name_map_.end()) {
str += " [";
str += it->second;
str += "] ";
}
str += buffer;
str += "\n"; // end-of-line
// write
pthread_mutex_lock(&write_mutex_);
size_t len = tellp();
if((unsigned long)(len + str.length()) >= log_size_) {
// rotate the log file
string cur_time = current_time(DMY_HMS);
// close
close();
// rename file
string new_filename(filename_);
new_filename += ".";
new_filename += cur_time;
int rc = rename(filename_.c_str(), new_filename.c_str());
if(rc == -1) {
return rc;
}
// reopen
open(filename_);
}
ofstream::write(str.c_str(), str.length());
pthread_mutex_unlock(&write_mutex_);
return rc;
}
const unsigned long xlogger::log_size() const {
return log_size_;
}
unsigned long& xlogger::log_size() {
return log_size_;
}
/////////////////////////////////////////////////////////////////////////
// test.cpp
// Author: Seree Rakwong
// Date: 5-NOV-10
// Purpose: Log a file
#include <iostream>
#include <string>
using namespace std;
class mylog : public xlogger {
public:
mylog() { init(); }
mylog(const char *filename) : xlogger(filename) { init(); }
//mylog(const string& filename) : xlogger(filename) { init(); }
public:
enum log_level_t_ {
System,
Protocol,
Data,
Debug
} log_level_t;
private:
void init() {
set_level(System, "S");
set_level(Protocol, "P");
set_level(Data, "D");
set_level(Debug, "G");
//current_level() = Debug;
}
};
int main(int argc, char **argv) {
if(argc < 2) {
cerr << "USAGE: " << argv[0] << " S|P|D|G" << endl;
cerr << "S - System level" << endl;
cerr << "P - Protocol level" << endl;
cerr << "D - Data level" << endl;
cerr << "G - Debug level" << endl;
return 1;
}
mylog logger("./meo.log");
switch(argv[1][0]) {
case 'P': logger.current_level() = mylog::Protocol; break;
case 'D': logger.current_level() = mylog::Data; break;
case 'G': logger.current_level() = mylog::Debug; break;
case 'S':
default:logger.current_level() = mylog::System; break;
}
cout << "log_size: [" << logger.log_size() << "]" << endl;
for(int i=0; i<1024; i++) {
logger.write(mylog::System, "{%04d::main} - this is a System level", __LINE__);
logger.write(mylog::Protocol, "{%04d::main} - this is a Protocol level", __LINE__);
logger.write(mylog::Data, "{%04d::main} - this is a Data level", __LINE__);
logger.write(mylog::Debug, "{%04d::main} - this is a Debug level", __LINE__);
}
return 0;
}