mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-01 19:26:58 +02:00
Make logsink and filter configurable
This commit is contained in:
parent
ad8332345f
commit
a2311dfbfd
7 changed files with 242 additions and 85 deletions
|
@ -49,10 +49,10 @@ struct ClientSettings
|
||||||
SharingMode sharing_mode{SharingMode::shared};
|
SharingMode sharing_mode{SharingMode::shared};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoggingSettings
|
struct Logging
|
||||||
{
|
{
|
||||||
bool debug{false};
|
std::string sink{""};
|
||||||
std::string debug_logfile{""};
|
std::string filter{"*:info"};
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t instance{1};
|
size_t instance{1};
|
||||||
|
@ -60,7 +60,7 @@ struct ClientSettings
|
||||||
|
|
||||||
ServerSettings server;
|
ServerSettings server;
|
||||||
PlayerSettings player;
|
PlayerSettings player;
|
||||||
LoggingSettings logging;
|
Logging logging;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -94,7 +94,10 @@ int main(int argc, char** argv)
|
||||||
OptionParser op("Allowed options");
|
OptionParser op("Allowed options");
|
||||||
auto helpSwitch = op.add<Switch>("", "help", "produce help message");
|
auto helpSwitch = op.add<Switch>("", "help", "produce help message");
|
||||||
auto groffSwitch = op.add<Switch, Attribute::hidden>("", "groff", "produce groff message");
|
auto groffSwitch = op.add<Switch, Attribute::hidden>("", "groff", "produce groff message");
|
||||||
auto debugOption = op.add<Implicit<string>, Attribute::hidden>("", "debug", "enable debug logging", ""); // TODO: &settings.logging.debug);
|
op.add<Value<string>>("", "logsink", "log sink [null,system,stdout,stderr,file:<filename>]", settings.logging.sink, &settings.logging.sink);
|
||||||
|
auto logfilterOption = op.add<Value<string>>(
|
||||||
|
"", "logfilter", "log filter <tag>:<level>[,<tag>:<level>]* with tag = * or <log tag> and level = [trace,debug,info,notice,warning,error,fatal]",
|
||||||
|
settings.logging.filter);
|
||||||
auto versionSwitch = op.add<Switch>("v", "version", "show version number");
|
auto versionSwitch = op.add<Switch>("v", "version", "show version number");
|
||||||
#if defined(HAS_ALSA) || defined(WINDOWS)
|
#if defined(HAS_ALSA) || defined(WINDOWS)
|
||||||
auto listSwitch = op.add<Switch>("l", "list", "list PCM devices");
|
auto listSwitch = op.add<Switch>("l", "list", "list PCM devices");
|
||||||
|
@ -175,18 +178,42 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// XXX: Only one metadata option must be set
|
// XXX: Only one metadata option must be set
|
||||||
|
|
||||||
// TODO: AixLog::Log::init<AixLog::SinkNative>("snapclient", AixLog::Severity::trace, AixLog::Type::special);
|
settings.logging.filter = logfilterOption->value();
|
||||||
if (debugOption->is_set())
|
if (logfilterOption->is_set())
|
||||||
{
|
{
|
||||||
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::trace, "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
|
for (size_t n = 1; n < logfilterOption->count(); ++n)
|
||||||
if (!debugOption->value().empty())
|
settings.logging.filter += "," + logfilterOption->value(n);
|
||||||
AixLog::Log::instance().add_logsink<AixLog::SinkFile>(AixLog::Severity::trace, debugOption->value(),
|
|
||||||
"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.logging.sink.empty())
|
||||||
|
{
|
||||||
|
settings.logging.sink = "stdout";
|
||||||
|
#ifdef HAS_DAEMON
|
||||||
|
if (daemonOption->is_set())
|
||||||
|
settings.logging.sink = "system";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
AixLog::Filter logfilter;
|
||||||
|
auto filters = utils::string::split(settings.logging.filter, ',');
|
||||||
|
for (const auto& filter : filters)
|
||||||
|
logfilter.add_filter(filter);
|
||||||
|
|
||||||
|
string logformat = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)";
|
||||||
|
if (settings.logging.sink.find("file:") != string::npos)
|
||||||
|
{
|
||||||
|
string logfile = settings.logging.sink.substr(settings.logging.sink.find(":") + 1);
|
||||||
|
AixLog::Log::init<AixLog::SinkFile>(logfilter, logfile, logformat);
|
||||||
|
}
|
||||||
|
else if (settings.logging.sink == "stdout")
|
||||||
|
AixLog::Log::init<AixLog::SinkCout>(logfilter, logformat);
|
||||||
|
else if (settings.logging.sink == "stderr")
|
||||||
|
AixLog::Log::init<AixLog::SinkCerr>(logfilter, logformat);
|
||||||
|
else if (settings.logging.sink == "system")
|
||||||
|
AixLog::Log::init<AixLog::SinkNative>("snapclient", logfilter);
|
||||||
|
else if (settings.logging.sink == "null")
|
||||||
|
AixLog::Log::init<AixLog::SinkNull>();
|
||||||
else
|
else
|
||||||
{
|
throw SnapException("Invalid log sink: " + settings.logging.sink);
|
||||||
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::info, "%Y-%m-%d %H-%M-%S [#severity] (#tag_func)");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAS_DAEMON
|
#ifdef HAS_DAEMON
|
||||||
std::unique_ptr<Daemon> daemon;
|
std::unique_ptr<Daemon> daemon;
|
||||||
|
@ -311,7 +338,7 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "Exception: " << e.what() << std::endl;
|
LOG(FATAL) << "Exception: " << e.what() << std::endl;
|
||||||
exitcode = EXIT_FAILURE;
|
exitcode = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -480,8 +480,8 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
lastUpdate_ = now;
|
lastUpdate_ = now;
|
||||||
median_ = buffer_.median();
|
median_ = buffer_.median();
|
||||||
shortMedian_ = shortBuffer_.median();
|
shortMedian_ = shortBuffer_.median();
|
||||||
LOG(INFO, LOG_TAG) << "Chunk: " << age.count() / 100 << "\t" << miniBuffer_.median() / 100 << "\t" << shortMedian_ / 100 << "\t" << median_ / 100
|
LOG(DEBUG, "Stats") << "Chunk: " << age.count() / 100 << "\t" << miniBuffer_.median() / 100 << "\t" << shortMedian_ / 100 << "\t" << median_ / 100
|
||||||
<< "\t" << buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\t" << frame_delta_ << "\n";
|
<< "\t" << buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\t" << frame_delta_ << "\n";
|
||||||
frame_delta_ = 0;
|
frame_delta_ = 0;
|
||||||
}
|
}
|
||||||
return (abs(cs::duration<cs::msec>(age)) < 500);
|
return (abs(cs::duration<cs::msec>(age)) < 500);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/ _\ ( )( \/ )( ) / \ / __)
|
/ _\ ( )( \/ )( ) / \ / __)
|
||||||
/ \ )( ) ( / (_/\( O )( (_ \
|
/ \ )( ) ( / (_/\( O )( (_ \
|
||||||
\_/\_/(__)(_/\_)\____/ \__/ \___/
|
\_/\_/(__)(_/\_)\____/ \__/ \___/
|
||||||
version 1.3.0
|
version 1.4.0
|
||||||
https://github.com/badaix/aixlog
|
https://github.com/badaix/aixlog
|
||||||
|
|
||||||
This file is part of aixlog
|
This file is part of aixlog
|
||||||
|
@ -175,6 +175,53 @@ enum class Severity : std::int8_t
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static Severity to_severity(std::string severity, Severity def = Severity::info)
|
||||||
|
{
|
||||||
|
std::transform(severity.begin(), severity.end(), severity.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||||
|
if (severity == "trace")
|
||||||
|
return Severity::trace;
|
||||||
|
else if (severity == "debug")
|
||||||
|
return Severity::debug;
|
||||||
|
else if (severity == "info")
|
||||||
|
return Severity::info;
|
||||||
|
else if (severity == "notice")
|
||||||
|
return Severity::notice;
|
||||||
|
else if (severity == "warning")
|
||||||
|
return Severity::warning;
|
||||||
|
else if (severity == "error")
|
||||||
|
return Severity::error;
|
||||||
|
else if (severity == "fatal")
|
||||||
|
return Severity::fatal;
|
||||||
|
else
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static std::string to_string(Severity logSeverity)
|
||||||
|
{
|
||||||
|
switch (logSeverity)
|
||||||
|
{
|
||||||
|
case Severity::trace:
|
||||||
|
return "Trace";
|
||||||
|
case Severity::debug:
|
||||||
|
return "Debug";
|
||||||
|
case Severity::info:
|
||||||
|
return "Info";
|
||||||
|
case Severity::notice:
|
||||||
|
return "Notice";
|
||||||
|
case Severity::warning:
|
||||||
|
return "Warn";
|
||||||
|
case Severity::error:
|
||||||
|
return "Error";
|
||||||
|
case Severity::fatal:
|
||||||
|
return "Fatal";
|
||||||
|
default:
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << static_cast<int>(logSeverity);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Color constants used for console colors
|
* Color constants used for console colors
|
||||||
|
@ -330,6 +377,10 @@ struct Tag
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tag(const char* text) : text(text), is_null_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Tag(const std::string& text) : text(text), is_null_(false)
|
Tag(const std::string& text) : text(text), is_null_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -345,6 +396,11 @@ struct Tag
|
||||||
return !is_null_;
|
return !is_null_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator<(const Tag& other) const
|
||||||
|
{
|
||||||
|
return (text < other.text);
|
||||||
|
}
|
||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -404,6 +460,59 @@ struct Metadata
|
||||||
Timestamp timestamp;
|
Timestamp timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Filter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter(Severity severity)
|
||||||
|
{
|
||||||
|
add_filter(severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match(const Metadata& metadata) const
|
||||||
|
{
|
||||||
|
if (tag_filter_.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto iter = tag_filter_.find(metadata.tag);
|
||||||
|
if (iter != tag_filter_.end())
|
||||||
|
return (metadata.severity >= iter->second);
|
||||||
|
|
||||||
|
iter = tag_filter_.find("*");
|
||||||
|
if (iter != tag_filter_.end())
|
||||||
|
return (metadata.severity >= iter->second);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_filter(const Tag& tag, Severity severity)
|
||||||
|
{
|
||||||
|
tag_filter_[tag] = severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_filter(Severity severity)
|
||||||
|
{
|
||||||
|
tag_filter_["*"] = severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_filter(const std::string& filter)
|
||||||
|
{
|
||||||
|
auto pos = filter.find(":");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
add_filter(filter.substr(0, pos), to_severity(filter.substr(pos + 1)));
|
||||||
|
else
|
||||||
|
add_filter(to_severity(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<Tag, Severity> tag_filter_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Abstract log sink
|
* Abstract log sink
|
||||||
|
@ -412,7 +521,7 @@ struct Metadata
|
||||||
*/
|
*/
|
||||||
struct Sink
|
struct Sink
|
||||||
{
|
{
|
||||||
Sink(Severity severity) : severity(severity)
|
Sink(const Filter& filter) : filter(filter)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +529,7 @@ struct Sink
|
||||||
|
|
||||||
virtual void log(const Metadata& metadata, const std::string& message) = 0;
|
virtual void log(const Metadata& metadata, const std::string& message) = 0;
|
||||||
|
|
||||||
Severity severity;
|
Filter filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ostream operators << for the meta data structs
|
/// ostream operators << for the meta data structs
|
||||||
|
@ -490,31 +599,6 @@ public:
|
||||||
log_sinks_.erase(std::remove(log_sinks_.begin(), log_sinks_.end(), sink), log_sinks_.end());
|
log_sinks_.erase(std::remove(log_sinks_.begin(), log_sinks_.end(), sink), log_sinks_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string to_string(Severity logSeverity)
|
|
||||||
{
|
|
||||||
switch (logSeverity)
|
|
||||||
{
|
|
||||||
case Severity::trace:
|
|
||||||
return "Trace";
|
|
||||||
case Severity::debug:
|
|
||||||
return "Debug";
|
|
||||||
case Severity::info:
|
|
||||||
return "Info";
|
|
||||||
case Severity::notice:
|
|
||||||
return "Notice";
|
|
||||||
case Severity::warning:
|
|
||||||
return "Warn";
|
|
||||||
case Severity::error:
|
|
||||||
return "Error";
|
|
||||||
case Severity::fatal:
|
|
||||||
return "Fatal";
|
|
||||||
default:
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << logSeverity;
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Log() noexcept : last_buffer_(nullptr)
|
Log() noexcept : last_buffer_(nullptr)
|
||||||
{
|
{
|
||||||
|
@ -536,7 +620,7 @@ protected:
|
||||||
{
|
{
|
||||||
for (const auto& sink : log_sinks_)
|
for (const auto& sink : log_sinks_)
|
||||||
{
|
{
|
||||||
if (metadata_.severity >= sink->severity)
|
if (sink->filter.match(metadata_))
|
||||||
sink->log(metadata_, get_stream().str());
|
sink->log(metadata_, get_stream().str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,6 +675,24 @@ private:
|
||||||
std::recursive_mutex mutex_;
|
std::recursive_mutex mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Null log sink
|
||||||
|
*
|
||||||
|
* Discards all log messages
|
||||||
|
*/
|
||||||
|
struct SinkNull : public Sink
|
||||||
|
{
|
||||||
|
SinkNull() : Sink(Filter())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void log(const Metadata& metadata, const std::string& message) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Abstract log sink with support for formatting log message
|
* Abstract log sink with support for formatting log message
|
||||||
|
@ -607,7 +709,7 @@ private:
|
||||||
*/
|
*/
|
||||||
struct SinkFormat : public Sink
|
struct SinkFormat : public Sink
|
||||||
{
|
{
|
||||||
SinkFormat(Severity severity, const std::string& format) : Sink(severity), format_(format)
|
SinkFormat(const Filter& filter, const std::string& format) : Sink(filter), format_(format)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,13 +729,13 @@ protected:
|
||||||
|
|
||||||
size_t pos = result.find("#severity");
|
size_t pos = result.find("#severity");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
result.replace(pos, 9, Log::to_string(metadata.severity));
|
result.replace(pos, 9, to_string(metadata.severity));
|
||||||
|
|
||||||
pos = result.find("#color_severity");
|
pos = result.find("#color_severity");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << TextColor(Color::RED) << Log::to_string(metadata.severity) << TextColor(Color::NONE);
|
ss << TextColor(Color::RED) << to_string(metadata.severity) << TextColor(Color::NONE);
|
||||||
result.replace(pos, 15, ss.str());
|
result.replace(pos, 15, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +775,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
struct SinkCout : public SinkFormat
|
struct SinkCout : public SinkFormat
|
||||||
{
|
{
|
||||||
SinkCout(Severity severity, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)") : SinkFormat(severity, format)
|
SinkCout(const Filter& filter, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)") : SinkFormat(filter, format)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,7 +791,7 @@ struct SinkCout : public SinkFormat
|
||||||
*/
|
*/
|
||||||
struct SinkCerr : public SinkFormat
|
struct SinkCerr : public SinkFormat
|
||||||
{
|
{
|
||||||
SinkCerr(Severity severity, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)") : SinkFormat(severity, format)
|
SinkCerr(const Filter& filter, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)") : SinkFormat(filter, format)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,8 +807,8 @@ struct SinkCerr : public SinkFormat
|
||||||
*/
|
*/
|
||||||
struct SinkFile : public SinkFormat
|
struct SinkFile : public SinkFormat
|
||||||
{
|
{
|
||||||
SinkFile(Severity severity, const std::string& filename, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)")
|
SinkFile(const Filter& filter, const std::string& filename, const std::string& format = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)")
|
||||||
: SinkFormat(severity, format)
|
: SinkFormat(filter, format)
|
||||||
{
|
{
|
||||||
ofs.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
|
ofs.open(filename.c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||||
}
|
}
|
||||||
|
@ -734,7 +836,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
struct SinkOutputDebugString : public Sink
|
struct SinkOutputDebugString : public Sink
|
||||||
{
|
{
|
||||||
SinkOutputDebugString(Severity severity) : Sink(severity)
|
SinkOutputDebugString(const Filter& filter) : Sink(filter)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,7 +855,7 @@ struct SinkOutputDebugString : public Sink
|
||||||
*/
|
*/
|
||||||
struct SinkUnifiedLogging : public Sink
|
struct SinkUnifiedLogging : public Sink
|
||||||
{
|
{
|
||||||
SinkUnifiedLogging(Severity severity) : Sink(severity)
|
SinkUnifiedLogging(const Filter& filter) : Sink(filter)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,7 +895,7 @@ struct SinkUnifiedLogging : public Sink
|
||||||
*/
|
*/
|
||||||
struct SinkSyslog : public Sink
|
struct SinkSyslog : public Sink
|
||||||
{
|
{
|
||||||
SinkSyslog(const char* ident, Severity severity) : Sink(severity)
|
SinkSyslog(const char* ident, const Filter& filter) : Sink(filter)
|
||||||
{
|
{
|
||||||
openlog(ident, LOG_PID, LOG_USER);
|
openlog(ident, LOG_PID, LOG_USER);
|
||||||
}
|
}
|
||||||
|
@ -842,7 +944,7 @@ struct SinkSyslog : public Sink
|
||||||
*/
|
*/
|
||||||
struct SinkAndroid : public Sink
|
struct SinkAndroid : public Sink
|
||||||
{
|
{
|
||||||
SinkAndroid(const std::string& ident, Severity severity) : Sink(severity), ident_(ident)
|
SinkAndroid(const std::string& ident, const Filter& filter) : Sink(filter), ident_(ident)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,7 +1001,7 @@ protected:
|
||||||
*/
|
*/
|
||||||
struct SinkEventLog : public Sink
|
struct SinkEventLog : public Sink
|
||||||
{
|
{
|
||||||
SinkEventLog(const std::string& ident, Severity severity) : Sink(severity)
|
SinkEventLog(const std::string& ident, const Filter& filter) : Sink(filter)
|
||||||
{
|
{
|
||||||
std::wstring wide = std::wstring(ident.begin(), ident.end()); // stijnvdb: RegisterEventSource expands to RegisterEventSourceW which takes wchar_t
|
std::wstring wide = std::wstring(ident.begin(), ident.end()); // stijnvdb: RegisterEventSource expands to RegisterEventSourceW which takes wchar_t
|
||||||
event_log = RegisterEventSource(NULL, wide.c_str());
|
event_log = RegisterEventSource(NULL, wide.c_str());
|
||||||
|
@ -951,16 +1053,16 @@ protected:
|
||||||
*/
|
*/
|
||||||
struct SinkNative : public Sink
|
struct SinkNative : public Sink
|
||||||
{
|
{
|
||||||
SinkNative(const std::string& ident, Severity severity) : Sink(severity), log_sink_(nullptr), ident_(ident)
|
SinkNative(const std::string& ident, const Filter& filter) : Sink(filter), log_sink_(nullptr), ident_(ident)
|
||||||
{
|
{
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
log_sink_ = std::make_shared<SinkAndroid>(ident_, severity);
|
log_sink_ = std::make_shared<SinkAndroid>(ident_, filter);
|
||||||
#elif HAS_APPLE_UNIFIED_LOG_
|
#elif HAS_APPLE_UNIFIED_LOG_
|
||||||
log_sink_ = std::make_shared<SinkUnifiedLogging>(severity);
|
log_sink_ = std::make_shared<SinkUnifiedLogging>(filter);
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
log_sink_ = std::make_shared<SinkEventLog>(ident, severity);
|
log_sink_ = std::make_shared<SinkEventLog>(ident, filter);
|
||||||
#elif HAS_SYSLOG_
|
#elif HAS_SYSLOG_
|
||||||
log_sink_ = std::make_shared<SinkSyslog>(ident_.c_str(), severity);
|
log_sink_ = std::make_shared<SinkSyslog>(ident_.c_str(), filter);
|
||||||
#else
|
#else
|
||||||
/// will not throw or something. Use "get_logger()" to check for success
|
/// will not throw or something. Use "get_logger()" to check for success
|
||||||
log_sink_ = nullptr;
|
log_sink_ = nullptr;
|
||||||
|
@ -995,7 +1097,7 @@ struct SinkCallback : public Sink
|
||||||
{
|
{
|
||||||
using callback_fun = std::function<void(const Metadata& metadata, const std::string& message)>;
|
using callback_fun = std::function<void(const Metadata& metadata, const std::string& message)>;
|
||||||
|
|
||||||
SinkCallback(Severity severity, callback_fun callback) : Sink(severity), callback_(callback)
|
SinkCallback(const Filter& filter, callback_fun callback) : Sink(filter), callback_(callback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,7 +1135,7 @@ static std::ostream& operator<<(std::ostream& os, const Severity& log_severity)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
os << Log::to_string(log_severity);
|
os << to_string(log_severity);
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,10 +146,12 @@ stream = pipe:///tmp/snapfifo?name=default
|
||||||
#
|
#
|
||||||
[logging]
|
[logging]
|
||||||
|
|
||||||
# enable debug logging
|
# log sink [null,system,stdout,stderr,file:<filename>]
|
||||||
#debug = false
|
# when left empty: if running as daemon "system" else "stdout"
|
||||||
|
#sink =
|
||||||
|
|
||||||
# log file name for the debug logs (debug must be enabled)
|
# log filter <tag>:<level>[,<tag>:<level>]*
|
||||||
#debug_logfile =
|
# with tag = * or <log tag> and level = [trace,debug,info,notice,warning,error,fatal]
|
||||||
|
#filter = *:info
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
|
@ -51,16 +51,16 @@ struct ServerSettings
|
||||||
std::vector<std::string> bind_to_address{{"0.0.0.0"}};
|
std::vector<std::string> bind_to_address{{"0.0.0.0"}};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoggingSettings
|
struct Logging
|
||||||
{
|
{
|
||||||
bool debug{false};
|
std::string sink{""};
|
||||||
std::string debug_logfile{""};
|
std::string filter{"*:info"};
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpSettings http;
|
HttpSettings http;
|
||||||
TcpSettings tcp;
|
TcpSettings tcp;
|
||||||
StreamSettings stream;
|
StreamSettings stream;
|
||||||
LoggingSettings logging;
|
Logging logging;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,9 +70,11 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
// debug settings
|
// debug settings
|
||||||
OptionParser conf("");
|
OptionParser conf("");
|
||||||
conf.add<Value<bool>>("", "logging.debug", "enable debug logging", settings.logging.debug, &settings.logging.debug);
|
op.add<Value<string>>("", "logging.sink", "log sink [null,system,stdout,stderr,file:<filename>]", settings.logging.sink, &settings.logging.sink);
|
||||||
conf.add<Value<string>>("", "logging.debug_logfile", "log file name for the debug logs (debug must be enabled)", settings.logging.debug_logfile,
|
auto logfilterOption = op.add<Value<string>>(
|
||||||
&settings.logging.debug_logfile);
|
"", "logging.filter",
|
||||||
|
"log filter <tag>:<level>[,<tag>:<level>]* with tag = * or <log tag> and level = [trace,debug,info,notice,warning,error,fatal]",
|
||||||
|
settings.logging.filter);
|
||||||
|
|
||||||
// stream settings
|
// stream settings
|
||||||
conf.add<Value<size_t>>("", "stream.port", "Server port", settings.stream.port, &settings.stream.port);
|
conf.add<Value<size_t>>("", "stream.port", "Server port", settings.stream.port, &settings.stream.port);
|
||||||
|
@ -182,18 +184,42 @@ int main(int argc, char* argv[])
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: AixLog::Log::init<AixLog::SinkNative>("snapserver", AixLog::Severity::trace, AixLog::Type::special);
|
settings.logging.filter = logfilterOption->value();
|
||||||
if (settings.logging.debug)
|
if (logfilterOption->is_set())
|
||||||
{
|
{
|
||||||
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::trace, "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
|
for (size_t n = 1; n < logfilterOption->count(); ++n)
|
||||||
if (!settings.logging.debug_logfile.empty())
|
settings.logging.filter += "," + logfilterOption->value(n);
|
||||||
AixLog::Log::instance().add_logsink<AixLog::SinkFile>(AixLog::Severity::trace, settings.logging.debug_logfile,
|
|
||||||
"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.logging.sink.empty())
|
||||||
|
{
|
||||||
|
settings.logging.sink = "stdout";
|
||||||
|
#ifdef HAS_DAEMON
|
||||||
|
if (daemonOption->is_set())
|
||||||
|
settings.logging.sink = "system";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
AixLog::Filter logfilter;
|
||||||
|
auto filters = utils::string::split(settings.logging.filter, ',');
|
||||||
|
for (const auto& filter : filters)
|
||||||
|
logfilter.add_filter(filter);
|
||||||
|
|
||||||
|
string logformat = "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)";
|
||||||
|
if (settings.logging.sink.find("file:") != string::npos)
|
||||||
|
{
|
||||||
|
string logfile = settings.logging.sink.substr(settings.logging.sink.find(":") + 1);
|
||||||
|
AixLog::Log::init<AixLog::SinkFile>(logfilter, logfile, logformat);
|
||||||
|
}
|
||||||
|
else if (settings.logging.sink == "stdout")
|
||||||
|
AixLog::Log::init<AixLog::SinkCout>(logfilter, logformat);
|
||||||
|
else if (settings.logging.sink == "stderr")
|
||||||
|
AixLog::Log::init<AixLog::SinkCerr>(logfilter, logformat);
|
||||||
|
else if (settings.logging.sink == "system")
|
||||||
|
AixLog::Log::init<AixLog::SinkNative>("snapclient", logfilter);
|
||||||
|
else if (settings.logging.sink == "null")
|
||||||
|
AixLog::Log::init<AixLog::SinkNull>();
|
||||||
else
|
else
|
||||||
{
|
throw SnapException("Invalid log sink: " + settings.logging.sink);
|
||||||
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::info, "%Y-%m-%d %H-%M-%S [#severity] (#tag_func)");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& opt : conf.unknown_options())
|
for (const auto& opt : conf.unknown_options())
|
||||||
LOG(WARNING) << "unknown configuration option: " << opt << "\n";
|
LOG(WARNING) << "unknown configuration option: " << opt << "\n";
|
||||||
|
|
Loading…
Add table
Reference in a new issue