00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef GRAPHLAB_LOG_LOG_HPP
00038 #define GRAPHLAB_LOG_LOG_HPP
00039 #include <fstream>
00040 #include <sstream>
00041 #include <cstdlib>
00042 #include <cassert>
00043 #include <cstring>
00044 #include <cstdarg>
00045 #include <pthread.h>
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define LOG_NONE 5
00059 #define LOG_FATAL 4
00060 #define LOG_ERROR 3
00061 #define LOG_WARNING 2
00062 #define LOG_INFO 1
00063 #define LOG_DEBUG 0
00064
00065
00066
00067
00068
00069
00070
00071
00072 #ifndef OUTPUTLEVEL
00073 #define OUTPUTLEVEL LOG_DEBUG
00074 #endif
00075
00076 #define COLOROUTPUT
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 #if OUTPUTLEVEL == LOG_NONE
00088
00089 #define logger(lvl,fmt,...)
00090 #define logbuf(lvl,fmt,...)
00091 #define logstream
00092 #else
00093
00094 #define logger(lvl,fmt,...) \
00095 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl,__FILE__, __func__ ,__LINE__,fmt,##__VA_ARGS__))
00096
00097
00098 #define logbuf(lvl,buf,len) \
00099 (log_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl,__FILE__, \
00100 __func__ ,__LINE__,buf,len))
00101
00102 #define logstream(lvl) \
00103 (log_stream_dispatch<(lvl >= OUTPUTLEVEL)>::exec(lvl,__FILE__, __func__ ,__LINE__) )
00104 #endif
00105
00106 namespace logger_impl {
00107 struct streambuff_tls_entry {
00108 std::stringstream streambuffer;
00109 bool streamactive;
00110 };
00111 }
00112
00113
00114
00115 void __print_back_trace();
00116
00117
00118
00119
00120
00121 class file_logger{
00122 public:
00123
00124
00125
00126 file_logger();
00127
00128 ~file_logger();
00129
00130
00131
00132
00133
00134
00135
00136 bool set_log_file(std::string file);
00137
00138
00139 void set_log_to_console(bool consolelog) {
00140 log_to_console = consolelog;
00141 }
00142
00143
00144 std::string get_log_file(void) {
00145 return log_file;
00146 }
00147
00148
00149 bool get_log_to_console() {
00150 return log_to_console;
00151 }
00152
00153
00154 int get_log_level() {
00155 return log_level;
00156 }
00157
00158 file_logger& start_stream(int lineloglevel,const char* file,const char* function, int line);
00159
00160 template <typename T>
00161 file_logger& operator<<(T a) {
00162
00163 logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
00164 pthread_getspecific(streambuffkey));
00165 if (streambufentry != NULL) {
00166 std::stringstream& streambuffer = streambufentry->streambuffer;
00167 bool& streamactive = streambufentry->streamactive;
00168
00169 if (streamactive) streambuffer << a;
00170 }
00171 return *this;
00172 }
00173
00174 file_logger& operator<<(const char* a) {
00175
00176 logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
00177 pthread_getspecific(streambuffkey));
00178 if (streambufentry != NULL) {
00179 std::stringstream& streambuffer = streambufentry->streambuffer;
00180 bool& streamactive = streambufentry->streamactive;
00181
00182 if (streamactive) {
00183 streambuffer << a;
00184 if (a[strlen(a)-1] == '\n') {
00185 stream_flush();
00186 }
00187 }
00188 }
00189 return *this;
00190 }
00191
00192 file_logger& operator<<(std::ostream& (*f)(std::ostream&)){
00193
00194 logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
00195 pthread_getspecific(streambuffkey));
00196 if (streambufentry != NULL) {
00197 std::stringstream& streambuffer = streambufentry->streambuffer;
00198 bool& streamactive = streambufentry->streamactive;
00199
00200 typedef std::ostream& (*endltype)(std::ostream&);
00201 if (streamactive) {
00202 if (endltype(f) == endltype(std::endl)) {
00203 streambuffer << "\n";
00204 stream_flush();
00205 if(streamloglevel == LOG_FATAL) {
00206 __print_back_trace();
00207 throw "log fatal";
00208
00209 }
00210 }
00211 }
00212 }
00213 return *this;
00214 }
00215
00216
00217
00218
00219
00220 void set_log_level(int new_log_level) {
00221 log_level = new_log_level;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 void _log(int loglevel,const char* file,const char* function,
00236 int line,const char* fmt, va_list arg );
00237
00238
00239 void _logbuf(int loglevel,const char* file,const char* function,
00240 int line, const char* buf, int len);
00241
00242 void _lograw(int loglevel, const char* buf, int len);
00243
00244 void stream_flush() {
00245
00246 logger_impl::streambuff_tls_entry* streambufentry = reinterpret_cast<logger_impl::streambuff_tls_entry*>(
00247 pthread_getspecific(streambuffkey));
00248 if (streambufentry != NULL) {
00249 std::stringstream& streambuffer = streambufentry->streambuffer;
00250
00251 streambuffer.flush();
00252 _lograw(streamloglevel,
00253 streambuffer.str().c_str(),
00254 (int)(streambuffer.str().length()));
00255 streambuffer.str("");
00256 }
00257 }
00258 private:
00259 std::ofstream fout;
00260 std::string log_file;
00261
00262 pthread_key_t streambuffkey;
00263
00264 int streamloglevel;
00265 pthread_mutex_t mut;
00266
00267 bool log_to_console;
00268 int log_level;
00269
00270 };
00271
00272
00273 file_logger& global_logger();
00274
00275
00276
00277
00278 template <bool dostuff>
00279 struct log_dispatch {};
00280
00281 template <>
00282 struct log_dispatch<true> {
00283 inline static void exec(int loglevel,const char* file,const char* function,
00284 int line,const char* fmt, ... ) {
00285 va_list argp;
00286 va_start(argp, fmt);
00287 global_logger()._log(loglevel, file, function, line, fmt, argp);
00288 va_end(argp);
00289 }
00290 };
00291
00292 template <>
00293 struct log_dispatch<false> {
00294 inline static void exec(int loglevel,const char* file,const char* function,
00295 int line,const char* fmt, ... ) {}
00296 };
00297
00298
00299 struct null_stream {
00300 template<typename T>
00301 inline null_stream operator<<(T t) { return null_stream(); }
00302 inline null_stream operator<<(const char* a) { return null_stream(); }
00303 inline null_stream operator<<(std::ostream& (*f)(std::ostream&)) { return null_stream(); }
00304 };
00305
00306
00307 template <bool dostuff>
00308 struct log_stream_dispatch {};
00309
00310 template <>
00311 struct log_stream_dispatch<true> {
00312 inline static file_logger& exec(int lineloglevel,const char* file,const char* function, int line) {
00313 return global_logger().start_stream(lineloglevel, file, function, line);
00314 }
00315 };
00316
00317 template <>
00318 struct log_stream_dispatch<false> {
00319 inline static null_stream exec(int lineloglevel,const char* file,const char* function, int line) {
00320 return null_stream();
00321 }
00322 };
00323
00324 #include <graphlab/logger/assertions.hpp>
00325
00326 #endif
00327