49 #ifndef GRAPHCHI_LOG_LOG_HPP
50 #define GRAPHCHI_LOG_LOG_HPP
86 #define OUTPUTLEVEL LOG_DEBUG
100 #if OUTPUTLEVEL == LOG_NONE
102 #define logger(lvl,fmt,...)
103 #define logbuf(lvl,fmt,...)
107 #define logger(lvl,fmt,...) \
108 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl,__FILE__, __func__ ,__LINE__,fmt,##__VA_ARGS__))
111 #define logbuf(lvl,buf,len) \
112 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl,__FILE__, \
113 __func__ ,__LINE__,buf,len))
115 #define logstream(lvl) \
116 (log_stream_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl,__FILE__, __func__ ,__LINE__) )
119 static const char* messages[] = {
"DEBUG: ",
125 namespace logger_impl {
127 std::stringstream streambuffer;
151 log_to_console = consolelog;
161 return log_to_console;
170 template <
typename T>
174 pthread_getspecific(streambuffkey));
175 if (streambufentry != NULL) {
176 std::stringstream& streambuffer = streambufentry->streambuffer;
177 bool& streamactive = streambufentry->streamactive;
179 if (streamactive) streambuffer << a;
187 pthread_getspecific(streambuffkey));
188 if (streambufentry != NULL) {
189 std::stringstream& streambuffer = streambufentry->streambuffer;
190 bool& streamactive = streambufentry->streamactive;
194 if (a[strlen(a)-1] ==
'\n') {
202 file_logger& operator<<(std::ostream& (*f)(std::ostream&)){
205 pthread_getspecific(streambuffkey));
206 if (streambufentry != NULL) {
207 std::stringstream& streambuffer = streambufentry->streambuffer;
208 bool& streamactive = streambufentry->streamactive;
210 typedef std::ostream& (*endltype)(std::ostream&);
212 if (endltype(f) == endltype(std::endl)) {
213 streambuffer <<
"\n";
230 log_level = new_log_level;
239 static void streambuffdestructor(
void* v){
252 log_to_console =
true;
254 pthread_mutex_init(&mut, NULL);
255 pthread_key_create(&streambuffkey, streambuffdestructor);
264 pthread_mutex_destroy(&mut);
267 bool set_log_file(std::string file) {
275 if (file.length() > 0) {
276 fout.open(file.c_str());
277 if (fout.fail())
return false;
302 void textcolor(FILE* handle,
int attr,
int fg)
306 sprintf(command,
"%c[%d;%dm", 0x1B, attr, fg + 30);
307 fprintf(handle,
"%s", command);
310 void reset_color(FILE* handle)
314 sprintf(command,
"%c[0m", 0x1B);
315 fprintf(handle,
"%s", command);
320 void _log(
int lineloglevel,
const char* file,
const char*
function,
321 int line,
const char* fmt, va_list ap ){
323 if (lineloglevel >= 0 && lineloglevel <= 3 && lineloglevel >= log_level){
326 file = ((strrchr(file,
'/') ? : file- 1) + 1);
331 int byteswritten = snprintf(str,1024,
"%s%s(%s:%d): ",
332 messages[lineloglevel],file,
function,line);
335 byteswritten += vsnprintf(str + byteswritten,1024 - byteswritten,fmt,ap);
337 str[byteswritten] =
'\n';
338 str[byteswritten+1] = 0;
341 pthread_mutex_lock(&mut);
343 pthread_mutex_unlock(&mut);
345 if (log_to_console) {
348 textcolor(stderr, BRIGHT, RED);
351 textcolor(stderr, BRIGHT, RED);
354 textcolor(stderr, BRIGHT, GREEN);
367 void _logbuf(
int lineloglevel,
const char* file,
const char*
function,
368 int line,
const char* buf,
int len) {
370 if (lineloglevel >= 0 && lineloglevel <= 3 && lineloglevel >= log_level){
373 file = ((strrchr(file,
'/') ? : file- 1) + 1);
376 size_t headerlen = snprintf(NULL,0,
"%s%s(%s:%d): ",
377 messages[lineloglevel],file,
function,line);
379 if (headerlen> 2047) {
380 std::cerr <<
"Header length exceed buffer length!";
384 const char *newline=
"\n";
386 int byteswritten = snprintf(str,2047,
"%s%s(%s:%d): ",
387 messages[lineloglevel],file,
function,line);
388 _lograw(lineloglevel,str, byteswritten);
389 _lograw(lineloglevel,buf, len);
390 _lograw(lineloglevel,newline, (
int)strlen(newline));
395 void _lograw(
int lineloglevel,
const char* buf,
int len) {
397 pthread_mutex_lock(&mut);
399 pthread_mutex_unlock(&mut);
401 if (log_to_console) {
404 textcolor(stderr, BRIGHT, RED);
407 textcolor(stderr, BRIGHT, RED);
410 textcolor(stderr, BRIGHT, GREEN);
413 textcolor(stderr, BRIGHT, YELLOW);
417 std::cerr.write(buf,len);
424 file_logger& start_stream(
int lineloglevel,
const char* file,
const char*
function,
int line) {
427 pthread_getspecific(streambuffkey));
429 if (streambufentry == NULL) {
431 pthread_setspecific(streambuffkey, streambufentry);
433 std::stringstream& streambuffer = streambufentry->streambuffer;
434 bool& streamactive = streambufentry->streamactive;
436 file = ((strrchr(file,
'/') ? : file- 1) + 1);
438 if (lineloglevel >= log_level){
439 if (streambuffer.str().length() == 0) {
440 streambuffer << messages[lineloglevel] << file
441 <<
"(" <<
function <<
":" <<line<<
"): ";
444 streamloglevel = lineloglevel;
447 streamactive =
false;
454 void stream_flush() {
457 pthread_getspecific(streambuffkey));
458 if (streambufentry != NULL) {
459 std::stringstream& streambuffer = streambufentry->streambuffer;
461 streambuffer.flush();
462 _lograw(streamloglevel,
463 streambuffer.str().c_str(),
464 (int)(streambuffer.str().length()));
465 streambuffer.str(
"");
470 std::string log_file;
472 pthread_key_t streambuffkey;
488 template <
bool dostuff>
493 inline static void exec(
int loglevel,
const char* file,
const char*
function,
494 int line,
const char* fmt, ... ) {
497 global_logger()._log(loglevel, file,
function, line, fmt, argp);
504 inline static void exec(
int loglevel,
const char* file,
const char*
function,
505 int line,
const char* fmt, ... ) {}
517 template <
bool dostuff>
522 inline static file_logger& exec(
int lineloglevel,
const char* file,
const char*
function,
int line) {
523 return global_logger().start_stream(lineloglevel, file,
function, line);
529 inline static null_stream exec(
int lineloglevel,
const char* file,
const char*
function,
int line) {
534 void textcolor(FILE* handle,
int attr,
int fg);
535 void reset_color(FILE* handle);