Consolidate logging initialization logic

This commit is contained in:
Stephen Shelton 2020-04-02 11:45:33 -06:00
parent 6909e20588
commit be014175e9
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C
6 changed files with 122 additions and 87 deletions

View File

@ -7,7 +7,6 @@
#include <router_contact.hpp>
#include <stdexcept>
#include <util/fs.hpp>
#include <util/logging/logger_syslog.hpp>
#include <util/logging/logger.hpp>
#include <util/mem.hpp>
#include <util/str.hpp>
@ -29,17 +28,6 @@ namespace llarp
constexpr int DefaultMinConnectionsForClient = 4;
constexpr int DefaultMaxConnectionsForClient = 6;
LoggingConfig::LogType
LoggingConfig::LogTypeFromString(const std::string& str)
{
if (str == "unknown") return LogType::Unknown;
else if (str == "file") return LogType::File;
else if (str == "json") return LogType::Json;
else if (str == "syslog") return LogType::Syslog;
return LogType::Unknown;
}
void
RouterConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params)
{
@ -353,7 +341,7 @@ namespace llarp
conf.defineOption<std::string>("logging", "type", false, DefaultLogType,
[this](std::string arg) {
LoggingConfig::LogType type = LogTypeFromString(arg);
LogType type = LogTypeFromString(arg);
if (type == LogType::Unknown)
throw std::invalid_argument(stringify("invalid log type: ", arg));

View File

@ -150,15 +150,6 @@ namespace llarp
struct LoggingConfig
{
enum class LogType
{
Unknown = 0,
File,
Json,
Syslog,
};
static LogType LogTypeFromString(const std::string&);
LogType m_logType;
LogLevel m_logLevel;
std::string m_logFile;

View File

@ -597,71 +597,12 @@ namespace llarp
}
// Logging config
LogContext::Instance().nodeName = conf->router.m_nickname;
FILE* logfile = nullptr;
if (conf->logging.m_logFile == "stdout")
{
logfile = stdout;
}
else
{
logfile = ::fopen(conf->logging.m_logFile.c_str(), "a");
if (not logfile)
{
LogError("could not open logfile ", conf->logging.m_logFile, ", errno: ", strerror(errno));
return false;
}
}
switch (conf->logging.m_logType)
{
case LoggingConfig::LogType::Unknown:
// Config shouldn't allow this to happen, so we die swiftly if we get here
assert(conf->logging.m_logType != LoggingConfig::LogType::Unknown);
break;
case LoggingConfig::LogType::File:
if (logfile != stdout)
{
LogInfo("Switching logger to file ", conf->logging.m_logFile);
std::cout << std::flush;
LogContext::Instance().logStream =
std::make_unique< FileLogStream >(diskworker(), logfile, 100ms, true);
}
else
{
LogInfo("Logger remains stdout");
}
break;
case LoggingConfig::LogType::Json:
LogInfo("Switching logger to JSON with file: ", conf->logging.m_logFile);
std::cout << std::flush;
LogContext::Instance().logStream = std::make_unique< JSONLogStream >(
diskworker(), logfile, 100ms, logfile != stdout);
break;
case LoggingConfig::LogType::Syslog:
if (logfile)
{
// TODO: this logic should be handled in Config
// TODO: this won't even work because of default value for 'file' (== "stdout")
LogError("Cannot mix log type=syslog and file=*");
::fclose(logfile);
return false;
}
#if defined(_WIN32)
LogError("syslog not supported on win32");
return false;
#else
LogInfo("Switching logger to syslog");
std::cout << std::flush;
LogContext::Instance().logStream = std::make_unique< SysLogStream >();
#endif
break;
}
LogContext::Instance().Initialize(
conf->logging.m_logLevel,
conf->logging.m_logType,
conf->logging.m_logFile,
conf->router.m_nickname,
diskworker());
// TODO: clean this up. it appears that we're dumping the [dns] "options" into the
// [network] "options"

View File

@ -1,6 +1,9 @@
#include <util/logging/logger.hpp>
#include <util/logging/logger.h>
#include <util/logging/ostream_logger.hpp>
#include <util/logging/logger_syslog.hpp>
#include <util/logging/file_logger.hpp>
#include <util/logging/json_logger.hpp>
#if defined(_WIN32)
#include <util/logging/win32_logger.hpp>
#endif
@ -8,6 +11,10 @@
#include <util/logging/android_logger.hpp>
#endif
#include <util/str.hpp>
#include <stdexcept>
namespace llarp
{
#if defined(_WIN32)
@ -23,6 +30,17 @@ namespace llarp
#endif
#endif
LogType
LogTypeFromString(const std::string& str)
{
if (str == "unknown") return LogType::Unknown;
else if (str == "file") return LogType::File;
else if (str == "json") return LogType::Json;
else if (str == "syslog") return LogType::Syslog;
return LogType::Unknown;
}
LogContext::LogContext()
: logStream(std::make_unique<Stream_t>(_LOGSTREAM_INIT)), started(llarp::time_now_ms())
{
@ -74,6 +92,78 @@ namespace llarp
logStream->ImmediateFlush();
}
void
LogContext::Initialize(LogLevel level,
LogType type,
const std::string& file,
const std::string& nickname,
std::shared_ptr<thread::ThreadPool> threadpool)
{
SetLogLevel(level);
nodeName = nickname;
FILE* logfile = nullptr;
if (file == "stdout")
{
logfile = stdout;
}
else
{
logfile = ::fopen(file.c_str(), "a");
if (not logfile)
{
throw std::runtime_error(stringify(
"could not open logfile ", file, ", errno: ", strerror(errno)));
}
}
switch (type)
{
case LogType::Unknown:
throw std::invalid_argument("Cannot use LogType::Unknown");
case LogType::File:
if (logfile != stdout)
{
LogInfo("Switching logger to file ", file);
std::cout << std::flush;
LogContext::Instance().logStream =
std::make_unique< FileLogStream >(threadpool, logfile, 100ms, true);
}
else
{
LogInfo("Logger remains stdout");
}
break;
case LogType::Json:
LogInfo("Switching logger to JSON with file: ", file);
std::cout << std::flush;
LogContext::Instance().logStream = std::make_unique< JSONLogStream >(
threadpool, logfile, 100ms, logfile != stdout);
break;
case LogType::Syslog:
if (logfile)
{
// TODO: this logic should be handled in Config
// TODO: this won't even work because of default value for 'file' (== "stdout")
::fclose(logfile);
throw std::invalid_argument("Cannot mix log type=syslog and file=*");
}
#if defined(_WIN32)
throw std::runtime_error("syslog not supported on win32");
#else
LogInfo("Switching logger to syslog");
std::cout << std::flush;
LogContext::Instance().logStream = std::make_unique< SysLogStream >();
#endif
break;
}
}
} // namespace llarp
extern "C"

View File

@ -1,12 +1,22 @@
#ifndef LLARP_UTIL_LOGGER_HPP
#define LLARP_UTIL_LOGGER_HPP
#include <memory>
#include <util/time.hpp>
#include <util/logging/logstream.hpp>
#include <util/logging/logger_internal.hpp>
#include <util/thread/thread_pool.hpp>
namespace llarp
{
enum class LogType
{
Unknown = 0,
File,
Json,
Syslog,
};
LogType LogTypeFromString(const std::string&);
struct LogContext
{
@ -32,6 +42,20 @@ namespace llarp
/// Should only be called in rare circumstances, such as when the program is about to exit.
void
ImmediateFlush();
/// Initialize the logging system.
///
/// @param level is the new log level (below which log statements will be ignored)
/// @param type is the type of logger to set up
/// @param file is the file to log to (relevant for types File and Json)
/// @param nickname is a tag to add to each log statement
/// @param threadpool is a threadpool where I/O can offloaded
void
Initialize(LogLevel level,
LogType type,
const std::string& file,
const std::string& nickname,
std::shared_ptr<thread::ThreadPool> threadpool);
};
void

View File

@ -47,5 +47,6 @@ namespace llarp
SysLogStream::PostLog(std::stringstream&) const
{
}
} // namespace llarp
#endif