Reworked log system: now logs are handled by lms itself (better control on what is logged), ref #725
This commit is contained in:
+1
-2
@@ -7,9 +7,8 @@ working-dir = "/var/lms";
|
|||||||
# ffmpeg location
|
# ffmpeg location
|
||||||
ffmpeg-file = "/usr/bin/ffmpeg";
|
ffmpeg-file = "/usr/bin/ffmpeg";
|
||||||
|
|
||||||
# Log files, empty means stdout
|
# Log files, empty means debug+info on stdout, warning+error+fatal on stderr
|
||||||
log-file = "";
|
log-file = "";
|
||||||
access-log-file = "";
|
|
||||||
# Minimum severity, can be "debug", "info", "warning", "error" or "fatal"
|
# Minimum severity, can be "debug", "info", "warning", "error" or "fatal"
|
||||||
# "debug" is useful for debugging purposes, but it will also generate a lot of log data and slow down the application
|
# "debug" is useful for debugging purposes, but it will also generate a lot of log data and slow down the application
|
||||||
log-min-severity = "info";
|
log-min-severity = "info";
|
||||||
|
|||||||
@@ -27,11 +27,9 @@ add_library(lmscore STATIC
|
|||||||
impl/Path.cpp
|
impl/Path.cpp
|
||||||
impl/Random.cpp
|
impl/Random.cpp
|
||||||
impl/RecursiveSharedMutex.cpp
|
impl/RecursiveSharedMutex.cpp
|
||||||
impl/StreamLogger.cpp
|
|
||||||
impl/String.cpp
|
impl/String.cpp
|
||||||
impl/TraceLogger.cpp
|
impl/TraceLogger.cpp
|
||||||
impl/UUID.cpp
|
impl/UUID.cpp
|
||||||
impl/WtLogger.cpp
|
|
||||||
impl/XxHash3.cpp
|
impl/XxHash3.cpp
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/impl/Version.cpp
|
${CMAKE_CURRENT_BINARY_DIR}/impl/Version.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,19 +17,17 @@
|
|||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
#include "core/ILogger.hpp"
|
#include "core/ILogger.hpp"
|
||||||
#include "core/ITraceLogger.hpp"
|
#include "core/ITraceLogger.hpp"
|
||||||
#include "core/StreamLogger.hpp"
|
|
||||||
|
|
||||||
namespace lms::core
|
namespace lms::core
|
||||||
{
|
{
|
||||||
// The trace logger is meant to built/destroyed once
|
// The trace logger is meant to built/destroyed once
|
||||||
const Service<logging::ILogger> logger{ std::make_unique<logging::StreamLogger>(std::cout, logging::StreamLogger::allSeverities) };
|
const Service<logging::ILogger> logger{ logging::createLogger() };
|
||||||
const Service<tracing::ITraceLogger> traceLogger{ tracing::createTraceLogger(tracing::Level::Overview) };
|
const Service<tracing::ITraceLogger> traceLogger{ tracing::createTraceLogger(tracing::Level::Overview) };
|
||||||
|
|
||||||
static void BM_TraceLogger_Overview(benchmark::State& state)
|
static void BM_TraceLogger_Overview(benchmark::State& state)
|
||||||
|
|||||||
@@ -17,7 +17,17 @@
|
|||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "core/ILogger.hpp"
|
#include "Logger.hpp"
|
||||||
|
|
||||||
|
#include <Wt/WDateTime.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "core/Exception.hpp"
|
||||||
|
#include "core/String.hpp"
|
||||||
|
|
||||||
namespace lms::core::logging
|
namespace lms::core::logging
|
||||||
{
|
{
|
||||||
@@ -63,6 +73,8 @@ namespace lms::core::logging
|
|||||||
return "UI";
|
return "UI";
|
||||||
case Module::UTILS:
|
case Module::UTILS:
|
||||||
return "UTILS";
|
return "UTILS";
|
||||||
|
case Module::WT:
|
||||||
|
return "WT";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -103,4 +115,94 @@ namespace lms::core::logging
|
|||||||
{
|
{
|
||||||
return _oss.str();
|
return _oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ILogger> createLogger(Severity minSeverity, const std::filesystem::path& logFilePath)
|
||||||
|
{
|
||||||
|
return std::make_unique<Logger>(minSeverity, logFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::OutputStream::OutputStream(std::ostream& os)
|
||||||
|
: stream{ os }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::Logger(Severity minSeverity, const std::filesystem::path& logFilePath)
|
||||||
|
{
|
||||||
|
if (!logFilePath.empty())
|
||||||
|
{
|
||||||
|
_logFileStream = std::make_unique<std::ofstream>(logFilePath, std::ios::out | std::ios::app);
|
||||||
|
if (!_logFileStream->is_open())
|
||||||
|
{
|
||||||
|
const std::error_code ec{ errno, std::generic_category() };
|
||||||
|
throw LmsException{ "Cannot open log file '" + logFilePath.string() + "' for writing: " + ec.message() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (minSeverity)
|
||||||
|
{
|
||||||
|
case core::logging::Severity::DEBUG:
|
||||||
|
if (_logFileStream)
|
||||||
|
addOutputStream(*_logFileStream, { core::logging::Severity::DEBUG });
|
||||||
|
else
|
||||||
|
addOutputStream(std::cout, { core::logging::Severity::DEBUG });
|
||||||
|
[[fallthrough]];
|
||||||
|
case core::logging::Severity::INFO:
|
||||||
|
if (_logFileStream)
|
||||||
|
addOutputStream(*_logFileStream, { core::logging::Severity::INFO });
|
||||||
|
else
|
||||||
|
addOutputStream(std::cout, { core::logging::Severity::INFO });
|
||||||
|
[[fallthrough]];
|
||||||
|
case core::logging::Severity::WARNING:
|
||||||
|
if (_logFileStream)
|
||||||
|
addOutputStream(*_logFileStream, { core::logging::Severity::WARNING });
|
||||||
|
else
|
||||||
|
addOutputStream(std::cerr, { core::logging::Severity::WARNING });
|
||||||
|
[[fallthrough]];
|
||||||
|
case core::logging::Severity::ERROR:
|
||||||
|
if (_logFileStream)
|
||||||
|
addOutputStream(*_logFileStream, { core::logging::Severity::ERROR });
|
||||||
|
else
|
||||||
|
addOutputStream(std::cerr, { core::logging::Severity::ERROR });
|
||||||
|
[[fallthrough]];
|
||||||
|
case core::logging::Severity::FATAL:
|
||||||
|
if (_logFileStream)
|
||||||
|
addOutputStream(*_logFileStream, { core::logging::Severity::FATAL });
|
||||||
|
else
|
||||||
|
addOutputStream(std::cerr, { core::logging::Severity::FATAL });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::~Logger() = default;
|
||||||
|
|
||||||
|
void Logger::addOutputStream(std::ostream& os, Severity severity)
|
||||||
|
{
|
||||||
|
auto it{ std::find_if(_outputStreams.begin(), _outputStreams.end(), [&os](const OutputStream& outputStream) { return &outputStream.stream == &os; }) };
|
||||||
|
if (it == _outputStreams.end())
|
||||||
|
it = _outputStreams.emplace(_outputStreams.end(), os);
|
||||||
|
|
||||||
|
assert(!_severityToOutputStreamMap.contains(severity));
|
||||||
|
_severityToOutputStreamMap.emplace(severity, &(*it));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Logger::isSeverityActive(Severity severity) const
|
||||||
|
{
|
||||||
|
return _severityToOutputStreamMap.contains(severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::processLog(const Log& log)
|
||||||
|
{
|
||||||
|
processLog(log.getModule(), log.getSeverity(), log.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::processLog(Module module, Severity severity, std::string_view message)
|
||||||
|
{
|
||||||
|
assert(isSeverityActive(severity)); // should have been filtered out by a isSeverityActive call
|
||||||
|
OutputStream* outputStream{ _severityToOutputStreamMap.at(severity) };
|
||||||
|
const Wt::WDateTime now{ Wt::WDateTime::currentDateTime() };
|
||||||
|
|
||||||
|
std::unique_lock lock{ outputStream->mutex };
|
||||||
|
outputStream->stream << stringUtils::toISO8601String(now) << " " << std::this_thread::get_id() << " [" << getSeverityName(severity) << "] [" << getModuleName(module) << "] " << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace lms::core::logging
|
} // namespace lms::core::logging
|
||||||
@@ -19,22 +19,41 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <filesystem>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "core/ILogger.hpp"
|
#include "core/ILogger.hpp"
|
||||||
|
|
||||||
namespace lms::core::logging
|
namespace lms::core::logging
|
||||||
{
|
{
|
||||||
class WtLogger final : public ILogger
|
class Logger final : public ILogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WtLogger(Severity minSeverity);
|
Logger(Severity minSeverity, const std::filesystem::path& logFilePath);
|
||||||
|
~Logger() override;
|
||||||
static std::string computeLogConfig(Severity minSeverity);
|
Logger(const Logger&) = delete;
|
||||||
|
Logger& operator=(const Logger&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isSeverityActive(Severity severity) const override;
|
bool isSeverityActive(Severity severity) const override;
|
||||||
void processLog(const Log& log) override;
|
void processLog(const Log& log) override;
|
||||||
const Severity _minSeverity;
|
void processLog(Module module, Severity severity, std::string_view message) override;
|
||||||
|
|
||||||
|
void addOutputStream(std::ostream& os, Severity severity);
|
||||||
|
|
||||||
|
struct OutputStream
|
||||||
|
{
|
||||||
|
OutputStream(std::ostream& os);
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
|
std::ostream& stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::list<OutputStream> _outputStreams;
|
||||||
|
std::unordered_map<Severity, OutputStream*> _severityToOutputStreamMap;
|
||||||
|
std::unique_ptr<std::ofstream> _logFileStream;
|
||||||
};
|
};
|
||||||
} // namespace lms::core::logging
|
} // namespace lms::core::logging
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "core/StreamLogger.hpp"
|
|
||||||
|
|
||||||
namespace lms::core::logging
|
|
||||||
{
|
|
||||||
StreamLogger::StreamLogger(std::ostream& os, EnumSet<Severity> severities)
|
|
||||||
: _os{ os }
|
|
||||||
, _severities{ severities }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void StreamLogger::processLog(const Log& log)
|
|
||||||
{
|
|
||||||
assert(isSeverityActive(log.getSeverity()));
|
|
||||||
_os << std::this_thread::get_id() << " [" << getSeverityName(log.getSeverity()) << "] [" << getModuleName(log.getModule()) << "] " << log.getMessage() << std::endl;
|
|
||||||
}
|
|
||||||
} // namespace lms::core::logging
|
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "core/Exception.hpp"
|
#include "core/Exception.hpp"
|
||||||
#include "core/ILogger.hpp"
|
#include "core/ILogger.hpp"
|
||||||
|
#include "core/String.hpp"
|
||||||
|
|
||||||
namespace lms::core::tracing
|
namespace lms::core::tracing
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "core/WtLogger.hpp"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include <Wt/WLogger.h>
|
|
||||||
#include <Wt/WServer.h>
|
|
||||||
|
|
||||||
#include "core/Exception.hpp"
|
|
||||||
|
|
||||||
namespace lms::core::logging
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
std::string to_string(std::thread::id id)
|
|
||||||
{
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << id;
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
WtLogger::WtLogger(Severity minSeverity)
|
|
||||||
: _minSeverity{ minSeverity }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string WtLogger::computeLogConfig(Severity minSeverity)
|
|
||||||
{
|
|
||||||
switch (minSeverity)
|
|
||||||
{
|
|
||||||
case Severity::DEBUG:
|
|
||||||
return "*";
|
|
||||||
case Severity::INFO:
|
|
||||||
return "* -debug";
|
|
||||||
case Severity::WARNING:
|
|
||||||
return "* -debug -info";
|
|
||||||
case Severity::ERROR:
|
|
||||||
return "* -debug -info -warning";
|
|
||||||
case Severity::FATAL:
|
|
||||||
return "* -debug -info -warning -error";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw LmsException{ "Unhandled severity" };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WtLogger::isSeverityActive(Severity severity) const
|
|
||||||
{
|
|
||||||
return static_cast<int>(severity) <= static_cast<int>(_minSeverity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WtLogger::processLog(const Log& log)
|
|
||||||
{
|
|
||||||
Wt::log(getSeverityName(log.getSeverity())) << Wt::WLogger::sep << to_string(std::this_thread::get_id()) << Wt::WLogger::sep << "[" << getModuleName(log.getModule()) << "]" << Wt::WLogger::sep << log.getMessage();
|
|
||||||
}
|
|
||||||
} // namespace lms::core::logging
|
|
||||||
@@ -19,11 +19,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "core/Service.hpp"
|
#include "core/Service.hpp"
|
||||||
#include "core/String.hpp"
|
|
||||||
|
|
||||||
namespace lms::core::logging
|
namespace lms::core::logging
|
||||||
{
|
{
|
||||||
@@ -57,6 +58,7 @@ namespace lms::core::logging
|
|||||||
TRANSCODING,
|
TRANSCODING,
|
||||||
UI,
|
UI,
|
||||||
UTILS,
|
UTILS,
|
||||||
|
WT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* getModuleName(Module mod);
|
const char* getModuleName(Module mod);
|
||||||
@@ -92,7 +94,11 @@ namespace lms::core::logging
|
|||||||
|
|
||||||
virtual bool isSeverityActive(Severity severity) const = 0;
|
virtual bool isSeverityActive(Severity severity) const = 0;
|
||||||
virtual void processLog(const Log& log) = 0;
|
virtual void processLog(const Log& log) = 0;
|
||||||
|
virtual void processLog(Module module, Severity severity, std::string_view message) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr Severity defaultMinSeverity{ Severity::INFO };
|
||||||
|
std::unique_ptr<ILogger> createLogger(Severity minSeverity = defaultMinSeverity, const std::filesystem::path& logFilePath = {});
|
||||||
} // namespace lms::core::logging
|
} // namespace lms::core::logging
|
||||||
|
|
||||||
#define LMS_LOG(module, severity, message) \
|
#define LMS_LOG(module, severity, message) \
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/EnumSet.hpp"
|
|
||||||
#include "core/ILogger.hpp"
|
|
||||||
|
|
||||||
namespace lms::core::logging
|
|
||||||
{
|
|
||||||
class StreamLogger final : public ILogger
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static constexpr EnumSet<Severity> allSeverities{ Severity::FATAL, Severity::ERROR, Severity::WARNING, Severity::INFO, Severity::DEBUG };
|
|
||||||
static constexpr EnumSet<Severity> defaultSeverities{ Severity::FATAL, Severity::ERROR, Severity::WARNING, Severity::INFO };
|
|
||||||
|
|
||||||
StreamLogger(std::ostream& oss, EnumSet<Severity> severities = defaultSeverities);
|
|
||||||
|
|
||||||
bool isSeverityActive(Severity severity) const override { return _severities.contains(severity); }
|
|
||||||
void processLog(const Log& log) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::ostream& _os;
|
|
||||||
const EnumSet<Severity> _severities;
|
|
||||||
};
|
|
||||||
} // namespace lms::core::logging
|
|
||||||
@@ -21,13 +21,12 @@
|
|||||||
|
|
||||||
#include "core/ILogger.hpp"
|
#include "core/ILogger.hpp"
|
||||||
#include "core/Service.hpp"
|
#include "core/Service.hpp"
|
||||||
#include "core/StreamLogger.hpp"
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
using namespace lms;
|
using namespace lms;
|
||||||
// log to stdout
|
// log to stdout
|
||||||
core::Service<core::logging::ILogger> logger{ std::make_unique<core::logging::StreamLogger>(std::cout, core::EnumSet<core::logging::Severity>{ core::logging::Severity::FATAL, core::logging::Severity::ERROR }) };
|
core::Service<core::logging::ILogger> logger{ core::logging::createLogger(core::logging::Severity::ERROR) };
|
||||||
|
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
|
|||||||
+84
-33
@@ -20,18 +20,19 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <Wt/WApplication.h>
|
#include <Wt/WApplication.h>
|
||||||
|
#include <Wt/WLogSink.h>
|
||||||
#include <Wt/WServer.h>
|
#include <Wt/WServer.h>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/property_tree/xml_parser.hpp>
|
#include <boost/property_tree/xml_parser.hpp>
|
||||||
|
|
||||||
#include "core/IChildProcessManager.hpp"
|
#include "core/IChildProcessManager.hpp"
|
||||||
#include "core/IConfig.hpp"
|
#include "core/IConfig.hpp"
|
||||||
|
#include "core/ILogger.hpp"
|
||||||
#include "core/IOContextRunner.hpp"
|
#include "core/IOContextRunner.hpp"
|
||||||
#include "core/ITraceLogger.hpp"
|
#include "core/ITraceLogger.hpp"
|
||||||
#include "core/Service.hpp"
|
#include "core/Service.hpp"
|
||||||
#include "core/String.hpp"
|
#include "core/String.hpp"
|
||||||
#include "core/SystemPaths.hpp"
|
#include "core/SystemPaths.hpp"
|
||||||
#include "core/WtLogger.hpp"
|
|
||||||
#include "database/IDb.hpp"
|
#include "database/IDb.hpp"
|
||||||
#include "database/IQueryPlanRecorder.hpp"
|
#include "database/IQueryPlanRecorder.hpp"
|
||||||
#include "database/Session.hpp"
|
#include "database/Session.hpp"
|
||||||
@@ -64,24 +65,6 @@ namespace lms
|
|||||||
return configHttpServerThreadCount ? configHttpServerThreadCount : std::max<unsigned long>(2, std::thread::hardware_concurrency());
|
return configHttpServerThreadCount ? configHttpServerThreadCount : std::max<unsigned long>(2, std::thread::hardware_concurrency());
|
||||||
}
|
}
|
||||||
|
|
||||||
core::logging::Severity getLogMinSeverity()
|
|
||||||
{
|
|
||||||
std::string_view minSeverity{ core::Service<core::IConfig>::get()->getString("log-min-severity", "info") };
|
|
||||||
|
|
||||||
if (minSeverity == "debug")
|
|
||||||
return core::logging::Severity::DEBUG;
|
|
||||||
else if (minSeverity == "info")
|
|
||||||
return core::logging::Severity::INFO;
|
|
||||||
else if (minSeverity == "warning")
|
|
||||||
return core::logging::Severity::WARNING;
|
|
||||||
else if (minSeverity == "error")
|
|
||||||
return core::logging::Severity::ERROR;
|
|
||||||
else if (minSeverity == "fatal")
|
|
||||||
return core::logging::Severity::FATAL;
|
|
||||||
|
|
||||||
throw core::LmsException{ "Invalid config value for 'log-min-severity'" };
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::AuthenticationBackend getUIAuthenticationBackend()
|
ui::AuthenticationBackend getUIAuthenticationBackend()
|
||||||
{
|
{
|
||||||
const std::string backend{ core::stringUtils::stringToLower(core::Service<core::IConfig>::get()->getString("authentication-backend", "internal")) };
|
const std::string backend{ core::stringUtils::stringToLower(core::Service<core::IConfig>::get()->getString("authentication-backend", "internal")) };
|
||||||
@@ -109,15 +92,13 @@ namespace lms
|
|||||||
throw core::LmsException{ "Invalid config value for 'tracing-level'" };
|
throw core::LmsException{ "Invalid config value for 'tracing-level'" };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> generateWtConfig(std::string execPath, core::logging::Severity minSeverity)
|
std::vector<std::string> generateWtConfig(std::string execPath)
|
||||||
{
|
{
|
||||||
core::IConfig& config{ *core::Service<core::IConfig>::get() };
|
core::IConfig& config{ *core::Service<core::IConfig>::get() };
|
||||||
|
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
|
||||||
const std::filesystem::path wtConfigPath{ config.getPath("working-dir", "/var/lms") / "wt_config.xml" };
|
const std::filesystem::path wtConfigPath{ config.getPath("working-dir", "/var/lms") / "wt_config.xml" };
|
||||||
const std::filesystem::path wtLogFilePath{ config.getPath("log-file", "") };
|
|
||||||
const std::filesystem::path wtAccessLogFilePath{ config.getPath("access-log-file", "") };
|
|
||||||
const std::filesystem::path wtResourcesPath{ config.getPath("wt-resources", "/usr/share/Wt/resources") };
|
const std::filesystem::path wtResourcesPath{ config.getPath("wt-resources", "/usr/share/Wt/resources") };
|
||||||
|
|
||||||
args.push_back(execPath);
|
args.push_back(execPath);
|
||||||
@@ -142,19 +123,12 @@ namespace lms
|
|||||||
args.push_back("--http-address=" + std::string{ config.getString("listen-addr", "0.0.0.0") });
|
args.push_back("--http-address=" + std::string{ config.getString("listen-addr", "0.0.0.0") });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wtAccessLogFilePath.empty())
|
|
||||||
args.push_back("--accesslog=" + wtAccessLogFilePath.string());
|
|
||||||
|
|
||||||
args.push_back("--threads=" + std::to_string(getThreadCount()));
|
args.push_back("--threads=" + std::to_string(getThreadCount()));
|
||||||
|
|
||||||
// Generate the wt_config.xml file
|
// Generate the wt_config.xml file
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree pt;
|
||||||
|
|
||||||
pt.put("server.application-settings.<xmlattr>.location", "*");
|
pt.put("server.application-settings.<xmlattr>.location", "*");
|
||||||
pt.put("server.application-settings.log-file", wtLogFilePath.string());
|
|
||||||
|
|
||||||
// log-config
|
|
||||||
pt.put("server.application-settings.log-config", core::logging::WtLogger::computeLogConfig(minSeverity));
|
|
||||||
|
|
||||||
// Reverse proxy
|
// Reverse proxy
|
||||||
if (config.getBool("behind-reverse-proxy", false))
|
if (config.getBool("behind-reverse-proxy", false))
|
||||||
@@ -238,6 +212,82 @@ namespace lms
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core::logging::Severity getLogMinSeverity()
|
||||||
|
{
|
||||||
|
std::string_view minSeverity{ core::Service<core::IConfig>::get()->getString("log-min-severity", "info") };
|
||||||
|
|
||||||
|
if (minSeverity == "debug")
|
||||||
|
return core::logging::Severity::DEBUG;
|
||||||
|
else if (minSeverity == "info")
|
||||||
|
return core::logging::Severity::INFO;
|
||||||
|
else if (minSeverity == "warning")
|
||||||
|
return core::logging::Severity::WARNING;
|
||||||
|
else if (minSeverity == "error")
|
||||||
|
return core::logging::Severity::ERROR;
|
||||||
|
else if (minSeverity == "fatal")
|
||||||
|
return core::logging::Severity::FATAL;
|
||||||
|
|
||||||
|
throw core::LmsException{ "Invalid config value for 'log-min-severity'" };
|
||||||
|
}
|
||||||
|
|
||||||
|
class LmsLogSink : public Wt::WLogSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LmsLogSink(core::logging::ILogger& logger)
|
||||||
|
: _logger{ logger }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void log(const std::string& type, const std::string& scope, const std::string& message) const noexcept override
|
||||||
|
{
|
||||||
|
// Some wt code path may go here without testing logging()
|
||||||
|
if (logging(type, scope))
|
||||||
|
{
|
||||||
|
const core::logging::Severity severity{ getSeverity(type, scope) };
|
||||||
|
_logger.processLog(core::logging::Module::WT, severity, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool logging(const std::string& type, const std::string& scope) const noexcept override
|
||||||
|
{
|
||||||
|
const core::logging::Severity severity{ getSeverity(type, scope) };
|
||||||
|
return _logger.isSeverityActive(severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
static core::logging::Severity getSeverity(const std::string& type, const std::string& scope)
|
||||||
|
{
|
||||||
|
return adjustSeverity(getSeverityFromString(type), scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
static core::logging::Severity adjustSeverity(core::logging::Severity initialSeverity, std::string_view scope)
|
||||||
|
{
|
||||||
|
if (initialSeverity == core::logging::Severity::INFO && (scope == "WebRequest" || scope == "wthttp"))
|
||||||
|
return core::logging::Severity::DEBUG;
|
||||||
|
|
||||||
|
return initialSeverity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static core::logging::Severity getSeverityFromString(std::string_view type)
|
||||||
|
{
|
||||||
|
if (type == "debug")
|
||||||
|
return core::logging::Severity::DEBUG;
|
||||||
|
if (type == "info")
|
||||||
|
return core::logging::Severity::INFO;
|
||||||
|
if (type == "warning")
|
||||||
|
return core::logging::Severity::WARNING;
|
||||||
|
if (type == "error")
|
||||||
|
return core::logging::Severity::ERROR;
|
||||||
|
if (type == "fatal")
|
||||||
|
return core::logging::Severity::FATAL;
|
||||||
|
|
||||||
|
return core::logging::Severity::INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::logging::ILogger& _logger;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
@@ -275,8 +325,7 @@ namespace lms
|
|||||||
close(STDIN_FILENO);
|
close(STDIN_FILENO);
|
||||||
|
|
||||||
core::Service<core::IConfig> config{ core::createConfig(configFilePath) };
|
core::Service<core::IConfig> config{ core::createConfig(configFilePath) };
|
||||||
const core::logging::Severity minLogSeverity{ getLogMinSeverity() };
|
core::Service<core::logging::ILogger> logger{ createLogger(getLogMinSeverity(), config->getPath("log-file", "")) };
|
||||||
core::Service<core::logging::ILogger> logger{ std::make_unique<core::logging::WtLogger>(minLogSeverity) };
|
|
||||||
core::Service<core::tracing::ITraceLogger> traceLogger;
|
core::Service<core::tracing::ITraceLogger> traceLogger;
|
||||||
if (const auto level{ getTracingLevel() })
|
if (const auto level{ getTracingLevel() })
|
||||||
traceLogger.assign(core::tracing::createTraceLogger(level.value(), config->getULong("tracing-buffer-size", core::tracing::MinBufferSizeInMBytes)));
|
traceLogger.assign(core::tracing::createTraceLogger(level.value(), config->getULong("tracing-buffer-size", core::tracing::MinBufferSizeInMBytes)));
|
||||||
@@ -292,7 +341,7 @@ namespace lms
|
|||||||
std::filesystem::create_directories(config->getPath("working-dir", "/var/lms") / "cache");
|
std::filesystem::create_directories(config->getPath("working-dir", "/var/lms") / "cache");
|
||||||
|
|
||||||
// Construct WT configuration and get the argc/argv back
|
// Construct WT configuration and get the argc/argv back
|
||||||
const std::vector<std::string> wtServerArgs{ generateWtConfig(argv[0], minLogSeverity) };
|
const std::vector<std::string> wtServerArgs{ generateWtConfig(argv[0]) };
|
||||||
|
|
||||||
std::vector<const char*> wtArgv(wtServerArgs.size());
|
std::vector<const char*> wtArgv(wtServerArgs.size());
|
||||||
for (std::size_t i = 0; i < wtServerArgs.size(); ++i)
|
for (std::size_t i = 0; i < wtServerArgs.size(); ++i)
|
||||||
@@ -301,8 +350,9 @@ namespace lms
|
|||||||
wtArgv[i] = wtServerArgs[i].c_str();
|
wtArgv[i] = wtServerArgs[i].c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::io_context ioContext; // ioContext used to dispatch all the services that are out of the Wt event loop
|
LmsLogSink lmsLogSink{ *logger };
|
||||||
Wt::WServer server{ argv[0] };
|
Wt::WServer server{ argv[0] };
|
||||||
|
server.setCustomLogger(lmsLogSink);
|
||||||
server.setServerConfiguration(wtServerArgs.size(), const_cast<char**>(&wtArgv[0]));
|
server.setServerConfiguration(wtServerArgs.size(), const_cast<char**>(&wtArgv[0]));
|
||||||
|
|
||||||
// As initialization can take a while (db migration, analyze, etc.), we bind a temporary init entry point to warn the user
|
// As initialization can take a while (db migration, analyze, etc.), we bind a temporary init entry point to warn the user
|
||||||
@@ -314,6 +364,7 @@ namespace lms
|
|||||||
LMS_LOG(MAIN, INFO, "Starting init web server...");
|
LMS_LOG(MAIN, INFO, "Starting init web server...");
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
|
boost::asio::io_context ioContext; // ioContext used to dispatch all the services that are out of the Wt event loop
|
||||||
core::IOContextRunner ioContextRunner{ ioContext, getThreadCount(), "Misc" };
|
core::IOContextRunner ioContextRunner{ ioContext, getThreadCount(), "Misc" };
|
||||||
|
|
||||||
core::Service<db::IQueryPlanRecorder> queryPlanRecorder;
|
core::Service<db::IQueryPlanRecorder> queryPlanRecorder;
|
||||||
|
|||||||
@@ -28,9 +28,9 @@
|
|||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#include "core/IConfig.hpp"
|
#include "core/IConfig.hpp"
|
||||||
|
#include "core/ILogger.hpp"
|
||||||
#include "core/Random.hpp"
|
#include "core/Random.hpp"
|
||||||
#include "core/Service.hpp"
|
#include "core/Service.hpp"
|
||||||
#include "core/StreamLogger.hpp"
|
|
||||||
#include "core/SystemPaths.hpp"
|
#include "core/SystemPaths.hpp"
|
||||||
#include "database/IDb.hpp"
|
#include "database/IDb.hpp"
|
||||||
#include "database/Session.hpp"
|
#include "database/Session.hpp"
|
||||||
@@ -184,7 +184,7 @@ int main(int argc, char* argv[])
|
|||||||
namespace program_options = boost::program_options;
|
namespace program_options = boost::program_options;
|
||||||
|
|
||||||
// log to stdout
|
// log to stdout
|
||||||
core::Service<core::logging::ILogger> logger{ std::make_unique<core::logging::StreamLogger>(std::cout) };
|
core::Service<core::logging::ILogger> logger{ core::logging::createLogger() };
|
||||||
|
|
||||||
const GeneratorParameters defaultParams;
|
const GeneratorParameters defaultParams;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#include "core/EnumSet.hpp"
|
#include "core/EnumSet.hpp"
|
||||||
#include "core/StreamLogger.hpp"
|
#include "core/ILogger.hpp"
|
||||||
#include "core/String.hpp"
|
#include "core/String.hpp"
|
||||||
#include "metadata/Exception.hpp"
|
#include "metadata/Exception.hpp"
|
||||||
#include "metadata/IAudioFileParser.hpp"
|
#include "metadata/IAudioFileParser.hpp"
|
||||||
@@ -456,7 +456,7 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// log to stdout
|
// log to stdout
|
||||||
core::Service<core::logging::ILogger> logger{ std::make_unique<core::logging::StreamLogger>(std::cout, core::logging::StreamLogger::allSeverities) };
|
core::Service<core::logging::ILogger> logger{ core::logging::createLogger(core::logging::Severity::DEBUG) };
|
||||||
|
|
||||||
for (const std::string& inputFile : inputFiles)
|
for (const std::string& inputFile : inputFiles)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#include "core/IConfig.hpp"
|
#include "core/IConfig.hpp"
|
||||||
|
#include "core/ILogger.hpp"
|
||||||
#include "core/Service.hpp"
|
#include "core/Service.hpp"
|
||||||
#include "core/StreamLogger.hpp"
|
|
||||||
#include "core/SystemPaths.hpp"
|
#include "core/SystemPaths.hpp"
|
||||||
#include "database/IDb.hpp"
|
#include "database/IDb.hpp"
|
||||||
#include "database/Session.hpp"
|
#include "database/Session.hpp"
|
||||||
@@ -129,7 +129,7 @@ int main(int argc, char* argv[])
|
|||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
// log to stdout
|
// log to stdout
|
||||||
core::Service<core::logging::ILogger> logger{ std::make_unique<core::logging::StreamLogger>(std::cout) };
|
core::Service<core::logging::ILogger> logger{ core::logging::createLogger() };
|
||||||
|
|
||||||
po::options_description desc{ "Allowed options" };
|
po::options_description desc{ "Allowed options" };
|
||||||
desc.add_options()("help,h", "print usage message")("conf,c", po::value<std::string>()->default_value(core::sysconfDirectory / "lms.conf"), "LMS config file")("artists,a", "Display recommendation for artists")("releases,r", "Display recommendation for releases")("tracks,t", "Display recommendation for tracks")("max,m", po::value<unsigned>()->default_value(3), "Max similarity result count");
|
desc.add_options()("help,h", "print usage message")("conf,c", po::value<std::string>()->default_value(core::sysconfDirectory / "lms.conf"), "LMS config file")("artists,a", "Display recommendation for artists")("releases,r", "Display recommendation for releases")("tracks,t", "Display recommendation for tracks")("max,m", po::value<unsigned>()->default_value(3), "Max similarity result count");
|
||||||
|
|||||||
Reference in New Issue
Block a user