181 lines
5.7 KiB
C++
181 lines
5.7 KiB
C++
/*
|
|
* Copyright (c) 2023, Alibaba Group Holding Limited;
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#pragma once
|
|
#include <functional>
|
|
#include <string_view>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "easylog/appender.hpp"
|
|
|
|
namespace easylog {
|
|
|
|
template <size_t Id = 0>
|
|
class logger {
|
|
public:
|
|
static logger<Id> &instance() {
|
|
static logger<Id> instance;
|
|
return instance;
|
|
}
|
|
|
|
void operator+=(record_t &record) { write(record); }
|
|
|
|
void write(record_t &record) {
|
|
if (async_ && appender_) {
|
|
append_record(std::move(record));
|
|
}
|
|
else {
|
|
append_format(record);
|
|
}
|
|
|
|
if (record.get_severity() == Severity::CRITICAL) {
|
|
flush();
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void flush() {
|
|
if (appender_) {
|
|
appender_->flush();
|
|
}
|
|
}
|
|
|
|
void init(Severity min_severity, bool async, bool enable_console,
|
|
const std::string &filename, size_t max_file_size, size_t max_files,
|
|
bool flush_every_time) {
|
|
static appender appender(filename, async, max_file_size, max_files,
|
|
flush_every_time);
|
|
async_ = async;
|
|
appender_ = &appender;
|
|
min_severity_ = min_severity;
|
|
enable_console_ = enable_console;
|
|
}
|
|
|
|
bool check_severity(Severity severity) { return severity >= min_severity_; }
|
|
|
|
void add_appender(std::function<void(std::string_view)> fn) {
|
|
appenders_.emplace_back(std::move(fn));
|
|
}
|
|
|
|
void stop_async_log() { appender_->stop(); }
|
|
|
|
private:
|
|
logger() {
|
|
static appender appender{};
|
|
appender_ = &appender;
|
|
}
|
|
|
|
logger(const logger &) = default;
|
|
|
|
void append_record(record_t record) { appender_->write(std::move(record)); }
|
|
|
|
void append_format(record_t &record) {
|
|
if (appender_) {
|
|
if (enable_console_) {
|
|
appender_->write_record<true, true>(record);
|
|
}
|
|
else {
|
|
appender_->write_record<true, false>(record);
|
|
}
|
|
}
|
|
}
|
|
|
|
Severity min_severity_;
|
|
bool async_ = false;
|
|
bool enable_console_ = true;
|
|
appender *appender_ = nullptr;
|
|
std::vector<std::function<void(std::string_view)>> appenders_;
|
|
};
|
|
|
|
template <size_t Id = 0>
|
|
inline void init_log(Severity min_severity, const std::string &filename = "",
|
|
bool async = true, bool enable_console = true,
|
|
size_t max_file_size = 0, size_t max_files = 0,
|
|
bool flush_every_time = false) {
|
|
logger<Id>::instance().init(min_severity, async, enable_console, filename,
|
|
max_file_size, max_files, flush_every_time);
|
|
}
|
|
|
|
template <size_t Id = 0>
|
|
inline void flush() {
|
|
logger<Id>::instance().flush();
|
|
}
|
|
|
|
template <size_t Id = 0>
|
|
inline void stop_async_log() {
|
|
logger<Id>::instance().stop_async_log();
|
|
}
|
|
|
|
template <size_t Id = 0>
|
|
inline void add_appender(std::function<void(std::string_view)> fn) {
|
|
logger<Id>::instance().add_appender(std::move(fn));
|
|
}
|
|
} // namespace easylog
|
|
|
|
#define ELOG_IMPL(severity, Id, ...) \
|
|
if (!easylog::logger<Id>::instance().check_severity(severity)) { \
|
|
; \
|
|
} \
|
|
else \
|
|
easylog::logger<Id>::instance() += \
|
|
easylog::record_t(std::chrono::system_clock::now(), severity, \
|
|
GET_STRING(__FILE__, __LINE__)) \
|
|
.ref()
|
|
|
|
#define ELOG(severity, ...) ELOG_IMPL(Severity::severity, __VA_ARGS__, 0)
|
|
|
|
#define ELOGV_IMPL(severity, Id, fmt, ...) \
|
|
if (!easylog::logger<Id>::instance().check_severity(severity)) { \
|
|
; \
|
|
} \
|
|
else { \
|
|
easylog::logger<Id>::instance() += \
|
|
easylog::record_t(std::chrono::system_clock::now(), severity, \
|
|
GET_STRING(__FILE__, __LINE__)) \
|
|
.sprintf(fmt, __VA_ARGS__); \
|
|
if (severity == Severity::CRITICAL) { \
|
|
easylog::flush<Id>(); \
|
|
std::exit(EXIT_FAILURE); \
|
|
} \
|
|
}
|
|
|
|
#define ELOGV(severity, ...) \
|
|
ELOGV_IMPL(Severity::severity, 0, __VA_ARGS__, "\n")
|
|
|
|
#define MELOGV(severity, Id, ...) \
|
|
ELOGV_IMPL(Severity::severity, Id, __VA_ARGS__, "\n")
|
|
|
|
#define ELOG_TRACE ELOG(INFO)
|
|
#define ELOG_DEBUG ELOG(DEBUG)
|
|
#define ELOG_INFO ELOG(INFO)
|
|
#define ELOG_WARN ELOG(WARN)
|
|
#define ELOG_ERROR ELOG(ERROR)
|
|
#define ELOG_CRITICAL ELOG(CRITICAL)
|
|
|
|
#define MELOG_TRACE(id) ELOG(INFO, id)
|
|
#define MELOG_DEBUG(id) ELOG(DEBUG, id)
|
|
#define MELOG_INFO(id) ELOG(INFO, id)
|
|
#define MELOG_WARN(id) ELOG(WARN, id)
|
|
#define MELOG_ERROR(id) ELOG(ERROR, id)
|
|
#define MELOG_CRITICAL(id) ELOG(CRITICAL, id)
|
|
|
|
#define ELOGT ELOG_TRACE
|
|
#define ELOGD ELOG_DEBUG
|
|
#define ELOGI ELOG_INFO
|
|
#define ELOGW ELOG_WARN
|
|
#define ELOGE ELOG_ERROR
|
|
#define ELOGC ELOG_CRITICAL
|