00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __libutilxx__sella__util__Log_H__
00010 #define __libutilxx__sella__util__Log_H__
00011
00012 #include "../../common.h"
00013 #include "LogFormat.h"
00014 #include "SimpleLogFormat.h"
00015 #include "LogException.h"
00016 #include "../Exception.h"
00017
00018 #include <memory>
00019
00020 #include <syslog.h>
00021 #include <stdint.h>
00022 #include <pthread.h>
00023
00024 #include <vector>
00025 #include <list>
00026 #include <string>
00027 #include <unordered_set>
00028
00029 #ifndef LOG_INSTANCE
00030 #define LOG_INSTANCE (*libutilxx__log)
00031 #define AUTO_LOG_INSTANCE
00032 #endif
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #define TRACE(option, format, ...) ((LOG_INSTANCE).trace(option, __func__, __FILE__, __LINE__, format, ##__VA_ARGS__))
00045 #define LOG(facility, level, format, ...) ((LOG_INSTANCE).write(facility, level, __func__, __FILE__, __LINE__, format, ##__VA_ARGS__))
00046 #define LOG2(level, format, ...) ((LOG_INSTANCE).write(level, __func__, __FILE__, __LINE__, format, ##__VA_ARGS__))
00047 #define EXCEPTION(e, format, ...) ((LOG_INSTANCE).write(LOG_ALERT, __func__, __FILE__, __LINE__, e, format, ##__VA_ARGS__))
00048
00049 #define SET_TRACE(option) ((LOG_INSTANCE).setTraceOption(option, true))
00050 #define SET_TRACE2(option, on) ((LOG_INSTANCE).setTraceOption(option, on))
00051 #define UNSET_TRACE(option) ((LOG_INSTANCE).setTraceOption(option, false))
00052 #define IS_TRACE(option) ((LOG_INSTANCE).isTraceOption(option))
00053 #define HAS_TRACE() ((LOG_INSTANCE).hasTraceOptions()
00054 #define CLEAR_TRACE() ((LOG_INSTANCE).clearTraceOptions())
00055
00056 #define SET_IDENTIFIER(identifier) ((LOG_INSTANCE).setIdentifier(identifier))
00057 #define SET_FACILITY(facility) ((LOG_INSTANCE).setFacility(facility))
00058 #define SET_OPTION(option) ((LOG_INSTANCE).setOption(option))
00059 #define SET_FORMAT(format) ((LOG_INSTANCE).setFormat(format))
00060 #define SET_LOGMASK(mask) ((LOG_INSTANCE).setLogMask(mask))
00061 #define SET_LOGSIZE(size) ((LOG_INSTANCE).setLogSize(size))
00062
00063 #define DO_PRAGMA(x) _Pragma(#x)
00064
00065 #ifdef NDEBUG
00066 #define DEBUG_FLAG 0
00067 #define TODO(x)
00068 #define FIXME(x)
00069 #else
00070 #define DEBUG_FLAG 1
00071 #define TODO(x) DO_PRAGMA(message("TODO: " #x))
00072 #define FIXME(x) DO_PRAGMA(message("FIXME: " #x))
00073 #endif
00074
00075 #define HERE(x) do { if (DEBUG_FLAG) LOG2(LOG_INFO, "HERE: " #x); } while (0)
00076 #define MARK do { if (DEBUG_FLAG) LOG2(LOG_INFO, "MARK: %s() %s:%d", __func__, __FILE__, __LINE__); } while (0)
00077
00078 #define DTRACE(option, format, ...) do { if (DEBUG_FLAG) ((LOG_INSTANCE).trace(option, __func__, __FILE__, __LINE__, format, ##__VA_ARGS__)); } while (0)
00079
00080 #define DLOG(format, ...) do { if (DEBUG_FLAG) LOG2(LOG_DEBUG, format, ##__VA_ARGS__); } while (0)
00081 #define DLOG_IF(format, ...) do { if (DEBUG_FLAG) LOG2_IF(LOG_DEBUG, format, ##__VA_ARGS__); } while (0)
00082 #define DLOG_EVERY_N(cnt, format, ...) do { if (DEBUG_FLAG) LOG2_EVERY_N(cnt, LOG_DEBUG, format, ##__VA_ARGS__); } while (0)
00083 #define DLOG_IF_EVERY_N(cond, cnt, format, ...) do { if (DEBUG_FLAG) LOG2_IF_EVERY_N((cond), cnt, LOG_DEBUG, format, ##__VA_ARGS__); } while (0)
00084 #define DLOG_FIRST_N(cnt, format, ...) do { if (DEBUG_FLAG) LOG2_FIRST_N(cnt, LOG_DEBUG, format, ##__VA_ARGS__); } while (0)
00085 #define DLOG_IF_FIRST_N(cond, cnt, format, ...) do { if (DEBUG_FLAG) LOG2_IF_FIRST_N((cond), cnt, LOG_DEBUG, format, ##__VA_ARGS__); } while (0)
00086
00087 #define EMERGENCY(format, ...) LOG2(LOG_EMERG, format, ##__VA_ARGS__)
00088 #define ALERT(format, ...) LOG2(LOG_ALERT, format, ##__VA_ARGS__)
00089 #define CRITICAL(format, ...) LOG2(LOG_CRIT, format, ##__VA_ARGS__)
00090 #define ERROR(format, ...) LOG2(LOG_ERR, format, ##__VA_ARGS__)
00091 #define WARNING(format, ...) LOG2(LOG_WARNING, format, ##__VA_ARGS__)
00092 #define NOTICE(format, ...) LOG2(LOG_NOTICE, format, ##__VA_ARGS__)
00093 #define INFO(format, ...) LOG2(LOG_INFO, format, ##__VA_ARGS__)
00094 #define DEBUG(format, ...) LOG2(LOG_DEBUG, format, ##__VA_ARGS__)
00095
00096 #define EMERGENCY_IF(cond, format, ...) LOG2_IF((cond), LOG_EMERG, format, ##__VA_ARGS__)
00097 #define ALERT_IF(cond, format, ...) LOG2_IF((cond), LOG_ALERT, format, ##__VA_ARGS__)
00098 #define CRITICAL_IF(cond, format, ...) LOG2_IF((cond), LOG_CRIT, format, ##__VA_ARGS__)
00099 #define ERROR_IF(cond, format, ...) LOG2_IF((cond), LOG_ERR, format, ##__VA_ARGS__)
00100 #define WARNING_IF(cond, format, ...) LOG2_IF((cond), LOG_WARNING, format, ##__VA_ARGS__)
00101 #define NOTICE_IF(cond, format, ...) LOG2_IF((cond), LOG_NOTICE, format, ##__VA_ARGS__)
00102 #define INFO_IF(cond, format, ...) LOG2_IF((cond), LOG_INFO, format, ##__VA_ARGS__)
00103 #define DEBUG_IF(cond, format, ...) LOG2_IF((cond), LOG_DEBUG, format, ##__VA_ARGS__)
00104
00105 #define EMERGENCY_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_EMERG, format, ##__VA_ARGS__)
00106 #define ALERT_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_ALERT, format, ##__VA_ARGS__)
00107 #define CRITICAL_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_CRIT, format, ##__VA_ARGS__)
00108 #define ERROR_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_ERR, format, ##__VA_ARGS__)
00109 #define WARNING_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_WARNING, format, ##__VA_ARGS__)
00110 #define NOTICE_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_NOTICE, format, ##__VA_ARGS__)
00111 #define INFO_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_INFO, format, ##__VA_ARGS__)
00112 #define DEBUG_EVERY_N(cnt, format, ...) LOG2_EVERY_N(cnt, LOG_DEBUG, format, ##__VA_ARGS__)
00113
00114 #define EMERGENCY_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_EMERG, format, ##__VA_ARGS__)
00115 #define ALERT_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_ALERT, format, ##__VA_ARGS__)
00116 #define CRITICAL_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_CRIT, format, ##__VA_ARGS__)
00117 #define ERROR_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_ERR, format, ##__VA_ARGS__)
00118 #define WARNING_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_WARNING, format, ##__VA_ARGS__)
00119 #define NOTICE_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_NOTICE, format, ##__VA_ARGS__)
00120 #define INFO_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_INFO, format, ##__VA_ARGS__)
00121 #define DEBUG_IF_EVERY_N(cond, cnt, format, ...) LOG2_IF_EVERY_N((cond), cnt, LOG_DEBUG, format, ##__VA_ARGS__)
00122
00123 #define EMERGENCY_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_EMERG, format, ##__VA_ARGS__)
00124 #define ALERT_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_ALERT, format, ##__VA_ARGS__)
00125 #define CRITICAL_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_CRIT, format, ##__VA_ARGS__)
00126 #define ERROR_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_ERR, format, ##__VA_ARGS__)
00127 #define WARNING_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_WARNING, format, ##__VA_ARGS__)
00128 #define NOTICE_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_NOTICE, format, ##__VA_ARGS__)
00129 #define INFO_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_INFO, format, ##__VA_ARGS__)
00130 #define DEBUG_FIRST_N(cnt, format, ...) LOG2_FIRST_N(cnt, LOG_DEBUG, format, ##__VA_ARGS__)
00131
00132 #define EMERGENCY_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_EMERG, format, ##__VA_ARGS__)
00133 #define ALERT_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_ALERT, format, ##__VA_ARGS__)
00134 #define CRITICAL_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_CRIT, format, ##__VA_ARGS__)
00135 #define ERROR_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_ERR, format, ##__VA_ARGS__)
00136 #define WARNING_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_WARNING, format, ##__VA_ARGS__)
00137 #define NOTICE_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_NOTICE, format, ##__VA_ARGS__)
00138 #define INFO_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_INFO, format, ##__VA_ARGS__)
00139 #define DEBUG_IF_FIRST_N(cond, cnt, format, ...) LOG2_IF_FIRST_N((cond), cnt, LOG_DEBUG, format, ##__VA_ARGS__)
00140
00141 #define TRACE_IF(cond, option, format, ...) if (cond) { TRACE(option, format, ##__VA_ARGS__); }
00142
00143 #define LOG_IF(cond, facility, level, format, ...) if (cond) { LOG(facility, level, format, ##__VA_ARGS__); }
00144 #define LOG2_IF(cond, level, format, ...) if (cond) { LOG2(level, format, ##__VA_ARGS__); }
00145 #define LOG_EVERY_N(cnt, level, format, ...) if ((LOG_INSTANCE).incEveryN(cnt)) { LOG(level, format, ##__VA_ARGS__); }
00146 #define LOG2_EVERY_N(cnt, level, format, ...) if ((LOG_INSTANCE).incEveryN(cnt)) { LOG2(level, format, ##__VA_ARGS__); }
00147 #define LOG_IF_EVERY_N(cond, cnt, level, format, ...) if ((cond) && (LOG_INSTANCE).incEveryN(cnt)) { LOG(level, format, ##__VA_ARGS__); }
00148 #define LOG2_IF_EVERY_N(cond, cnt, level, format, ...) if ((cond) && (LOG_INSTANCE).incEveryN(cnt)) { LOG2(level, format, ##__VA_ARGS__); }
00149 #define LOG_FIRST_N(cnt, level, format, ...) if ((LOG_INSTANCE).incFirstN(cnt)) { LOG(level, format, ##__VA_ARGS__); }
00150 #define LOG2_FIRST_N(cnt, level, format, ...) if ((LOG_INSTANCE).incFirstN(cnt)) { LOG2(level, format, ##__VA_ARGS__); }
00151 #define LOG_IF_FIRST_N(cond, cnt, level, format, ...) if ((cond) && (LOG_INSTANCE).incFirstN(cnt)) { LOG(level, format, ##__VA_ARGS__); }
00152 #define LOG2_IF_FIRST_N(cond, cnt, level, format, ...) if ((cond) && (LOG_INSTANCE).incFirstN(cnt)) { LOG2(level, format, ##__VA_ARGS__); }
00153
00154 namespace sella {
00155 namespace util {
00156 class Log;
00157 }
00158 }
00159
00160 class sella::util::Log {
00161 public:
00162 typedef std::shared_ptr<Log> shared;
00163 typedef Log *ptr;
00164 typedef std::unordered_set<std::string> option_umap;
00165
00166 public:
00167 static const int FACILITY_AUTH = LOG_AUTH;
00168 static const int FACILITY_AUTHPRIV = LOG_AUTHPRIV;
00169 static const int FACILITY_CRON = LOG_CRON;
00170 static const int FACILITY_DAEMON = LOG_DAEMON;
00171 static const int FACILITY_FTP = LOG_FTP;
00172 static const int FACILITY_KERN = LOG_KERN;
00173 static const int FACILITY_LOCAL0 = LOG_LOCAL0;
00174 static const int FACILITY_LOCAL1 = LOG_LOCAL1;
00175 static const int FACILITY_LOCAL2 = LOG_LOCAL2;
00176 static const int FACILITY_LOCAL3 = LOG_LOCAL3;
00177 static const int FACILITY_LOCAL4 = LOG_LOCAL4;
00178 static const int FACILITY_LOCAL5 = LOG_LOCAL5;
00179 static const int FACILITY_LOCAL6 = LOG_LOCAL6;
00180 static const int FACILITY_LOCAL7 = LOG_LOCAL7;
00181 static const int FACILITY_LPR = LOG_LPR;
00182 static const int FACILITY_MAIL = LOG_MAIL;
00183 static const int FACILITY_NEWS = LOG_NEWS;
00184 static const int FACILITY_SYSLOG = LOG_SYSLOG;
00185 static const int FACILITY_USER = LOG_USER;
00186 static const int FACILITY_UUCP = LOG_UUCP;
00187
00188 static const int LEVEL_EMERGENCY = LOG_EMERG;
00189 static const int LEVEL_ALERT = LOG_ALERT;
00190 static const int LEVEL_CRITICAL = LOG_CRIT;
00191 static const int LEVEL_ERROR = LOG_ERR;
00192 static const int LEVEL_WARNING = LOG_WARNING;
00193 static const int LEVEL_NOTICE = LOG_NOTICE;
00194 static const int LEVEL_INFO = LOG_INFO;
00195 static const int LEVEL_DEBUG = LOG_DEBUG;
00196
00197 static const char* LABEL_EMERGENCY;
00198 static const char* LABEL_ALERT;
00199 static const char* LABEL_CRITICAL;
00200 static const char* LABEL_ERROR;
00201 static const char* LABEL_WARNING;
00202 static const char* LABEL_NOTICE;
00203 static const char* LABEL_INFO;
00204 static const char* LABEL_DEBUG;
00205
00206 static const int DefaultOption = (LOG_CONS|LOG_NDELAY|LOG_NOWAIT|LOG_PID);
00207 static const int WithStderrOption = (LOG_CONS|LOG_NDELAY|LOG_NOWAIT|LOG_PID|LOG_PERROR);
00208 static const int DefaultLogMask = LOG_UPTO(LOG_DEBUG);
00209 static const size_t DefaultLogSize = 1022;
00210
00211 public:
00212 static Log::shared& instance(const std::string &identifier = std::string());
00213
00214 public:
00215 Log(const std::string &identifier, int facility, int option = DefaultOption, int mask = DefaultLogMask, const LogFormat &format = SimpleLogFormat(), size_t size = DefaultLogSize) throw (LogException);
00216 Log(const std::string &file, const LogFormat &format = SimpleLogFormat(), size_t size = DefaultLogSize) throw (LogException);
00217
00218 Log(const Log &other) throw ();
00219 virtual ~Log() throw ();
00220
00221 static const Log::shared shared_ptr(const std::string &identifier, int facility, int option = DefaultOption, int mask = DefaultLogMask, const LogFormat &format = SimpleLogFormat(), size_t size = DefaultLogSize) throw (LogException);
00222 static const Log::shared shared_ptr(const std::string &file, const LogFormat &format = SimpleLogFormat(), size_t size = DefaultLogSize) throw (LogException);
00223 public:
00224 Log& operator=(const Log &other) throw ();
00225
00226 public:
00227 static const char* priority(int level) throw ();
00228
00229 void setIdentifier(const std::string &identifier = std::string()) throw ();
00230 void setFacility(int facility) throw ();
00231 void setOption(int option = DefaultOption) throw ();
00232 void setFormat(const LogFormat &format) throw ();
00233
00234 void setLogLevel(int level, bool on = true) throw ();
00235 int setLogMask(int mask) throw ();
00236 void setLogSize(size_t size = DefaultLogSize) throw ();
00237 int getLogMask(void) throw ();
00238 bool isLogMask(int level) throw ();
00239 size_t getLogSize(void) throw ();
00240
00241 void setTraceOption(const std::string &option, bool on = true) throw ();
00242 void setTraceOption(const std::vector<std::string> &options, bool on = true) throw ();
00243 void setTraceOption(const std::list<std::string> &options, bool on = true) throw ();
00244 void setTraceOptions(const std::vector<std::string> &options, bool on = true) throw ();
00245 void setTraceOptions(const std::list<std::string> &options, bool on = true) throw ();
00246 bool isTraceOption(const char *option) throw ();
00247 bool isTraceOption(const std::string &option) throw ();
00248 bool hasTraceOptions(void) throw ();
00249 void clearTraceOptions(void) throw ();
00250
00251 bool incEveryN(uint64_t n) throw ();
00252 bool incFirstN(uint64_t n) throw ();
00253 void resetEveryN(void) throw ();
00254
00255 bool trace(const char *option, const char *func, const char *file, int line, const char *format, ...) throw ();
00256 bool trace(std::string &option, const char *func, const char *file, int line, const char *format, ...) throw ();
00257 bool trace(const char *option, const char *func, const char *file, int line, const std::string &format, ...) throw ();
00258 bool trace(std::string &option, const char *func, const char *file, int line, const std::string &format, ...) throw ();
00259 bool write(int facility, int level, const char *func, const char *file, int line, const sella::Exception &e, const std::string &format, ...) throw ();
00260 bool write(int facility, int level, const char *func, const char *file, int line, const std::string &format, ...) throw ();
00261
00262 bool write(int level, const char *func, const char *file, int line, const sella::Exception &e) throw ();
00263 bool write(int level, const char *func, const char *file, int line, const sella::Exception &e, const std::string &format, ...) throw ();
00264 bool write(int level, const char *func, const char *file, int line, const std::string &format, ...) throw ();
00265
00266 bool write(int facility, int level, const char *func, const char *file, int line, const sella::Exception &e, const char *format, ...) throw ();
00267 bool write(int facility, int level, const char *func, const char *file, int line, const char *format, ...) throw ();
00268
00269 bool write(int level, const char *func, const char *file, int line, const sella::Exception &e, const char *format, ...) throw ();
00270 bool write(int level, const char *func, const char *file, int line, const char *format, ...) throw ();
00271
00272 private:
00273 uint64_t &references;
00274 uint64_t &everyN;
00275
00276 std::string identifier;
00277 int facility;
00278 int option;
00279
00280 LogFormat *format;
00281 bool syslog;
00282 int syslogMask;
00283 size_t size;
00284
00285 option_umap traceOptions;
00286 bool allTraceOptions;
00287
00288 pthread_mutex_t mutex;
00289
00290 inline void resize(std::string &text) throw ();
00291 };
00292
00293 #ifdef AUTO_LOG_INSTANCE
00294 extern sella::util::Log::shared libutilxx__log;
00295 #endif
00296
00297 #endif
00298
00299
00300
00301