*: port to spdlog
Later commits will work on creating loggers for each component.
This commit is contained in:
parent
3a6f7e7d7d
commit
919490a8c0
|
@ -196,3 +196,6 @@
|
|||
[submodule "third_party/boost/mysql"]
|
||||
path = third_party/boost/mysql
|
||||
url = https://github.com/boostorg/mysql.git
|
||||
[submodule "third_party/spdlog"]
|
||||
path = third_party/spdlog
|
||||
url = https://github.com/gabime/spdlog
|
||||
|
|
|
@ -2,10 +2,6 @@ add_library(base_base
|
|||
assert.cpp
|
||||
backoff.cpp
|
||||
html_escape.cpp
|
||||
|
||||
# logging library
|
||||
logger.cpp
|
||||
stdout_sink.cpp
|
||||
)
|
||||
|
||||
lobbyserver_target(base_base)
|
||||
|
@ -13,6 +9,7 @@ lobbyserver_target(base_base)
|
|||
target_link_libraries(base_base PUBLIC
|
||||
# techinically not needed anymore but /shrug
|
||||
base::impl
|
||||
spdlog::spdlog
|
||||
)
|
||||
|
||||
add_library(base::base ALIAS base_base)
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <base/logger.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace base {
|
||||
|
||||
static Logger gAssertLogger{MakeChannelId(MessageSource::Base, MessageComponentSource::Base_Assertions)};
|
||||
|
||||
[[noreturn]] void ExitMsg(const char* message) {
|
||||
gAssertLogger.Fatal("{}", message);
|
||||
spdlog::error("{}", message);
|
||||
std::exit(0xAF);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
#include <base/assert.hpp>
|
||||
#include <base/logger.hpp>
|
||||
#include <base/types.hpp>
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace logger_detail {
|
||||
|
||||
static constexpr std::string_view SeverityToString(MessageSeverity sev) {
|
||||
// This must match order of logger_detail::MessageSeverity.
|
||||
const char* MessageSeverityStringTable[] = { "Debug", "Info", "Warn", "Error", "Fatal" };
|
||||
return MessageSeverityStringTable[static_cast<std::size_t>(sev)];
|
||||
}
|
||||
|
||||
constexpr static auto ChannelToString(ChannelId channelId) -> std::string_view {
|
||||
MessageSource src;
|
||||
MessageComponentSource comp;
|
||||
|
||||
ChannelIdToComponents(channelId, src, comp);
|
||||
|
||||
switch(src) {
|
||||
case MessageSource::Main: {
|
||||
switch(comp) {
|
||||
case MessageComponentSource::Main_Global: return "Main::Global";
|
||||
default: BASE_CHECK(false, "Invalid component source");
|
||||
}
|
||||
};
|
||||
|
||||
case MessageSource::Base: {
|
||||
switch(comp) {
|
||||
case MessageComponentSource::Base_Assertions: return "Base::Assert";
|
||||
default: BASE_CHECK(false, "Invalid component source");
|
||||
}
|
||||
};
|
||||
|
||||
case MessageSource::Http: {
|
||||
switch(comp) {
|
||||
case MessageComponentSource::Http_Server: return "HTTP::Server";
|
||||
case MessageComponentSource::Http_WebSocketClient: return "HTTP::WebSocketClient";
|
||||
default: BASE_CHECK(false, "Invalid component source");
|
||||
}
|
||||
};
|
||||
|
||||
case MessageSource::Server: {
|
||||
switch(comp) {
|
||||
case MessageComponentSource::Server_Server: return "LobbyServer2::Server";
|
||||
default: BASE_CHECK(false, "Invalid component source");
|
||||
}
|
||||
};
|
||||
|
||||
default: BASE_CHECK(false, "Invalid channel source {:04x}", static_cast<u16>(src));
|
||||
}
|
||||
}
|
||||
|
||||
struct LoggerThreadData {
|
||||
// Logger thread stuff
|
||||
std::thread loggerThread;
|
||||
std::mutex logQueueMutex;
|
||||
std::condition_variable logQueueCv;
|
||||
std::deque<MessageData> logQueue;
|
||||
|
||||
bool logThreadShutdown = false;
|
||||
|
||||
// N.B: This is stored/cached here just because it really does
|
||||
// *NOT* need to be in a hot path.
|
||||
const std::chrono::time_zone* timeZone = std::chrono::current_zone();
|
||||
|
||||
bool ShouldUnblock() {
|
||||
// Always unblock if the logger thread needs to be shut down.
|
||||
if(logThreadShutdown)
|
||||
return true;
|
||||
|
||||
return !logQueue.empty();
|
||||
}
|
||||
|
||||
void PushMessage(MessageData&& md) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(logQueueMutex);
|
||||
logQueue.emplace_back(std::move(md));
|
||||
}
|
||||
logQueueCv.notify_one();
|
||||
}
|
||||
};
|
||||
|
||||
Unique<LoggerThreadData> threadData;
|
||||
|
||||
void LoggerGlobalState::LoggerThread() {
|
||||
auto& self = The();
|
||||
|
||||
// Fancy thread names.
|
||||
pthread_setname_np(pthread_self(), "LoggerThread");
|
||||
|
||||
while(true) {
|
||||
std::unique_lock<std::mutex> lk(threadData->logQueueMutex);
|
||||
if(threadData->logQueue.empty()) {
|
||||
// Await for messages.
|
||||
threadData->logQueueCv.wait(lk, []() { return threadData->ShouldUnblock(); });
|
||||
}
|
||||
|
||||
// Flush the logger queue until there are no more messages.
|
||||
while(!threadData->logQueue.empty()) {
|
||||
self.OutputMessage(threadData->logQueue.back());
|
||||
threadData->logQueue.pop_back();
|
||||
}
|
||||
|
||||
// Shutdown if requested.
|
||||
if(threadData->logThreadShutdown)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LoggerGlobalState& LoggerGlobalState::The() {
|
||||
static LoggerGlobalState storage;
|
||||
return storage;
|
||||
}
|
||||
|
||||
LoggerGlobalState::LoggerGlobalState() {
|
||||
// Spawn the logger thread
|
||||
threadData = std::make_unique<LoggerThreadData>();
|
||||
threadData->loggerThread = std::thread(&LoggerGlobalState::LoggerThread);
|
||||
}
|
||||
|
||||
LoggerGlobalState::~LoggerGlobalState() {
|
||||
// Shut down the logger thread
|
||||
threadData->logThreadShutdown = true;
|
||||
threadData->logQueueCv.notify_all();
|
||||
threadData->loggerThread.join();
|
||||
}
|
||||
|
||||
void LoggerGlobalState::AttachSink(Sink& sink) {
|
||||
sinks.push_back(&sink);
|
||||
}
|
||||
|
||||
void LoggerGlobalState::OutputMessage(const MessageData& data) {
|
||||
// give up early if no sinks are attached
|
||||
if(sinks.empty())
|
||||
return;
|
||||
|
||||
if(data.severity < logLevel)
|
||||
return;
|
||||
|
||||
auto formattedLoggerMessage =
|
||||
std::format("[{:%F %H:%M:%S}|{}|{}] {}", std::chrono::floor<std::chrono::milliseconds>(threadData->timeZone->to_local(data.time)),
|
||||
SeverityToString(data.severity), ChannelToString(data.channelId), data.message);
|
||||
|
||||
for(auto sink : sinks)
|
||||
sink->OutputMessage(formattedLoggerMessage);
|
||||
}
|
||||
|
||||
} // namespace logger_detail
|
||||
|
||||
Logger& Logger::Global() {
|
||||
static Logger globalLogger;
|
||||
return globalLogger;
|
||||
}
|
||||
|
||||
void Logger::VOut(MessageSeverity severity, std::string_view format, std::format_args args) {
|
||||
logger_detail::MessageData data {
|
||||
.time = std::chrono::system_clock::now(), .severity = severity, .channelId = channelId, .message = std::vformat(format, args)
|
||||
};
|
||||
|
||||
// Push data into logger thread.
|
||||
logger_detail::threadData->PushMessage(std::move(data));
|
||||
}
|
||||
|
||||
} // namespace base
|
|
@ -1,212 +0,0 @@
|
|||
//! Logging utilities for the Support Library
|
||||
//! Using Standard C++ <format>
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <base/types.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace logger_detail {
|
||||
|
||||
enum class MessageSeverity { Debug, Info, Warning, Error, Fatal };
|
||||
|
||||
/// A message source. In our tree, this is essentially defined as
|
||||
/// each library the server's made up of.
|
||||
enum class MessageSource : u16 { Main = 0x1000, Base, Http, Server };
|
||||
|
||||
/// A component source. This basically defines "what" part of a source
|
||||
/// is creating the message. For instance, the HTTP library has multiple
|
||||
/// components which can each log messages.
|
||||
enum class MessageComponentSource : u16 {
|
||||
// The "default" global logger channel
|
||||
Main_Global = 0x1000,
|
||||
|
||||
Base_Assertions = 0x10,
|
||||
|
||||
Http_Server = 0x50,
|
||||
Http_Router,
|
||||
Http_WebSocketClient,
|
||||
|
||||
Server_Server = 0x60,
|
||||
};
|
||||
|
||||
/// A channel ID. `enum class`es are used to avoid confusion with a normal u32,
|
||||
/// and to also add addional interface type safety.
|
||||
///
|
||||
/// A channel ID looks something like:
|
||||
/// ssssssss ssssssss cccccccc cccccccc
|
||||
///
|
||||
/// Where:
|
||||
/// s: message source
|
||||
/// c: message component source
|
||||
enum class ChannelId : u32 {};
|
||||
|
||||
/// Create a channel ID from a source and component source.
|
||||
constexpr static ChannelId MakeChannelId(MessageSource source, MessageComponentSource component) {
|
||||
auto srcbits = std::bit_cast<u16>(source);
|
||||
auto cmpbits = std::bit_cast<u16>(component);
|
||||
|
||||
return static_cast<ChannelId>((static_cast<u32>(srcbits) << 16 | cmpbits));
|
||||
}
|
||||
|
||||
/// Splits a channel ID into its individual components.
|
||||
constexpr static void ChannelIdToComponents(ChannelId id, MessageSource& src, MessageComponentSource& component) {
|
||||
src = static_cast<MessageSource>((static_cast<u32>(id) & 0xffff0000) >> 16);
|
||||
component = static_cast<MessageComponentSource>(static_cast<u32>(id) & 0x0000ffff);
|
||||
}
|
||||
|
||||
/// The default global channel ID.
|
||||
constexpr static auto ChannelGlobal = MakeChannelId(MessageSource::Main, MessageComponentSource::Main_Global);
|
||||
|
||||
/// Message data. This is only used by logger sinks.
|
||||
struct MessageData {
|
||||
std::chrono::system_clock::time_point time;
|
||||
MessageSeverity severity;
|
||||
|
||||
ChannelId channelId; // the channel ID.
|
||||
|
||||
std::string message; // DO NOT SET THIS, IT WILL BE OVERWRITTEN AND I WILL BE VERY SAD -lily
|
||||
};
|
||||
|
||||
/// A logger sink. Outputs messages to some device (a TTY), a file,
|
||||
/// what have you. Basically a interface for the logger to spit stuff out.
|
||||
///
|
||||
/// # Notes
|
||||
/// Sinks do not run on the main application thread. Instead, they run on a
|
||||
/// single Support Library internal thread which the only purpose of is to
|
||||
/// stream logger messages and output them, from a internally managed queue.
|
||||
///
|
||||
/// This is techinically a implementation detail, but for implementers of logger
|
||||
/// sinks it's probably a good idea for them to know just in case.
|
||||
///
|
||||
/// Do note that you probably don't have to actually do any thread-safety magic
|
||||
/// in your sink implementation, since it's only a single thread/etc...
|
||||
struct Sink {
|
||||
virtual void OutputMessage(std::string_view message) = 0;
|
||||
};
|
||||
|
||||
/// Shared global state all loggers use.
|
||||
struct LoggerGlobalState {
|
||||
static LoggerGlobalState& The();
|
||||
|
||||
void AttachSink(Sink& sink);
|
||||
|
||||
void OutputMessage(const MessageData& data);
|
||||
|
||||
/// Get the current log level.
|
||||
MessageSeverity GetLogLevel() const { return logLevel; }
|
||||
|
||||
/// Set the current log level.
|
||||
void SetLogLevel(MessageSeverity newLogLevel) { logLevel = newLogLevel; }
|
||||
|
||||
private:
|
||||
LoggerGlobalState();
|
||||
~LoggerGlobalState();
|
||||
|
||||
std::vector<Sink*> sinks;
|
||||
MessageSeverity logLevel { MessageSeverity::Info };
|
||||
|
||||
static void LoggerThread();
|
||||
};
|
||||
|
||||
inline auto& GlobalState() {
|
||||
return LoggerGlobalState::The();
|
||||
}
|
||||
|
||||
} // namespace logger_detail
|
||||
|
||||
using logger_detail::ChannelId;
|
||||
using logger_detail::MessageComponentSource;
|
||||
using logger_detail::MessageSource;
|
||||
|
||||
using logger_detail::MakeChannelId;
|
||||
|
||||
/// Attach a sink to all Support loggers; allowing it to output logger messages.
|
||||
inline void AttachSink(logger_detail::Sink& sink) {
|
||||
logger_detail::GlobalState().AttachSink(sink);
|
||||
}
|
||||
|
||||
inline logger_detail::MessageSeverity GetLogLevel() {
|
||||
return logger_detail::GlobalState().GetLogLevel();
|
||||
}
|
||||
|
||||
inline void SetLogLevel(logger_detail::MessageSeverity newLevel) {
|
||||
return logger_detail::GlobalState().SetLogLevel(newLevel);
|
||||
}
|
||||
|
||||
struct Logger {
|
||||
using MessageSeverity = logger_detail::MessageSeverity;
|
||||
using MessageData = logger_detail::MessageData;
|
||||
using Sink = logger_detail::Sink;
|
||||
|
||||
/// Get the global instance of the logger.
|
||||
static Logger& Global();
|
||||
|
||||
Logger() : Logger(logger_detail::ChannelGlobal) {}
|
||||
|
||||
constexpr explicit Logger(ChannelId channel) { this->channelId = channel; }
|
||||
|
||||
Logger(const Logger&) = delete;
|
||||
Logger(Logger&&) = delete;
|
||||
|
||||
template <class... Args>
|
||||
inline void Debug(std::string_view fmt, Args... args) {
|
||||
VOut(MessageSeverity::Debug, fmt, std::make_format_args(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Info(std::string_view fmt, Args... args) {
|
||||
VOut(MessageSeverity::Info, fmt, std::make_format_args(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Warning(std::string_view fmt, Args... args) {
|
||||
VOut(MessageSeverity::Warning, fmt, std::make_format_args(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Error(std::string_view fmt, Args... args) {
|
||||
VOut(MessageSeverity::Error, fmt, std::make_format_args(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Fatal(std::string_view fmt, Args... args) {
|
||||
VOut(MessageSeverity::Fatal, fmt, std::make_format_args(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
private:
|
||||
void VOut(MessageSeverity severity, std::string_view format, std::format_args args);
|
||||
|
||||
ChannelId channelId;
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
constexpr void LogDebug(std::string_view format, Args... args) {
|
||||
Logger::Global().Debug(format, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
constexpr void LogInfo(std::string_view format, Args... args) {
|
||||
Logger::Global().Info(format, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
constexpr void LogWarning(std::string_view format, Args... args) {
|
||||
Logger::Global().Warning(format, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
constexpr void LogError(std::string_view format, Args... args) {
|
||||
Logger::Global().Error(format, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
constexpr void LogFatal(std::string_view format, Args... args) {
|
||||
Logger::Global().Fatal(format, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace base
|
|
@ -14,6 +14,7 @@ add_library(base_http
|
|||
lobbyserver_target(base_http)
|
||||
|
||||
target_link_libraries(base_http PUBLIC
|
||||
spdlog::spdlog
|
||||
base::impl
|
||||
Boost::url
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
#include <sys/socket.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <boost/beast/core/flat_buffer.hpp>
|
||||
#include <boost/beast/http/read.hpp>
|
||||
|
@ -71,7 +71,8 @@ namespace base::http {
|
|||
|
||||
struct Server::Impl {
|
||||
struct Session {
|
||||
Session(Impl& impl, Server::StreamType&& stream) : impl(impl), stream(std::move(stream)) {}
|
||||
Session(Impl& impl, Server::StreamType&& stream)
|
||||
: impl(impl), stream(std::move(stream)) {}
|
||||
|
||||
void Close() {
|
||||
if(stream.socket().is_open()) {
|
||||
|
@ -107,7 +108,7 @@ namespace base::http {
|
|||
}
|
||||
} catch(bsys::system_error& ec) {
|
||||
// if(ec.code() != beast::http::error::end_of_stream)
|
||||
// logger.Error("Error in http::BasicServer::DoSession(): {}", ec.what());
|
||||
// spdlog::error("Error in http::BasicServer::DoSession(): {}", ec.what());
|
||||
}
|
||||
|
||||
// todo: standalone close() function
|
||||
|
@ -180,7 +181,8 @@ namespace base::http {
|
|||
using RouteVariant = std::variant<Server::RouteHandler, Server::WebSocketRouteHandler>;
|
||||
|
||||
template <class ProtocolEndpoint>
|
||||
Impl(asio::any_io_executor ioc, ProtocolEndpoint ep) : exec(ioc), ep(ep), acceptor(ioc) {}
|
||||
Impl(asio::any_io_executor ioc, ProtocolEndpoint ep)
|
||||
: exec(ioc), ep(ep), acceptor(ioc) {}
|
||||
|
||||
void On(beast::http::verb verb, std::string_view path, Server::RouteHandler handler) {
|
||||
handlerStorage.emplace_back(handler);
|
||||
|
@ -192,7 +194,7 @@ namespace base::http {
|
|||
|
||||
if(errstr) {
|
||||
// error inserting into tree
|
||||
logger.Error("Error inserting route \"{}\" into tree: {}", path, errstr);
|
||||
spdlog::error("Error inserting route \"{}\" into tree: {}", path, errstr);
|
||||
free(errstr);
|
||||
return;
|
||||
}
|
||||
|
@ -205,7 +207,7 @@ namespace base::http {
|
|||
&errstr);
|
||||
if(errstr) {
|
||||
// error inserting into tree
|
||||
logger.Error("Error inserting route \"{}\" into tree: {}", path, errstr);
|
||||
spdlog::error("Error inserting route \"{}\" into tree: {}", path, errstr);
|
||||
free(errstr);
|
||||
return;
|
||||
}
|
||||
|
@ -216,7 +218,7 @@ namespace base::http {
|
|||
char* errstr { nullptr };
|
||||
tree.compile(&errstr);
|
||||
if(errstr) {
|
||||
logger.Error("Error compiling route tree: {}", errstr);
|
||||
spdlog::error("Error compiling route tree: {}", errstr);
|
||||
free(errstr);
|
||||
return false;
|
||||
}
|
||||
|
@ -315,7 +317,7 @@ namespace base::http {
|
|||
using reuse_port = asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT>;
|
||||
acceptor.set_option(reuse_port(true));
|
||||
|
||||
logger.Info("Able to enable SO_NODELAY; doing so");
|
||||
spdlog::info("Able to enable SO_NODELAY; doing so");
|
||||
acceptor.set_option(asio::ip::tcp::no_delay { true });
|
||||
}
|
||||
|
||||
|
@ -332,7 +334,7 @@ namespace base::http {
|
|||
} catch(bsys::system_error& ec) {
|
||||
// Filter out "operation cancelled", because that's not really an error we need to know about.
|
||||
if(ec.code() != asio::error::operation_aborted)
|
||||
logger.Error("Error in http::BasicServer::Listener(): {}", ec.what());
|
||||
spdlog::error("Error in http::BasicServer::Listener(): {}", ec.what());
|
||||
}
|
||||
|
||||
listening = false;
|
||||
|
@ -372,8 +374,6 @@ namespace base::http {
|
|||
bool listening { false };
|
||||
|
||||
asio::basic_socket_acceptor<GenericProtocol> acceptor;
|
||||
|
||||
Logger logger { MakeChannelId(MessageSource::Http, MessageComponentSource::Http_Server) };
|
||||
};
|
||||
|
||||
Server::Server(asio::any_io_executor ioc, asio::ip::tcp::endpoint ep) {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <http/request.hpp>
|
||||
#include <http/response.hpp>
|
||||
#include <http/websocket_client.hpp>
|
||||
#include <base/logger.hpp>
|
||||
#include <base/types.hpp>
|
||||
|
||||
namespace base::http {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <http/websocket_client.hpp>
|
||||
#include <http/proxy_address.hpp>
|
||||
#include <base/assert.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace base::http {
|
||||
|
||||
|
@ -83,7 +84,7 @@ namespace base::http {
|
|||
asio::deferred);
|
||||
}
|
||||
} catch(bsys::error_code& ec) {
|
||||
logger.Error("Error when closing (not fatal): {}", ec.what());
|
||||
spdlog::error("Error when closing (not fatal): {}", ec.what());
|
||||
}
|
||||
|
||||
// notify the send task that it needs to stop
|
||||
|
@ -138,7 +139,7 @@ namespace base::http {
|
|||
self->sendQueue.shrink_to_fit();
|
||||
}
|
||||
} catch(bsys::system_error& ec) {
|
||||
// logger.Error("failure in write end: {}", ec.what());
|
||||
// spdlog::error("failure in write end: {}", ec.what());
|
||||
}
|
||||
|
||||
co_await self->Close();
|
||||
|
@ -184,7 +185,7 @@ namespace base::http {
|
|||
} catch(bsys::system_error& ec) {
|
||||
// TODO: this should be re-enabled but doesn't seem to limit properly
|
||||
// if(ec.code() != beast::websocket::error::closed || ec.code() != asio::error::eof)
|
||||
// logger.Error("fail in read end {}", ec.what());
|
||||
// spdlog::error("fail in read end {}", ec.what());
|
||||
}
|
||||
|
||||
co_await self->Close();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <http/request.hpp>
|
||||
#include <http/websocket_message.hpp>
|
||||
#include <base/async_condition_variable.hpp>
|
||||
#include <base/logger.hpp>
|
||||
#include <base/types.hpp>
|
||||
|
||||
namespace base::http {
|
||||
|
@ -70,8 +69,6 @@ namespace base::http {
|
|||
|
||||
Request upgrade;
|
||||
|
||||
Logger logger { MakeChannelId(MessageSource::Http, MessageComponentSource::Http_WebSocketClient) };
|
||||
|
||||
constexpr static u32 MAX_MESSAGES_IN_QUEUE = 256;
|
||||
|
||||
Awaitable<void> WriteEnd();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include <base/assert.hpp>
|
||||
#include <base/logger.hpp>
|
||||
#include <base/types.hpp>
|
||||
|
||||
namespace base::http {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "DirtySockServer.hpp"
|
||||
|
||||
constexpr static auto MAX_PAYLOAD_SIZE = 4 * (1024 * 1024);
|
||||
|
@ -30,7 +32,7 @@ namespace ls {
|
|||
|
||||
// Sanity check. I don't expect game payloa
|
||||
if(header.payloadSize > MAX_PAYLOAD_SIZE) {
|
||||
base::LogError("WOAH! Message size {} MB larger than {}MB..", (static_cast<float>(header.payloadSize) / 1024 / 1024), (static_cast<float>(MAX_PAYLOAD_SIZE) / 1024 / 1024));
|
||||
spdlog::error("WOAH! Message size {} MB larger than {}MB..", (static_cast<float>(header.payloadSize) / 1024 / 1024), (static_cast<float>(MAX_PAYLOAD_SIZE) / 1024 / 1024));
|
||||
co_return nullptr;
|
||||
}
|
||||
|
||||
|
@ -48,7 +50,7 @@ namespace ls {
|
|||
co_return MessageFactory::CreateAndParseMessage(header, propertyBuffer);
|
||||
} catch(bsys::system_error& ec) {
|
||||
if(ec.code() != asio::error::operation_aborted)
|
||||
base::LogError("Error in DirtySockClient::WriteMessage(): {}", ec.what());
|
||||
spdlog::error("Error in DirtySockClient::WriteMessage(): {}", ec.what());
|
||||
co_return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +64,7 @@ namespace ls {
|
|||
co_await asio::async_write(stream, asio::buffer(buf), asio::deferred);
|
||||
} catch(bsys::system_error& ec) {
|
||||
if(ec.code() != asio::error::operation_aborted)
|
||||
base::LogError("Error in DirtySockClient::WriteMessage(): {}", ec.what());
|
||||
spdlog::error("Error in DirtySockClient::WriteMessage(): {}", ec.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,14 +78,14 @@ namespace ls {
|
|||
co_await message->Process(shared_from_this());
|
||||
} else {
|
||||
// This will occur if parsing fails or etc.
|
||||
base::LogError("Error parsing message, closing connection");
|
||||
spdlog::error("Error parsing message, closing connection");
|
||||
Close();
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
} catch(bsys::system_error& ec) {
|
||||
if(ec.code() != asio::error::operation_aborted)
|
||||
base::LogError("Error in DirtySockClient::Run(): {}", ec.what());
|
||||
spdlog::error("Error in DirtySockClient::Run(): {}", ec.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "DirtySockServer.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "DirtySockClient.hpp"
|
||||
|
||||
namespace ls {
|
||||
|
@ -32,7 +34,7 @@ namespace ls {
|
|||
acceptor.bind(endpoint);
|
||||
acceptor.listen(asio::socket_base::max_listen_connections);
|
||||
|
||||
logger.Info("DirtySockServer listening on {}:{}", endpoint.address().to_string(), endpoint.port());
|
||||
spdlog::info("DirtySockServer listening on {}:{}", endpoint.address().to_string(), endpoint.port());
|
||||
|
||||
while(true) {
|
||||
auto socket = co_await acceptor.async_accept(asio::deferred);
|
||||
|
@ -42,7 +44,7 @@ namespace ls {
|
|||
}
|
||||
} catch(bsys::system_error& ec) {
|
||||
if(ec.code() != asio::error::operation_aborted)
|
||||
logger.Error("Error in DirtySockServer::Listener(): {}", ec.what());
|
||||
spdlog::error("Error in DirtySockServer::Listener(): {}", ec.what());
|
||||
}
|
||||
|
||||
co_return;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <base/fourcc.hpp>
|
||||
#include <base/logger.hpp>
|
||||
#include <impl/asio_config.hpp>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
@ -40,7 +39,7 @@ namespace ls {
|
|||
std::set<base::Ref<DirtySockClient>> clientSet;
|
||||
|
||||
// i'm moving to spdlog fuck this
|
||||
base::Logger logger { base::MakeChannelId(base::MessageSource::Server, base::MessageComponentSource::Server_Server) };
|
||||
|
||||
};
|
||||
|
||||
} // namespace ls
|
|
@ -1,6 +1,6 @@
|
|||
#include "IMessage.hpp"
|
||||
|
||||
#include <base/logger.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <impl/asio_config.hpp>
|
||||
|
||||
// So debug message can just reply
|
||||
|
@ -153,11 +153,11 @@ namespace ls {
|
|||
base::Awaitable<void> Process(base::Ref<ls::DirtySockClient> client) override {
|
||||
auto* fccbytes = std::bit_cast<u8*>(&header.typeCode);
|
||||
|
||||
base::LogInfo("Debug Message FourCC lo: \"{:c}{:c}{:c}{:c}\"", fccbytes[0], fccbytes[1], fccbytes[2], fccbytes[3]);
|
||||
base::LogInfo("Debug Message Properties:");
|
||||
spdlog::info("Debug Message FourCC lo: \"{:c}{:c}{:c}{:c}\"", fccbytes[0], fccbytes[1], fccbytes[2], fccbytes[3]);
|
||||
spdlog::info("Debug Message Properties:");
|
||||
|
||||
for(auto [key, value] : properties)
|
||||
base::LogInfo("{}: {}", key, value);
|
||||
spdlog::info("{}: {}", key, value);
|
||||
|
||||
// :( but it works to just replay the message.
|
||||
co_await client->WriteMessage(std::make_shared<DebugMessage>(*this));
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "Server.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "DirtySockServer.hpp"
|
||||
#include "impl/asio_config.hpp"
|
||||
|
||||
|
@ -20,7 +22,7 @@ namespace ls {
|
|||
|
||||
if(!lobbyServer->Listening()) {
|
||||
// uh oh worm..
|
||||
logger.Error("for some reason lobby server isnt listening..");
|
||||
spdlog::error("for some reason lobby server isnt listening..");
|
||||
co_return;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
#include <impl/asio_config.hpp>
|
||||
#include <set>
|
||||
|
||||
#include "base/logger.hpp"
|
||||
|
||||
|
||||
namespace ls {
|
||||
|
||||
struct DirtySockServer;
|
||||
|
@ -35,7 +32,7 @@ namespace ls {
|
|||
|
||||
Config config;
|
||||
|
||||
base::Logger logger { base::MakeChannelId(base::MessageSource::Server, base::MessageComponentSource::Server_Server) };
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
21
src/main.cpp
21
src/main.cpp
|
@ -1,11 +1,12 @@
|
|||
#include <base/assert.hpp>
|
||||
#include <base/stdout_sink.hpp>
|
||||
#include <base/types.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <boost/asio/thread_pool.hpp>
|
||||
#include <thread>
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "Server.hpp"
|
||||
|
||||
asio::io_context ioc(1);
|
||||
|
@ -18,10 +19,10 @@ base::Awaitable<void> CoWaitForSignal() {
|
|||
try {
|
||||
co_await interruptSignal.async_wait(asio::deferred);
|
||||
} catch(bsys::system_error& ec) {
|
||||
base::LogError("Error waiting for signal? {}", ec.what());
|
||||
spdlog::error("Error waiting for signal? {}", ec.what());
|
||||
}
|
||||
|
||||
base::LogInfo("SIGINT/SIGTERM recieved, stopping server...");
|
||||
spdlog::info("SIGINT/SIGTERM recieved, stopping server...");
|
||||
|
||||
// After this the main coroutine will handle cleanly shutting down
|
||||
co_await server->Stop();
|
||||
|
@ -35,8 +36,6 @@ base::Awaitable<void> CoMain(const ls::Server::Config& config) {
|
|||
}
|
||||
|
||||
int main() {
|
||||
base::LoggerAttachStdout();
|
||||
|
||||
auto config = ls::Server::Config {};
|
||||
|
||||
try {
|
||||
|
@ -48,29 +47,29 @@ int main() {
|
|||
auto buddy_port_ptr = table["lobbyserver"]["buddy_listen_port"].as_integer();
|
||||
|
||||
if(!addr_ptr || !lobby_port_ptr || !buddy_port_ptr) {
|
||||
base::LogError("Invalid configuration file \"{}\".", CONFIG_FILE);
|
||||
spdlog::error("Invalid configuration file \"{}\".", CONFIG_FILE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(lobby_port_ptr->get() > 65535) {
|
||||
base::LogError("Invalid lobby listen port \"{}\", should be 65535 or less", lobby_port_ptr->get());
|
||||
spdlog::error("Invalid lobby listen port \"{}\", should be 65535 or less", lobby_port_ptr->get());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(buddy_port_ptr->get() > 65535) {
|
||||
base::LogError("Invalid buddy listen port \"{}\", should be 65535 or less", buddy_port_ptr->get());
|
||||
spdlog::error("Invalid buddy listen port \"{}\", should be 65535 or less", buddy_port_ptr->get());
|
||||
return 1;
|
||||
}
|
||||
|
||||
config.buddyListenEndpoint = { asio::ip::make_address(addr_ptr->get()), static_cast<u16>(buddy_port_ptr->get()) };
|
||||
config.lobbyListenEndpoint = { asio::ip::make_address(addr_ptr->get()), static_cast<u16>(lobby_port_ptr->get()) };
|
||||
} else {
|
||||
base::LogError("Invalid configuration file \"{}\"", CONFIG_FILE);
|
||||
spdlog::error("Invalid configuration file \"{}\"", CONFIG_FILE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} catch(toml::parse_error& err) {
|
||||
base::LogError("Error parsing configuration file \"{}\": {}", CONFIG_FILE, err.what());
|
||||
spdlog::error("Error parsing configuration file \"{}\": {}", CONFIG_FILE, err.what());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -92,7 +91,7 @@ int main() {
|
|||
BASE_CHECK(false, "Unhandled exception in server main loop: {}", e.what());
|
||||
}
|
||||
} else {
|
||||
base::LogInfo("Server returned, exiting process\n");
|
||||
spdlog::info("Server returned, exiting process\n");
|
||||
// done
|
||||
ioc.stop();
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#include <impl/asio_config.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "base/logger.hpp"
|
||||
#include "../IMessage.hpp"
|
||||
|
||||
LS_MESSAGE(PingMessage, "~png") {
|
||||
LS_MESSAGE_CTOR(PingMessage, "~png")
|
||||
|
||||
base::Awaitable<void> Process(base::Ref<ls::DirtySockClient> client) override {
|
||||
base::LogInfo("Got ping message!");
|
||||
spdlog::info("Got ping message!");
|
||||
co_return;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
add_subdirectory(boost)
|
||||
add_subdirectory(tomlplusplus)
|
||||
|
||||
#set(SPDLOG_USE_STD_FORMAT ON)
|
||||
add_subdirectory(spdlog)
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ae525b75c31adaad130dd4501d37ff632ec5eade
|
Loading…
Reference in New Issue