update aixlog

This commit is contained in:
badaix 2017-08-23 22:21:38 +02:00
parent c3d1ded653
commit 0c3a881df0
5 changed files with 330 additions and 218 deletions

View file

@ -42,7 +42,7 @@ ifeq ($(TARGET), ANDROID)
CXX = $(PROGRAM_PREFIX)clang++ CXX = $(PROGRAM_PREFIX)clang++
STRIP = $(PROGRAM_PREFIX)strip STRIP = $(PROGRAM_PREFIX)strip
CXXFLAGS += -pthread -DANDROID -DNO_CPP11_STRING -fPIC -DHAS_TREMOR -DHAS_OPENSL -I$(NDK_DIR)/include CXXFLAGS += -pthread -DANDROID -DNO_CPP11_STRING -fPIC -DHAS_TREMOR -DHAS_OPENSL -I$(NDK_DIR)/include
LDFLAGS = -L$(NDK_DIR)/lib -pie -lvorbisidec -logg -lFLAC -lOpenSLES -latomic LDFLAGS = -L$(NDK_DIR)/lib -pie -lvorbisidec -logg -lFLAC -lOpenSLES -latomic -llog
OBJ += player/openslPlayer.o OBJ += player/openslPlayer.o
else ifeq ($(TARGET), OPENWRT) else ifeq ($(TARGET), OPENWRT)

View file

@ -117,7 +117,7 @@ int main (int argc, char **argv)
} }
catch (const std::invalid_argument& e) catch (const std::invalid_argument& e)
{ {
SLOG(LOG_ERR) << "Exception: " << e.what() << std::endl; cerr << "Exception: " << e.what() << std::endl;
cout << "\n" << op << "\n"; cout << "\n" << op << "\n";
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -155,10 +155,10 @@ int main (int argc, char **argv)
if (instance <= 0) if (instance <= 0)
std::invalid_argument("instance id must be >= 1"); std::invalid_argument("instance id must be >= 1");
Log::init( AixLog::Log::init(
{ {
make_shared<LogSinkCout>(debugSwitch.isSet()?(LogSeverity::trace):(LogSeverity::info), LogSink::Type::all, debugSwitch.isSet()?"%Y-%m-%d %H-%M-%S.#ms [#prio] (#tag)":"%Y-%m-%d %H-%M-%S [#prio]"), make_shared<AixLog::SinkCout>(debugSwitch.isSet()?(AixLog::Severity::trace):(AixLog::Severity::info), AixLog::Type::all, debugSwitch.isSet()?"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag)":"%Y-%m-%d %H-%M-%S [#severity]"),
make_shared<LogSinkNative>("snapclient", LogSeverity::trace, LogSink::Type::special) make_shared<AixLog::SinkNative>("snapclient", AixLog::Severity::trace, AixLog::Type::special)
} }
); );

View file

@ -3,37 +3,26 @@
/ _\ ( )( \/ )( ) / \ / __) / _\ ( )( \/ )( ) / \ / __)
/ \ )( ) ( / (_/\( O )( (_ \ / \ )( ) ( / (_/\( O )( (_ \
\_/\_/(__)(_/\_)\____/ \__/ \___/ \_/\_/(__)(_/\_)\____/ \__/ \___/
version 0.7.0 version 0.13.0
https://github.com/badaix/aixlog https://github.com/badaix/aixlog
This file is part of aixlog This file is part of aixlog
Copyright (C) 2017 Johannes Pohl Copyright (C) 2017 Johannes Pohl
This program is free software: you can redistribute it and/or modify This software may be modified and distributed under the terms
it under the terms of the GNU General Public License as published by of the MIT license. See the LICENSE file for details.
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/ ***/
/// inspired by "eater": /// inspired by "eater":
/// https://stackoverflow.com/questions/2638654/redirect-c-stdclog-to-syslog-on-unix /// https://stackoverflow.com/questions/2638654/redirect-c-stdclog-to-syslog-on-unix
/// TODO: add global log level
#ifndef AIX_LOG_HPP #ifndef AIX_LOG_HPP
#define AIX_LOG_HPP #define AIX_LOG_HPP
#ifndef _WIN32 #ifndef _WIN32
#define _HAS_SYSLOG_ #define _HAS_SYSLOG_ 1
#endif #endif
#include <algorithm> #include <algorithm>
@ -59,33 +48,28 @@
/// Internal helper defines /// Internal helper defines
#define LOG_WO_TAG(P) std::clog << (LogSeverity)P << Tag(__func__) << LogType::normal #define LOG_WO_TAG(P) std::clog << (AixLog::Severity)P
#define SLOG_WO_TAG(P) std::clog << (LogSeverity)P << Tag(__func__) << LogType::special #define LOG_TAG(P, T) std::clog << (AixLog::Severity)P << TAG(T)
#define LOG_TAG(P, T) std::clog << (LogSeverity)P << Tag(T) << LogType::normal #define ONE_COLOR(FG) AixLog::Color::FG
#define SLOG_TAG(P, T) std::clog << (LogSeverity)P << Tag(T) << LogType::special #define TWO_COLOR(FG, BG) AixLog::TextColor(AixLog::Color::FG, AixLog::Color::BG)
#define LOG_X(x,P,T,FUNC, ...) FUNC #define VAR_PARM(x,P,T,FUN, ...) FUN
#define SLOG_X(x,P,T,FUNC, ...) FUNC
/// External logger defines /// External logger defines
#define LOG(...) LOG_X(,##__VA_ARGS__, LOG_TAG(__VA_ARGS__), LOG_WO_TAG(__VA_ARGS__)) #define LOG(...) VAR_PARM(,##__VA_ARGS__, LOG_TAG(__VA_ARGS__), LOG_WO_TAG(__VA_ARGS__)) << TIMESTAMP << FUNC
#define SLOG(...) SLOG_X(,##__VA_ARGS__, SLOG_TAG(__VA_ARGS__), SLOG_WO_TAG(__VA_ARGS__)) #define SLOG(...) VAR_PARM(,##__VA_ARGS__, LOG_TAG(__VA_ARGS__), LOG_WO_TAG(__VA_ARGS__)) << TIMESTAMP << SPECIAL << FUNC
#define COLOR(...) VAR_PARM(,##__VA_ARGS__, TWO_COLOR(__VA_ARGS__), ONE_COLOR(__VA_ARGS__))
#define FUNC __func__ #define FUNC AixLog::Function(__func__, __FILE__, __LINE__)
#define TAG Tag #define TAG AixLog::Tag
#define COND Conditional #define COND AixLog::Conditional
#define SPECIAL AixLog::Type::special
#define TIMESTAMP AixLog::Timestamp(std::chrono::system_clock::now())
enum class LogType enum SEVERITY
{
normal,
special
};
enum Severity
{ {
// https://chromium.googlesource.com/chromium/mini_chromium/+/master/base/logging.cc // https://chromium.googlesource.com/chromium/mini_chromium/+/master/base/logging.cc
@ -113,7 +97,20 @@ enum Severity
}; };
enum class LogSeverity : std::int8_t
namespace AixLog
{
enum class Type
{
normal,
special,
all
};
enum class Severity : std::int8_t
{ {
trace = TRACE, trace = TRACE,
debug = DEBUG, debug = DEBUG,
@ -141,9 +138,9 @@ enum class Color
struct LogColor struct TextColor
{ {
LogColor(Color foreground = Color::none, Color background = Color::none) : TextColor(Color foreground = Color::none, Color background = Color::none) :
foreground(foreground), foreground(foreground),
background(background) background(background)
{ {
@ -181,9 +178,58 @@ private:
struct Timestamp
{
typedef std::chrono::time_point<std::chrono::system_clock> time_point_sys_clock;
Timestamp(std::nullptr_t) : is_null_(true)
{
}
Timestamp() : Timestamp(nullptr)
{
}
Timestamp(const time_point_sys_clock& time_point) : time_point(time_point), is_null_(false)
{
}
virtual explicit operator bool() const
{
return !is_null_;
}
/// strftime format + proprietary "#ms" for milliseconds
std::string to_string(const std::string& format = "%Y-%m-%d %H-%M-%S.#ms") const
{
std::time_t now_c = std::chrono::system_clock::to_time_t(time_point);
struct::tm now_tm = *std::localtime(&now_c);
char buffer[256];
strftime(buffer, sizeof buffer, format.c_str(), &now_tm);
std::string result = buffer;
size_t pos = result.find("#ms");
if (pos != std::string::npos)
{
int ms_part = std::chrono::time_point_cast<std::chrono::milliseconds>(time_point).time_since_epoch().count() % 1000;
char ms_str[4];
sprintf(ms_str, "%03d", ms_part);
result.replace(pos, 3, ms_str);
}
return result;
}
time_point_sys_clock time_point;
private:
bool is_null_;
};
struct Tag struct Tag
{ {
Tag(std::nullptr_t) : tag(""), is_null(true) Tag(std::nullptr_t) : text(""), is_null_(true)
{ {
} }
@ -191,54 +237,92 @@ struct Tag
{ {
} }
Tag(const std::string& tag) : tag(tag), is_null(false) Tag(const std::string& text) : text(text), is_null_(false)
{ {
} }
virtual explicit operator bool() const virtual explicit operator bool() const
{ {
return !is_null; return !is_null_;
} }
std::string tag; std::string text;
private: private:
bool is_null; bool is_null_;
}; };
typedef std::chrono::time_point<std::chrono::system_clock> time_point_sys_clock;
struct LogSink struct Function
{ {
enum class Type Function(const std::string& name, const std::string& file, size_t line) :
{ name(name), file(file), line(line), is_null_(false)
normal,
special,
all
};
LogSink(LogSeverity severity, Type type) : severity(severity), sink_type_(type)
{ {
} }
virtual ~LogSink() Function(std::nullptr_t) : name(""), file(""), line(0), is_null_(true)
{ {
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const = 0; Function() : Function(nullptr)
{
}
virtual explicit operator bool() const
{
return !is_null_;
}
std::string name;
std::string file;
size_t line;
private:
bool is_null_;
};
struct Metadata
{
Metadata() :
severity(Severity::trace), tag(nullptr), type(Type::normal), function(nullptr), timestamp(nullptr)
{
}
Severity severity;
Tag tag;
Type type;
Function function;
Timestamp timestamp;
};
struct Sink
{
Sink(Severity severity, Type type) : severity(severity), sink_type_(type)
{
}
virtual ~Sink()
{
}
virtual void log(const Metadata& metadata, const std::string& message) const = 0;
virtual Type get_type() const virtual Type get_type() const
{ {
return sink_type_; return sink_type_;
} }
virtual LogSink& set_type(Type sink_type) virtual Sink& set_type(Type sink_type)
{ {
sink_type_ = sink_type; sink_type_ = sink_type;
return *this; return *this;
} }
LogSeverity severity; Severity severity;
protected: protected:
Type sink_type_; Type sink_type_;
@ -246,12 +330,14 @@ protected:
static std::ostream& operator<< (std::ostream& os, const LogSeverity& log_severity); static std::ostream& operator<< (std::ostream& os, const Severity& log_severity);
static std::ostream& operator<< (std::ostream& os, const LogType& log_type); static std::ostream& operator<< (std::ostream& os, const Type& log_type);
static std::ostream& operator<< (std::ostream& os, const Timestamp& timestamp);
static std::ostream& operator<< (std::ostream& os, const Tag& tag); static std::ostream& operator<< (std::ostream& os, const Tag& tag);
static std::ostream& operator<< (std::ostream& os, const Function& function);
static std::ostream& operator<< (std::ostream& os, const Conditional& conditional); static std::ostream& operator<< (std::ostream& os, const Conditional& conditional);
typedef std::shared_ptr<LogSink> log_sink_ptr; typedef std::shared_ptr<Sink> log_sink_ptr;
class Log : public std::basic_streambuf<char, std::char_traits<char> > class Log : public std::basic_streambuf<char, std::char_traits<char> >
@ -266,6 +352,8 @@ public:
/// Without "init" every LOG(X) will simply go to clog /// Without "init" every LOG(X) will simply go to clog
static void init(const std::vector<log_sink_ptr> log_sinks = {}) static void init(const std::vector<log_sink_ptr> log_sinks = {})
{ {
Log::instance().log_sinks_.clear();
for (auto sink: log_sinks) for (auto sink: log_sinks)
Log::instance().add_logsink(sink); Log::instance().add_logsink(sink);
@ -274,31 +362,31 @@ public:
void add_logsink(log_sink_ptr sink) void add_logsink(log_sink_ptr sink)
{ {
logSinks.push_back(sink); log_sinks_.push_back(sink);
} }
void remove_logsink(log_sink_ptr sink) void remove_logsink(log_sink_ptr sink)
{ {
logSinks.erase(std::remove(logSinks.begin(), logSinks.end(), sink), logSinks.end()); log_sinks_.erase(std::remove(log_sinks_.begin(), log_sinks_.end(), sink), log_sinks_.end());
} }
static std::string toString(LogSeverity logSeverity) static std::string to_string(Severity logSeverity)
{ {
switch (logSeverity) switch (logSeverity)
{ {
case LogSeverity::trace: case Severity::trace:
return "Trace"; return "Trace";
case LogSeverity::debug: case Severity::debug:
return "Debug"; return "Debug";
case LogSeverity::info: case Severity::info:
return "Info"; return "Info";
case LogSeverity::notice: case Severity::notice:
return "Notice"; return "Notice";
case LogSeverity::warning: case Severity::warning:
return "Warn"; return "Warn";
case LogSeverity::error: case Severity::error:
return "Err"; return "Err";
case LogSeverity::fatal: case Severity::fatal:
return "Fatal"; return "Fatal";
default: default:
std::stringstream ss; std::stringstream ss;
@ -309,7 +397,7 @@ public:
protected: protected:
Log() : type_(LogType::normal) Log()
{ {
} }
@ -317,25 +405,27 @@ protected:
{ {
if (!buffer_.str().empty()) if (!buffer_.str().empty())
{ {
auto now = std::chrono::system_clock::now();
if (conditional_.is_true()) if (conditional_.is_true())
{ {
for (const auto sink: logSinks) for (const auto sink: log_sinks_)
{ {
if ( if (
(sink->get_type() == LogSink::Type::all) || (metadata_.type == Type::all) ||
((type_ == LogType::special) && (sink->get_type() == LogSink::Type::special)) || (sink->get_type() == Type::all) ||
((type_ == LogType::normal) && (sink->get_type() == LogSink::Type::normal)) ((metadata_.type == Type::special) && (sink->get_type() == Type::special)) ||
((metadata_.type == Type::normal) && (sink->get_type() == Type::normal))
) )
if (severity_ >= sink->severity) if (metadata_.severity >= sink->severity)
sink->log(now, severity_, type_, tag_, buffer_.str()); sink->log(metadata_, buffer_.str());
} }
} }
buffer_.str(""); buffer_.str("");
buffer_.clear(); buffer_.clear();
//severity_ = debug; // default to debug for each message metadata_.severity = Severity::trace;
//type_ = kNormal; metadata_.type = Type::normal;
tag_ = nullptr; metadata_.timestamp = nullptr;
metadata_.tag = nullptr;
metadata_.function = nullptr;
conditional_.set(true); conditional_.set(true);
} }
return 0; return 0;
@ -357,7 +447,6 @@ protected:
} }
else else
{ {
std::cout << "EOF\n";
sync(); sync();
} }
return c; return c;
@ -365,25 +454,25 @@ protected:
private: private:
friend std::ostream& operator<< (std::ostream& os, const LogSeverity& log_severity); friend std::ostream& operator<< (std::ostream& os, const Severity& log_severity);
friend std::ostream& operator<< (std::ostream& os, const LogType& log_type); friend std::ostream& operator<< (std::ostream& os, const Type& log_type);
friend std::ostream& operator<< (std::ostream& os, const Timestamp& timestamp);
friend std::ostream& operator<< (std::ostream& os, const Tag& tag); friend std::ostream& operator<< (std::ostream& os, const Tag& tag);
friend std::ostream& operator<< (std::ostream& os, const Function& function);
friend std::ostream& operator<< (std::ostream& os, const Conditional& conditional); friend std::ostream& operator<< (std::ostream& os, const Conditional& conditional);
std::stringstream buffer_; std::stringstream buffer_;
LogSeverity severity_; Metadata metadata_;
LogType type_;
Tag tag_;
Conditional conditional_; Conditional conditional_;
std::vector<log_sink_ptr> logSinks; std::vector<log_sink_ptr> log_sinks_;
}; };
struct LogSinkFormat : public LogSink struct SinkFormat : public Sink
{ {
LogSinkFormat(LogSeverity severity, Type type, const std::string& format = "%Y-%m-%d %H-%M-%S [#prio] (#tag)") : // #logline") : SinkFormat(Severity severity, Type type, const std::string& format = "%Y-%m-%d %H-%M-%S [#severity] (#tag)") :
LogSink(severity, type), Sink(severity, type),
format_(format) format_(format)
{ {
} }
@ -393,38 +482,29 @@ struct LogSinkFormat : public LogSink
format_ = format; format_ = format;
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const = 0; virtual void log(const Metadata& metadata, const std::string& message) const = 0;
protected: protected:
/// strftime format + proprietary "#ms" for milliseconds virtual void do_log(std::ostream& stream, const Metadata& metadata, const std::string& message) const
virtual void do_log(std::ostream& stream, const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const
{ {
std::time_t now_c = std::chrono::system_clock::to_time_t(timestamp); std::string result = format_;
struct::tm now_tm = *std::localtime(&now_c); if (metadata.timestamp)
result = metadata.timestamp.to_string(result);
char buffer[256]; size_t pos = result.find("#severity");
strftime(buffer, sizeof buffer, format_.c_str(), &now_tm);
std::string result = buffer;
size_t pos = result.find("#ms");
if (pos != std::string::npos) if (pos != std::string::npos)
{ result.replace(pos, 9, Log::to_string(metadata.severity));
int ms_part = std::chrono::time_point_cast<std::chrono::milliseconds>(timestamp).time_since_epoch().count() % 1000;
char ms_str[4];
sprintf(ms_str, "%03d", ms_part);
result.replace(pos, 3, ms_str);
}
pos = result.find("#prio");
if (pos != std::string::npos)
result.replace(pos, 5, Log::toString(severity));
pos = result.find("#tag"); pos = result.find("#tag");
if (pos != std::string::npos) if (pos != std::string::npos)
result.replace(pos, 4, tag?tag.tag:"log"); result.replace(pos, 4, metadata.tag?metadata.tag.text:(metadata.function?metadata.function.name:"log"));
pos = result.find("#logline"); pos = result.find("#function");
if (pos != std::string::npos)
result.replace(pos, 9, metadata.function?metadata.function.name:"");
pos = result.find("#message");
if (pos != std::string::npos) if (pos != std::string::npos)
{ {
result.replace(pos, 8, message); result.replace(pos, 8, message);
@ -444,46 +524,46 @@ protected:
struct LogSinkCout : public LogSinkFormat struct SinkCout : public SinkFormat
{ {
LogSinkCout(LogSeverity severity, Type type, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#prio] (#tag)") : // #logline") : SinkCout(Severity severity, Type type, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag)") :
LogSinkFormat(severity, type, format) SinkFormat(severity, type, format)
{ {
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
if (severity >= this->severity) if (severity >= this->severity)
do_log(std::cout, timestamp, severity, type, tag, message); do_log(std::cout, metadata, message);
} }
}; };
struct LogSinkCerr : public LogSinkFormat struct SinkCerr : public SinkFormat
{ {
LogSinkCerr(LogSeverity severity, Type type, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#prio] (#tag)") : // #logline") : SinkCerr(Severity severity, Type type, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag)") :
LogSinkFormat(severity, type, format) SinkFormat(severity, type, format)
{ {
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
if (severity >= this->severity) if (severity >= this->severity)
do_log(std::cerr, timestamp, severity, type, tag, message); do_log(std::cerr, metadata, message);
} }
}; };
/// Not tested due to unavailability of Windows /// Not tested due to unavailability of Windows
struct LogSinkOutputDebugString : LogSink struct SinkOutputDebugString : Sink
{ {
LogSinkOutputDebugString(LogSeverity severity, Type type = Type::all, const std::string& default_tag = "") : LogSink(severity, type) SinkOutputDebugString(Severity severity, Type type = Type::all, const std::string& default_tag = "") : Sink(severity, type)
{ {
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
#ifdef _WIN32 #ifdef _WIN32
OutputDebugString(message.c_str()); OutputDebugString(message.c_str());
@ -493,29 +573,29 @@ struct LogSinkOutputDebugString : LogSink
struct LogSinkUnifiedLogging : LogSink struct SinkUnifiedLogging : Sink
{ {
LogSinkUnifiedLogging(LogSeverity severity, Type type = Type::all) : LogSink(severity, type) SinkUnifiedLogging(Severity severity, Type type = Type::all) : Sink(severity, type)
{ {
} }
#ifdef __APPLE__ #ifdef __APPLE__
os_log_type_t get_os_log_type(LogSeverity severity) const os_log_type_t get_os_log_type(Severity severity) const
{ {
// https://developer.apple.com/documentation/os/os_log_type_t?language=objc // https://developer.apple.com/documentation/os/os_log_type_t?language=objc
switch (severity) switch (severity)
{ {
case LogSeverity::trace: case Severity::trace:
case LogSeverity::debug: case Severity::debug:
return OS_LOG_TYPE_DEBUG; return OS_LOG_TYPE_DEBUG;
case LogSeverity::info: case Severity::info:
case LogSeverity::notice: case Severity::notice:
return OS_LOG_TYPE_INFO; return OS_LOG_TYPE_INFO;
case LogSeverity::warning: case Severity::warning:
return OS_LOG_TYPE_DEFAULT; return OS_LOG_TYPE_DEFAULT;
case LogSeverity::error: case Severity::error:
return OS_LOG_TYPE_ERROR; return OS_LOG_TYPE_ERROR;
case LogSeverity::fatal: case Severity::fatal:
return OS_LOG_TYPE_FAULT; return OS_LOG_TYPE_FAULT;
default: default:
return OS_LOG_TYPE_DEFAULT; return OS_LOG_TYPE_DEFAULT;
@ -523,48 +603,50 @@ struct LogSinkUnifiedLogging : LogSink
} }
#endif #endif
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
#ifdef __APPLE__ #ifdef __APPLE__
os_log_with_type(OS_LOG_DEFAULT, get_os_log_type(severity), "%{public}s", message.c_str()); os_log_with_type(OS_LOG_DEFAULT, get_os_log_type(metadata.severity), "%{public}s", message.c_str());
#endif #endif
} }
}; };
struct LogSinkSyslog : public LogSink struct SinkSyslog : public Sink
{ {
LogSinkSyslog(const char* ident, LogSeverity severity, Type type) : LogSink(severity, type) SinkSyslog(const char* ident, Severity severity, Type type) : Sink(severity, type)
{ {
#ifdef _HAS_SYSLOG_ #ifdef _HAS_SYSLOG_
openlog(ident, LOG_PID, LOG_USER); openlog(ident, LOG_PID, LOG_USER);
#endif #endif
} }
virtual ~LogSinkSyslog() virtual ~SinkSyslog()
{ {
#ifdef _HAS_SYSLOG_
closelog(); closelog();
#endif
} }
#ifdef _HAS_SYSLOG_ #ifdef _HAS_SYSLOG_
int get_syslog_priority(LogSeverity severity) const int get_syslog_priority(Severity severity) const
{ {
// http://unix.superglobalmegacorp.com/Net2/newsrc/sys/syslog.h.html // http://unix.superglobalmegacorp.com/Net2/newsrc/sys/syslog.h.html
switch (severity) switch (severity)
{ {
case LogSeverity::trace: case Severity::trace:
case LogSeverity::debug: case Severity::debug:
return LOG_DEBUG; return LOG_DEBUG;
case LogSeverity::info: case Severity::info:
return LOG_INFO; return LOG_INFO;
case LogSeverity::notice: case Severity::notice:
return LOG_NOTICE; return LOG_NOTICE;
case LogSeverity::warning: case Severity::warning:
return LOG_WARNING; return LOG_WARNING;
case LogSeverity::error: case Severity::error:
return LOG_ERR; return LOG_ERR;
case LogSeverity::fatal: case Severity::fatal:
return LOG_CRIT; return LOG_CRIT;
default: default:
return LOG_INFO; return LOG_INFO;
@ -573,40 +655,40 @@ struct LogSinkSyslog : public LogSink
#endif #endif
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
#ifdef _HAS_SYSLOG_ #ifdef _HAS_SYSLOG_
syslog(get_syslog_priority(severity), "%s", message.c_str()); syslog(get_syslog_priority(metadata.severity), "%s", message.c_str());
#endif #endif
} }
}; };
struct LogSinkAndroid : public LogSink struct SinkAndroid : public Sink
{ {
LogSinkAndroid(const std::string& ident, LogSeverity severity, Type type = Type::all) : LogSink(severity, type), ident_(ident) SinkAndroid(const std::string& ident, Severity severity, Type type = Type::all) : Sink(severity, type), ident_(ident)
{ {
} }
#ifdef __ANDROID__ #ifdef __ANDROID__
android_LogSeverity get_android_prio(LogSeverity severity) const android_LogPriority get_android_prio(Severity severity) const
{ {
// https://developer.android.com/ndk/reference/log_8h.html // https://developer.android.com/ndk/reference/log_8h.html
switch (severity) switch (severity)
{ {
case LogSeverity::trace: case Severity::trace:
return ANDROID_LOG_VERBOSE; return ANDROID_LOG_VERBOSE;
case LogSeverity::debug: case Severity::debug:
return ANDROID_LOG_DEBUG; return ANDROID_LOG_DEBUG;
case LogSeverity::info: case Severity::info:
case LogSeverity::notice: case Severity::notice:
return ANDROID_LOG_INFO; return ANDROID_LOG_INFO;
case LogSeverity::warning: case Severity::warning:
return ANDROID_LOG_WARN; return ANDROID_LOG_WARN;
case LogSeverity::error: case Severity::error:
return ANDROID_LOG_ERROR; return ANDROID_LOG_ERROR;
case LogSeverity::fatal: case Severity::fatal:
return ANDROID_LOG_FATAL; return ANDROID_LOG_FATAL;
default: default:
return ANDROID_LOG_UNKNOWN; return ANDROID_LOG_UNKNOWN;
@ -614,21 +696,21 @@ struct LogSinkAndroid : public LogSink
} }
#endif #endif
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
#ifdef __ANDROID__ #ifdef __ANDROID__
std::string log_tag;// = default_tag_; std::string tag = metadata.tag?metadata.tag.text:(metadata.function?metadata.function.name:"");
if (tag) std::string log_tag;
{ if (!ident_.empty() && !tag.empty())
if (!ident_.empty()) log_tag = ident_ + "." + tag;
log_tag = ident_ + "." + tag.tag; else if (!ident_.empty())
else
log_tag = tag.tag;
}
else
log_tag = ident_; log_tag = ident_;
else if (!tag.empty())
log_tag = tag;
else
log_tag = "log";
__android_log_write(get_android_prio(severity), log_tag.c_str(), message.c_str()); __android_log_write(get_android_prio(metadata.severity), log_tag.c_str(), message.c_str());
#endif #endif
} }
@ -639,9 +721,9 @@ protected:
/// Not tested due to unavailability of Windows /// Not tested due to unavailability of Windows
struct LogSinkEventLog : public LogSink struct SinkEventLog : public Sink
{ {
LogSinkEventLog(const std::string& ident, LogSeverity severity, Type type = Type::all) : LogSink(severity, type) SinkEventLog(const std::string& ident, Severity severity, Type type = Type::all) : Sink(severity, type)
{ {
#ifdef _WIN32 #ifdef _WIN32
event_log = RegisterEventSource(NULL, ident.c_str()); event_log = RegisterEventSource(NULL, ident.c_str());
@ -649,21 +731,21 @@ struct LogSinkEventLog : public LogSink
} }
#ifdef _WIN32 #ifdef _WIN32
WORD get_type(LogSeverity severity) const WORD get_type(Severity severity) const
{ {
// https://msdn.microsoft.com/de-de/library/windows/desktop/aa363679(v=vs.85).aspx // https://msdn.microsoft.com/de-de/library/windows/desktop/aa363679(v=vs.85).aspx
switch (severity) switch (severity)
{ {
case LogSeverity::trace: case Severity::trace:
case LogSeverity::debug: case Severity::debug:
return EVENTLOG_INFORMATION_TYPE; return EVENTLOG_INFORMATION_TYPE;
case LogSeverity::info: case Severity::info:
case LogSeverity::notice: case Severity::notice:
return EVENTLOG_SUCCESS; return EVENTLOG_SUCCESS;
case LogSeverity::warning: case Severity::warning:
return EVENTLOG_WARNING_TYPE; return EVENTLOG_WARNING_TYPE;
case LogSeverity::error: case Severity::error:
case LogSeverity::fatal: case Severity::fatal:
return EVENTLOG_ERROR_TYPE; return EVENTLOG_ERROR_TYPE;
default: default:
return EVENTLOG_INFORMATION_TYPE; return EVENTLOG_INFORMATION_TYPE;
@ -671,10 +753,10 @@ struct LogSinkEventLog : public LogSink
} }
#endif #endif
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
#ifdef _WIN32 #ifdef _WIN32
ReportEvent(event_log, get_type(severity), 0, 0, NULL, 1, 0, &message.c_str(), NULL); ReportEvent(event_log, get_type(metadata.severity), 0, 0, NULL, 1, 0, &message.c_str(), NULL);
#endif #endif
} }
@ -686,28 +768,36 @@ protected:
struct LogSinkNative : public LogSink struct SinkNative : public Sink
{ {
LogSinkNative(const std::string& ident, LogSeverity severity, Type type = Type::all) : SinkNative(const std::string& ident, Severity severity, Type type = Type::all) :
LogSink(severity, type), Sink(severity, type),
log_sink_(nullptr), log_sink_(nullptr),
ident_(ident) ident_(ident)
{ {
#ifdef __ANDROID__ #ifdef __ANDROID__
log_sink_ = std::make_shared<LogSinkAndroid>(ident_, severity, type); log_sink_ = std::make_shared<SinkAndroid>(ident_, severity, type);
#elif __APPLE__ #elif __APPLE__
log_sink_ = std::make_shared<LogSinkUnifiedLogging>(severity, type); log_sink_ = std::make_shared<SinkUnifiedLogging>(severity, type);
#elif _WIN32 #elif _WIN32
log_sink_ = std::make_shared<LogSinkEventLog>(severity, type); log_sink_ = std::make_shared<SinkEventLog>(severity, type);
#elif _HAS_SYSLOG_
log_sink_ = std::make_shared<SinkSyslog>(ident_.c_str(), severity, type);
#else #else
log_sink_ = std::make_shared<LogSinkSyslog>(ident_.c_str(), severity, type); /// will not throw or something. Use "get_logger()" to check for success
log_sink_ = nullptr;
#endif #endif
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual log_sink_ptr get_logger()
{
return log_sink_;
}
virtual void log(const Metadata& metadata, const std::string& message) const
{ {
if (log_sink_) if (log_sink_)
log_sink_->log(timestamp, severity, type, tag, message); log_sink_->log(metadata, message);
} }
protected: protected:
@ -717,44 +807,54 @@ protected:
struct LogSinkCallback : public LogSink struct SinkCallback : public Sink
{ {
typedef std::function<void(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message)> callback_fun; typedef std::function<void(const Metadata& metadata, const std::string& message)> callback_fun;
LogSinkCallback(LogSeverity severity, Type type, callback_fun callback) : LogSink(severity, type), callback(callback) SinkCallback(Severity severity, Type type, callback_fun callback) : Sink(severity, type), callback_(callback)
{ {
} }
virtual void log(const time_point_sys_clock& timestamp, LogSeverity severity, LogType type, const Tag& tag, const std::string& message) const virtual void log(const Metadata& metadata, const std::string& message) const
{ {
if (callback && (severity >= this->severity)) if (callback_ && (severity >= this->severity))
callback(timestamp, severity, type, tag, message); callback_(metadata, message);
} }
private: private:
callback_fun callback; callback_fun callback_;
}; };
static std::ostream& operator<< (std::ostream& os, const LogSeverity& log_severity) static std::ostream& operator<< (std::ostream& os, const Severity& log_severity)
{ {
Log* log = dynamic_cast<Log*>(os.rdbuf()); Log* log = dynamic_cast<Log*>(os.rdbuf());
if (log && (log->severity_ != log_severity)) if (log && (log->metadata_.severity != log_severity))
{ {
log->sync(); log->sync();
log->severity_ = log_severity; log->metadata_.severity = log_severity;
} }
return os; return os;
} }
static std::ostream& operator<< (std::ostream& os, const LogType& log_type) static std::ostream& operator<< (std::ostream& os, const Type& log_type)
{ {
Log* log = dynamic_cast<Log*>(os.rdbuf()); Log* log = dynamic_cast<Log*>(os.rdbuf());
if (log) if (log)
log->type_ = log_type; log->metadata_.type = log_type;
return os;
}
static std::ostream& operator<< (std::ostream& os, const Timestamp& timestamp)
{
Log* log = dynamic_cast<Log*>(os.rdbuf());
if (log)
log->metadata_.timestamp = timestamp;
return os; return os;
} }
@ -764,7 +864,17 @@ static std::ostream& operator<< (std::ostream& os, const Tag& tag)
{ {
Log* log = dynamic_cast<Log*>(os.rdbuf()); Log* log = dynamic_cast<Log*>(os.rdbuf());
if (log) if (log)
log->tag_ = tag; log->metadata_.tag = tag;
return os;
}
static std::ostream& operator<< (std::ostream& os, const Function& function)
{
Log* log = dynamic_cast<Log*>(os.rdbuf());
if (log)
log->metadata_.function = function;
return os; return os;
} }
@ -780,7 +890,7 @@ static std::ostream& operator<< (std::ostream& os, const Conditional& conditiona
static std::ostream& operator<< (std::ostream& os, const LogColor& log_color) static std::ostream& operator<< (std::ostream& os, const TextColor& log_color)
{ {
os << "\033["; os << "\033[";
if ((log_color.foreground == Color::none) && (log_color.background == Color::none)) if ((log_color.foreground == Color::none) && (log_color.background == Color::none))
@ -803,11 +913,13 @@ static std::ostream& operator<< (std::ostream& os, const LogColor& log_color)
static std::ostream& operator<< (std::ostream& os, const Color& color) static std::ostream& operator<< (std::ostream& os, const Color& color)
{ {
os << LogColor(color); os << TextColor(color);
return os; return os;
} }
}
#endif /// AIX_LOG_HPP #endif /// AIX_LOG_HPP

View file

@ -43,7 +43,7 @@ ifeq ($(TARGET), ANDROID)
CXX = $(NDK_DIR)/bin/arm-linux-androideabi-g++ CXX = $(NDK_DIR)/bin/arm-linux-androideabi-g++
STRIP = $(NDK_DIR)/bin/arm-linux-androideabi-strip STRIP = $(NDK_DIR)/bin/arm-linux-androideabi-strip
CXXFLAGS += -pthread -DANDROID -DNO_CPP11_STRING -fPIC -I$(NDK_DIR)/include CXXFLAGS += -pthread -DANDROID -DNO_CPP11_STRING -fPIC -I$(NDK_DIR)/include
LDFLAGS += -L$(NDK_DIR)/lib -pie LDFLAGS += -L$(NDK_DIR)/lib -pie -llog
else ifeq ($(TARGET), OPENWRT) else ifeq ($(TARGET), OPENWRT)

View file

@ -143,10 +143,10 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
Log::init( AixLog::Log::init(
{ {
make_shared<LogSinkCout>(debugSwitch.isSet()?(LogSeverity::trace):(LogSeverity::info), LogSink::Type::all, debugSwitch.isSet()?"%Y-%m-%d %H-%M-%S.#ms [#prio] (#tag)":"%Y-%m-%d %H-%M-%S [#prio]"), make_shared<AixLog::SinkCout>(debugSwitch.isSet()?(AixLog::Severity::trace):(AixLog::Severity::info), AixLog::Type::all, debugSwitch.isSet()?"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag)":"%Y-%m-%d %H-%M-%S [#severity]"),
make_shared<LogSinkNative>("snapserver", LogSeverity::trace, LogSink::Type::special) make_shared<AixLog::SinkNative>("snapserver", AixLog::Severity::trace, AixLog::Type::special)
} }
); );