Skip to content
This repository has been archived by the owner on Jan 15, 2025. It is now read-only.

Commit

Permalink
Merge pull request #329 from GabrielNagy/PA-3490/syslog-logging
Browse files Browse the repository at this point in the history
(PA-3490) Add syslog logging to leatherman
  • Loading branch information
mihaibuzgau authored Dec 9, 2020
2 parents 246f0c5 + 776b7ac commit 093ae02
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 13 deletions.
44 changes: 43 additions & 1 deletion logging/inc/leatherman/logging/logging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,36 @@ namespace leatherman { namespace logging {
fatal
};

/**
* Represents the supported logging backends.
*/
enum class logging_backend { eventlog, syslog, file };

/**
* Represents the supported syslog facilities
*/
enum class syslog_facility
{
kern = (0<<3),
user = (1<<3),
mail = (2<<3),
daemon = (3<<3),
auth = (4<<3),
syslog = (5<<3),
lpr = (6<<3),
news = (7<<3),
uucp = (8<<3),
cron = (9<<3),
local0 = (16<<3),
local1 = (17<<3),
local2 = (18<<3),
local3 = (19<<3),
local4 = (20<<3),
local5 = (21<<3),
local6 = (22<<3),
local7 = (23<<3),
};

/**
* Reads a log level from an input stream.
* This is used in boost::lexical_cast<log_level>.
Expand Down Expand Up @@ -158,10 +188,18 @@ namespace leatherman { namespace logging {
/**
* Registers application to event log and configures event log handle
* The logging level is set to warning by default.
* @param application Destination stream for logging output.
* @param application Application name.
*/
void setup_eventlog_logging(std::string application);

/**
* Configures application to log to syslog
* The logging level is set to warning by default.
* @param application Application name.
* @param facility Syslog facility to log to.
*/
void setup_syslog_logging(const char* application, const std::string& facility);

/**
* Sets the current log level.
* @param level The new current log level to set.
Expand Down Expand Up @@ -270,6 +308,10 @@ namespace leatherman { namespace logging {

// private
void log_eventlog(log_level level, std::string const& message);
void log_syslog(log_level level, std::string const& message);
void log_boost(const std::string &logger, log_level level, int line_num, std::string const& message);
void enable_event_log(void);
void disable_event_log(void);
void enable_syslog(void);
void disable_syslog(void);
}} // namespace leatherman::logging
45 changes: 33 additions & 12 deletions logging/src/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ namespace leatherman { namespace logging {

static function<bool(log_level, string const&)> g_callback;
static log_level g_level = log_level::none;
static logging_backend g_backend = logging_backend::file;
static bool g_colorize = false;
static bool g_error_logged = false;
static bool use_event_log = false;

namespace lth_locale = leatherman::locale;

Expand Down Expand Up @@ -166,18 +166,29 @@ namespace leatherman { namespace logging {
return;
}

if (use_event_log) {
switch (g_backend) {
case logging_backend::eventlog:
log_eventlog(level, message);
} else {
src::logger slg;
slg.add_attribute("Severity", attrs::constant<log_level>(level));
slg.add_attribute("Namespace", attrs::constant<string>(logger));
if (line_num > 0) {
slg.add_attribute("LineNum", attrs::constant<int>(line_num));
}
break;
case logging_backend::syslog:
log_syslog(level, message);
break;
default:
log_boost(logger, level, line_num, message);
break;
}
}

BOOST_LOG(slg) << message;
void log_boost(const string &logger, log_level level, int line_num, string const& message)
{
src::logger slg;
slg.add_attribute("Severity", attrs::constant<log_level>(level));
slg.add_attribute("Namespace", attrs::constant<string>(logger));
if (line_num > 0) {
slg.add_attribute("LineNum", attrs::constant<int>(line_num));
}

BOOST_LOG(slg) << message;
}

istream& operator>>(istream& in, log_level& level)
Expand Down Expand Up @@ -233,12 +244,22 @@ namespace leatherman { namespace logging {

void enable_event_log()
{
use_event_log = true;
g_backend = logging_backend::eventlog;
}

void disable_event_log()
{
use_event_log = false;
g_backend = logging_backend::file;
}

void enable_syslog()
{
g_backend = logging_backend::syslog;
}

void disable_syslog()
{
g_backend = logging_backend::file;
}

}} // namespace leatherman::logging
75 changes: 75 additions & 0 deletions logging/src/posix/logging.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include <leatherman/logging/logging.hpp>
#include <boost/nowide/iostream.hpp>
#include <unistd.h>
#include <syslog.h>

using namespace std;

namespace leatherman { namespace logging {

namespace lth_locale = leatherman::locale;

void colorize(ostream& dst, log_level level)
{
if (!get_colorization()) {
Expand Down Expand Up @@ -39,4 +42,76 @@ namespace leatherman { namespace logging {
void log_eventlog(log_level level, string const& message) {
throw runtime_error("eventlog is available only on windows");
}

syslog_facility string_to_syslog_facility(std::string facility)
{
syslog_facility fac;
try {
const std::map<std::string, syslog_facility> option_to_syslog_facility {
{ "kern", syslog_facility::kern },
{ "user", syslog_facility::user },
{ "mail", syslog_facility::mail },
{ "daemon", syslog_facility::daemon },
{ "auth", syslog_facility::auth },
{ "syslog", syslog_facility::syslog },
{ "lpr", syslog_facility::lpr },
{ "news", syslog_facility::news },
{ "uucp", syslog_facility::uucp },
{ "cron", syslog_facility::cron },
{ "local0", syslog_facility::local0 },
{ "local1", syslog_facility::local1 },
{ "local2", syslog_facility::local2 },
{ "local3", syslog_facility::local3 },
{ "local4", syslog_facility::local4 },
{ "local5", syslog_facility::local5 },
{ "local6", syslog_facility::local6 },
{ "local7", syslog_facility::local7 },
};
fac = option_to_syslog_facility.at(facility);
} catch (const std::out_of_range& e) {
throw runtime_error {
lth_locale::format("invalid syslog facility: '{1}'", facility) };
}
return fac;
}

void setup_syslog_logging(const char* application, const string& facility)
{
syslog_facility syslog_facility = string_to_syslog_facility(facility);
int fac = static_cast<int>(syslog_facility);

openlog(application, LOG_PID | LOG_NDELAY, fac);

// Default to the warning level
set_level(log_level::warning);
enable_syslog();
}

int log_level_to_severity(log_level level)
{
switch (level) {
case log_level::fatal:
return LOG_ALERT;
case log_level::error:
return LOG_ERR;
case log_level::warning:
return LOG_WARNING;
case log_level::info:
return LOG_INFO;
case log_level::debug:
case log_level::trace:
return LOG_DEBUG;
default:
return LOG_INFO;
}
}

void log_syslog(log_level level, string const &message) {
if (level != log_level::none) {
int severity = log_level_to_severity(level);
syslog(severity, "%s", message.c_str());
}
}

void clean_syslog_logging() { closelog(); }
}} // namespace leatherman::logging
4 changes: 4 additions & 0 deletions logging/src/windows/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ namespace leatherman { namespace logging {
}
}

void log_syslog(log_level level, string const &message) {
throw runtime_error("syslog is only available on POSIX platforms");
}

void clean_eventlog_logging()
{
if (h_event_log) {
Expand Down

0 comments on commit 093ae02

Please sign in to comment.