39 #define LEVELS(L) L(NONE) L(FATAL) L(ERR) L(WARN) L(INFO) L(DEBUG) L(TRACE) L(TRACEALL)
40 #define DO_DESCRIPTION(e) #e,
50 static const std::array<const char* const, 8> buffer = {{LEVELS(DO_DESCRIPTION)}};
52 enum log_level { LEVELS(DO_ENUM) DBGTRACE = TRACEALL };
59 assert(logLevel >= NONE && logLevel <= TRACEALL);
60 std::array<const log_level, 8> m = {{NONE, FATAL, ERR, WARN, INFO, DEBUG, TRACE, TRACEALL}};
72 for(
auto i = 0U; i <= log_level::TRACEALL; ++i) {
73 if(strcmp(buf.c_str(), buffer[i]) == 0) {
88 template <
typename T>
class Log {
94 Log& operator=(
const Log&) =
delete;
118 os << std::setw(7) << std::left <<
to_string(level);
120 os <<
"[" << category <<
"]";
121 os <<
": " << std::internal;
123 get_last_log_level() = level;
132 static std::atomic<log_level> reportingLevel{WARN};
133 return reportingLevel;
147 static std::atomic<bool> flag{
false};
164 for(
unsigned int i = NONE; i <= TRACE; i++)
165 if(!strncasecmp(level.c_str(), (
const char*)(get_log_level_cstr() + i), strlen((
const char*)get_log_level_cstr() + i)))
167 Log<T>().Get(WARN) <<
"Unknown logging level '" << level <<
"'. Using INFO level as default.";
176 static std::atomic<bool> flag{
true};
185 static std::atomic<bool> flag{
true};
190 std::atomic<log_level>& get_last_log_level() {
191 static std::atomic<log_level> level{TRACE};
194 static const char*
const* get_log_level_cstr() {
return buffer.data(); };
195 std::ostringstream os;
208 static std::atomic<FILE*> pStream{stdout};
212 static std::atomic<std::ostream*>& ostream() {
213 static std::atomic<std::ostream*> oStream{
nullptr};
221 static void output(
const std::string& msg) {
222 static std::mutex mtx;
223 std::lock_guard<std::mutex> lock(mtx);
224 std::ostream* ostr = ostream();
230 fprintf(pStream,
"%s", msg.c_str());
238 constexpr
static char const* name =
"default";
241 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
242 #if defined(BUILDING_FILELOG_DLL)
243 #define FILELOG_DECLSPEC __declspec(dllexport)
244 #elif defined(USING_FILELOG_DLL)
245 #define FILELOG_DECLSPEC __declspec(dllimport)
247 #define FILELOG_DECLSPEC
250 #define FILELOG_DECLSPEC
253 #ifndef FILELOG_MAX_LEVEL
254 #define FILELOG_MAX_LEVEL ::logging::TRACE
257 #define _LOGGER(CATEGORY) ::logging::Log<::logging::Output2FILE<CATEGORY>>
258 #define LOGGER(CATEGORY) _LOGGER(::logging::CATEGORY)
259 #define _LOG_OUTPUT(CATEGORY) ::logging::Output2FILE<CATEGORY>
260 #define LOG_OUTPUT(CATEGORY) _LOG_OUTPUT(::logging::CATEGORY)
264 if(::logging::LEVEL <= LOGGER(DEFAULT)::get_reporting_level() && LOG_OUTPUT(DEFAULT)::stream()) \
265 LOGGER(DEFAULT)().get(::logging::LEVEL)
267 #define CPPLOG(LEVEL) \
268 if(::logging::LEVEL <= LOGGER(DEFAULT)::get_reporting_level() && LOG_OUTPUT(DEFAULT)::stream()) \
269 LOGGER(DEFAULT)().get(::logging::LEVEL)
271 #define NSCLOG(LEVEL, CATEGORY) \
272 if(::logging::LEVEL <= _LOGGER(CATEGORY)::get_reporting_level() && _LOG_OUTPUT(CATEGORY)::stream()) \
273 _LOGGER(CATEGORY)().get(::logging::LEVEL, CATEGORY::name)
274 #define CLOG(LEVEL, CATEGORY) NSCLOG(LEVEL, ::logging::CATEGORY)
278 const int MAX_LEN = 200;
279 char buffer[MAX_LEN];
280 if(GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0,
"HH':'mm':'ss", buffer, MAX_LEN) == 0)
281 return "Error in now_time()";
282 char result[100] = {0};
283 static DWORD first = GetTickCount();
284 std::sprintf(result,
"%s.%03ld", buffer, (
long)(GetTickCount() - first) % 1000);
289 static std::mutex mtx;
290 static std::array<char, 11> buffer;
291 static std::array<char, 100> result;
292 std::lock_guard<std::mutex> lck(mtx);
295 tm r{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
nullptr};
296 strftime(buffer.data(), buffer.size(),
"%X", localtime_r(&t, &r));
298 gettimeofday(&tv,
nullptr);
299 memset(result.data(), 100, 1);
300 sprintf(result.data(),
"%s.%03ld", buffer.data(), (
long)tv.tv_usec / 1000);
301 return result.data();
305 template <typename T> std::ostream& operator<<(std::ostream& stream, const std::vector<T>& vector) {
306 copy(vector.begin(), vector.end(), std::ostream_iterator<T>(stream,
","));
316 #define SCCASSERT(condition, message) \
319 logging::Logger().Get(logging::fatal) \
320 << "Assertion `" #condition "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
325 #define SCCASSERT(condition, message) \
330 #define SCCCHECK(condition, message) \
333 logging::Logger().Get(logging::fatal) \
334 << "Check of `" #condition "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \
static std::atomic< log_level > & reporting_level()
virtual ~Log()
the destructor
static std::string to_string(log_level level)
static std::atomic< bool > & print_time()
std::ostream & get(log_level level=INFO, const char *category="")
static log_level get_reporting_level()
static std::atomic< bool > & abort_on_fatal()
static std::atomic< bool > & print_severity()
static log_level from_string(const std::string &level)
static void output(const std::string &msg)
static std::atomic< FILE * > & stream()
log_level as_log_level(int logLevel)
log_level
enum defining the log levels
std::istream & operator>>(std::istream &is, log_level &val)
the default logging category