mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
398 lines
13 KiB
C++
398 lines
13 KiB
C++
#ifndef LOGGER_H
|
|
#define LOGGER_H
|
|
|
|
#include "core/math/date.h"
|
|
#include "log_stream.h"
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
class String;
|
|
|
|
class RLogger {
|
|
public:
|
|
static void log_trace(const String &str);
|
|
static void log_trace(const char *str);
|
|
|
|
static void log_message(const String &str);
|
|
static void log_message(const char *str);
|
|
|
|
static void log_warning(const String &str);
|
|
static void log_warning(const char *str);
|
|
|
|
static void log_error(const String &str);
|
|
static void log_error(const char *str);
|
|
|
|
static void _log_error(const char *p_function, const char *p_file, int p_line, const char *str);
|
|
static void _log_error(const char *p_function, const char *p_file, int p_line, const String &str);
|
|
static void _log_msg_error(const char *p_function, const char *p_file, int p_line, const char *p_msg, const char *str);
|
|
static void _log_index_error(const char *p_function, const char *p_file, int p_line, const int index, const int size, const char *str);
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @file Logger.h
|
|
* @author An Tao
|
|
*
|
|
* Public header file in trantor lib.
|
|
*
|
|
* Copyright 2018, An Tao. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the License file.
|
|
*
|
|
*
|
|
*/
|
|
|
|
namespace trantor {
|
|
/**
|
|
* @brief This class implements log functions.
|
|
*
|
|
*/
|
|
class Logger {
|
|
protected:
|
|
Logger(const Logger &) = delete;
|
|
Logger &operator=(const Logger &) = delete;
|
|
// some uncopyable classes maybe support move constructor....
|
|
Logger(Logger &&) noexcept(true) = default;
|
|
Logger &operator=(Logger &&) noexcept(true) = default;
|
|
|
|
public:
|
|
enum LogLevel {
|
|
kTrace = 0,
|
|
kDebug,
|
|
kInfo,
|
|
kWarn,
|
|
kError,
|
|
kFatal,
|
|
kNumberOfLogLevels
|
|
};
|
|
|
|
/**
|
|
* @brief Calculate of basename of source files in compile time.
|
|
*
|
|
*/
|
|
class SourceFile {
|
|
public:
|
|
template <int N>
|
|
inline SourceFile(const char (&arr)[N]) :
|
|
data_(arr), size_(N - 1) {
|
|
// std::cout<<data_<<std::endl;
|
|
const char *slash = strrchr(data_, '/'); // builtin function
|
|
if (slash) {
|
|
data_ = slash + 1;
|
|
size_ -= static_cast<int>(data_ - arr);
|
|
}
|
|
}
|
|
|
|
explicit SourceFile(const char *filename) :
|
|
data_(filename) {
|
|
const char *slash = strrchr(filename, '/');
|
|
if (slash) {
|
|
data_ = slash + 1;
|
|
}
|
|
size_ = static_cast<int>(strlen(data_));
|
|
}
|
|
|
|
const char *data_;
|
|
int size_;
|
|
};
|
|
Logger(SourceFile file, int line);
|
|
Logger(SourceFile file, int line, LogLevel level);
|
|
Logger(SourceFile file, int line, bool isSysErr);
|
|
Logger(SourceFile file, int line, LogLevel level, const char *func);
|
|
~Logger();
|
|
Logger &setIndex(int index) {
|
|
index_ = index;
|
|
return *this;
|
|
}
|
|
LogStream &stream();
|
|
|
|
/**
|
|
* @brief Set the output function.
|
|
*
|
|
* @param outputFunc The function to output a log message.
|
|
* @param flushFunc The function to flush.
|
|
* @note Logs are output to the standard output by default.
|
|
*/
|
|
static void setOutputFunction(
|
|
std::function<void(const char *msg, const uint64_t len)> outputFunc,
|
|
std::function<void()> flushFunc,
|
|
int index = -1) {
|
|
if (index < 0) {
|
|
outputFunc_() = outputFunc;
|
|
flushFunc_() = flushFunc;
|
|
} else {
|
|
outputFunc_(index) = outputFunc;
|
|
flushFunc_(index) = flushFunc;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Set the log level. Logs below the level are not printed.
|
|
*
|
|
* @param level
|
|
*/
|
|
static void setLogLevel(LogLevel level) {
|
|
logLevel_() = level;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the current log level.
|
|
*
|
|
* @return LogLevel
|
|
*/
|
|
static LogLevel logLevel() {
|
|
return logLevel_();
|
|
}
|
|
|
|
protected:
|
|
static void defaultOutputFunction(const char *msg, const uint64_t len) {
|
|
fwrite(msg, 1, len, stdout);
|
|
}
|
|
static void defaultFlushFunction() {
|
|
fflush(stdout);
|
|
}
|
|
void formatTime();
|
|
static LogLevel &logLevel_() {
|
|
#ifdef RELEASE
|
|
static LogLevel logLevel = LogLevel::kInfo;
|
|
#else
|
|
static LogLevel logLevel = LogLevel::kDebug;
|
|
#endif
|
|
return logLevel;
|
|
}
|
|
static std::function<void(const char *msg, const uint64_t len)>
|
|
&outputFunc_() {
|
|
static std::function<void(const char *msg, const uint64_t len)>
|
|
outputFunc = Logger::defaultOutputFunction;
|
|
return outputFunc;
|
|
}
|
|
static std::function<void()> &flushFunc_() {
|
|
static std::function<void()> flushFunc = Logger::defaultFlushFunction;
|
|
return flushFunc;
|
|
}
|
|
static std::function<void(const char *msg, const uint64_t len)>
|
|
&outputFunc_(size_t index) {
|
|
static std::vector<
|
|
std::function<void(const char *msg, const uint64_t len)> >
|
|
outputFuncs;
|
|
if (index < outputFuncs.size()) {
|
|
return outputFuncs[index];
|
|
}
|
|
while (index >= outputFuncs.size()) {
|
|
outputFuncs.emplace_back(outputFunc_());
|
|
}
|
|
return outputFuncs[index];
|
|
}
|
|
static std::function<void()> &flushFunc_(size_t index) {
|
|
static std::vector<std::function<void()> > flushFuncs;
|
|
if (index < flushFuncs.size()) {
|
|
return flushFuncs[index];
|
|
}
|
|
while (index >= flushFuncs.size()) {
|
|
flushFuncs.emplace_back(flushFunc_());
|
|
}
|
|
return flushFuncs[index];
|
|
}
|
|
friend class RawLogger;
|
|
LogStream logStream_;
|
|
Date date_{ Date::now() };
|
|
SourceFile sourceFile_;
|
|
int fileLine_;
|
|
LogLevel level_;
|
|
int index_{ -1 };
|
|
};
|
|
|
|
class RawLogger {
|
|
protected:
|
|
RawLogger(const RawLogger &) = delete;
|
|
RawLogger &operator=(const RawLogger &) = delete;
|
|
// some uncopyable classes maybe support move constructor....
|
|
RawLogger(RawLogger &&) noexcept(true) = default;
|
|
RawLogger &operator=(RawLogger &&) noexcept(true) = default;
|
|
|
|
public:
|
|
RawLogger() {}
|
|
~RawLogger();
|
|
RawLogger &setIndex(int index) {
|
|
index_ = index;
|
|
return *this;
|
|
}
|
|
LogStream &stream() {
|
|
return logStream_;
|
|
}
|
|
|
|
private:
|
|
LogStream logStream_;
|
|
int index_{ -1 };
|
|
};
|
|
|
|
|
|
#ifdef NDEBUG
|
|
#define LOG_TRACE \
|
|
if (0) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#else
|
|
#define LOG_TRACE \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kTrace) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#define LOG_TRACE_TO(index) \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kTrace) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.setIndex(index) \
|
|
.stream()
|
|
|
|
#endif
|
|
|
|
#define LOG_DEBUG \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
|
|
.stream()
|
|
#define LOG_DEBUG_TO(index) \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kDebug) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \
|
|
.setIndex(index) \
|
|
.stream()
|
|
#define LOG_INFO \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
|
|
trantor::Logger(__FILE__, __LINE__).stream()
|
|
#define LOG_INFO_TO(index) \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kInfo) \
|
|
trantor::Logger(__FILE__, __LINE__).setIndex(index).stream()
|
|
#define LOG_WARN \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream()
|
|
#define LOG_WARN_TO(index) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn) \
|
|
.setIndex(index) \
|
|
.stream()
|
|
#define LOG_ERROR \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream()
|
|
#define LOG_ERROR_TO(index) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError) \
|
|
.setIndex(index) \
|
|
.stream()
|
|
#define LOG_FATAL \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream()
|
|
#define LOG_FATAL_TO(index) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal) \
|
|
.setIndex(index) \
|
|
.stream()
|
|
#define LOG_SYSERR trantor::Logger(__FILE__, __LINE__, true).stream()
|
|
#define LOG_SYSERR_TO(index) \
|
|
trantor::Logger(__FILE__, __LINE__, true).setIndex(index).stream()
|
|
|
|
#define LOG_RAW trantor::RawLogger().stream()
|
|
#define LOG_RAW_TO(index) trantor::RawLogger().setIndex(index).stream()
|
|
|
|
#define LOG_TRACE_IF(cond) \
|
|
if ((trantor::Logger::logLevel() <= trantor::Logger::kTrace) && (cond)) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#define LOG_DEBUG_IF(cond) \
|
|
if ((Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) && (cond)) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \
|
|
.stream()
|
|
#define LOG_INFO_IF(cond) \
|
|
if ((Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) && (cond)) \
|
|
Tensor::Logger(__FILE__, __LINE__).stream()
|
|
#define LOG_WARN_IF(cond) \
|
|
if (cond) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream()
|
|
#define LOG_ERROR_IF(cond) \
|
|
if (cond) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream()
|
|
#define LOG_FATAL_IF(cond) \
|
|
if (cond) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream()
|
|
|
|
#ifdef NDEBUG
|
|
#define DLOG_TRACE \
|
|
if (0) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#define DLOG_DEBUG \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \
|
|
.stream()
|
|
#define DLOG_INFO \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__).stream()
|
|
#define DLOG_WARN \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream()
|
|
#define DLOG_ERROR \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream()
|
|
#define DLOG_FATAL \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream()
|
|
|
|
#define DLOG_TRACE_IF(cond) \
|
|
if (0) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#define DLOG_DEBUG_IF(cond) \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \
|
|
.stream()
|
|
#define DLOG_INFO_IF(cond) \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__).stream()
|
|
#define DLOG_WARN_IF(cond) \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream()
|
|
#define DLOG_ERROR_IF(cond) \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream()
|
|
#define DLOG_FATAL_IF(cond) \
|
|
if (0) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream()
|
|
#else
|
|
#define DLOG_TRACE \
|
|
if (trantor::Logger::logLevel() <= trantor::Logger::kTrace) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#define DLOG_DEBUG \
|
|
if (Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \
|
|
.stream()
|
|
#define DLOG_INFO \
|
|
if (Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) \
|
|
Tensor::Logger(__FILE__, __LINE__).stream()
|
|
#define DLOG_WARN \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream()
|
|
#define DLOG_ERROR \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream()
|
|
#define DLOG_FATAL \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream()
|
|
|
|
#define DLOG_TRACE_IF(cond) \
|
|
if ((trantor::Logger::logLevel() <= trantor::Logger::kTrace) && (cond)) \
|
|
trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \
|
|
.stream()
|
|
#define DLOG_DEBUG_IF(cond) \
|
|
if ((Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) && (cond)) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \
|
|
.stream()
|
|
#define DLOG_INFO_IF(cond) \
|
|
if ((Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) && (cond)) \
|
|
Tensor::Logger(__FILE__, __LINE__).stream()
|
|
#define DLOG_WARN_IF(cond) \
|
|
if (cond) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream()
|
|
#define DLOG_ERROR_IF(cond) \
|
|
if (cond) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream()
|
|
#define DLOG_FATAL_IF(cond) \
|
|
if (cond) \
|
|
Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream()
|
|
#endif
|
|
|
|
const char *strerror_tl(int savedErrno);
|
|
} // namespace trantor
|
|
|
|
#endif
|