From 12d138bbab1ca5b925f90436be14624e6db37fc2 Mon Sep 17 00:00:00 2001 From: jf99 Date: Wed, 6 Jan 2021 13:32:19 +0100 Subject: [PATCH 1/7] add logging interface --- src/HttpContext.h | 9 ++++++--- src/Log.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/Log.h diff --git a/src/HttpContext.h b/src/HttpContext.h index 9a4cc346b..c32e5c1bd 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -25,9 +25,9 @@ #include "HttpResponseData.h" #include "AsyncSocket.h" #include "WebSocketData.h" +#include "Log.h" #include -#include #include "f2/function2.hpp" namespace uWS { @@ -155,9 +155,13 @@ struct HttpContext { httpContextData->router.getUserData() = {(HttpResponse *) s, httpRequest}; if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl())) { /* We have to force close this socket as we have no handler for it */ + log("No handler for route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 1); us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); return nullptr; } + else { + log("Successfully handled route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 3); + } /* First of all we need to check if this socket was deleted due to upgrade */ if (httpContextData->upgradedWebSocket) { @@ -177,8 +181,7 @@ struct HttpContext { /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */ if (!((HttpResponse *) s)->hasResponded() && !httpResponseData->onAborted) { - /* Throw exception here? */ - std::cerr << "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!" << std::endl; + log("Error: Returning from a request handler without responding or attaching an abort handler is forbidden!", 0); std::terminate(); } diff --git a/src/Log.h b/src/Log.h new file mode 100644 index 000000000..440d78e50 --- /dev/null +++ b/src/Log.h @@ -0,0 +1,28 @@ +#ifndef UWS_LOG_H +#define UWS_LOG_H +#include +#include +#include + +namespace uWS { + +/*! + * \brief Log a message. The user of this lib is free to override this function object with a custom logger. + * \param [in] message The message to be logged. + * \param [in] logLevel The severity of the message. 0 is error, 1 is warning, 2 is info. With each increment the severity decrements. + */ +typedef std::function LogFunction; + +inline LogFunction log = [](const std::string& message, int logLevel) -> void { + if(logLevel <= 1) { + std::cerr << message << std::endl; + } + else { + std::cout << message << std::endl; + } +}; + +} // namespace uWS + +#endif // UWS_LOG_H + From 99e2de9c6b1607eaa0e7b82d14a731cf93c159cb Mon Sep 17 00:00:00 2001 From: jf99 Date: Fri, 8 Jan 2021 11:04:13 +0100 Subject: [PATCH 2/7] make log verbosity compile-time configurable --- src/HttpContext.h | 4 ++++ src/Log.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/HttpContext.h b/src/HttpContext.h index c32e5c1bd..407f24c05 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -155,13 +155,17 @@ struct HttpContext { httpContextData->router.getUserData() = {(HttpResponse *) s, httpRequest}; if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl())) { /* We have to force close this socket as we have no handler for it */ + #if UWS_LOG_LEVEL <= 1 log("No handler for route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 1); + #endif us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); return nullptr; } + #if UWS_LOG_LEVEL <= 3 else { log("Successfully handled route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 3); } + #endif /* First of all we need to check if this socket was deleted due to upgrade */ if (httpContextData->upgradedWebSocket) { diff --git a/src/Log.h b/src/Log.h index 440d78e50..8e91980e8 100644 --- a/src/Log.h +++ b/src/Log.h @@ -4,6 +4,8 @@ #include #include +#define UWS_LOG_LEVEL 0 // override this to get more verbose logging + namespace uWS { /*! From 6d40144df4d8ce25f1c6750183a26f1ed11d4297 Mon Sep 17 00:00:00 2001 From: jf99 Date: Mon, 11 Jan 2021 13:08:41 +0100 Subject: [PATCH 3/7] check loglevel in UWS_LOG_REQUEST macro --- src/HttpContext.h | 10 +++------- src/Log.h | 6 ++++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/HttpContext.h b/src/HttpContext.h index 407f24c05..6a27d97f5 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -155,17 +155,13 @@ struct HttpContext { httpContextData->router.getUserData() = {(HttpResponse *) s, httpRequest}; if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl())) { /* We have to force close this socket as we have no handler for it */ - #if UWS_LOG_LEVEL <= 1 - log("No handler for route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 1); - #endif + UWS_LOG_REQUEST("No handler for route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 1); us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); return nullptr; } - #if UWS_LOG_LEVEL <= 3 else { - log("Successfully handled route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 3); + UWS_LOG_REQUEST("Successfully handled route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 3); } - #endif /* First of all we need to check if this socket was deleted due to upgrade */ if (httpContextData->upgradedWebSocket) { @@ -185,7 +181,7 @@ struct HttpContext { /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */ if (!((HttpResponse *) s)->hasResponded() && !httpResponseData->onAborted) { - log("Error: Returning from a request handler without responding or attaching an abort handler is forbidden!", 0); + UWS_LOG_REQUEST("Error: Returning from a request handler without responding or attaching an abort handler is forbidden!", 0); std::terminate(); } diff --git a/src/Log.h b/src/Log.h index 8e91980e8..9c540ada9 100644 --- a/src/Log.h +++ b/src/Log.h @@ -24,6 +24,12 @@ inline LogFunction log = [](const std::string& message, int logLevel) -> void { } }; +#define UWS_LOG_REQUEST(msg, loglevel) { \ + if constexpr(loglevel <= UWS_LOG_LEVEL) { \ + log(msg, loglevel); \ + } \ +} + } // namespace uWS #endif // UWS_LOG_H From 1af11d36241b81dcd68da2f7a292490324956455 Mon Sep 17 00:00:00 2001 From: jf99 Date: Mon, 11 Jan 2021 15:47:03 +0100 Subject: [PATCH 4/7] make logging more efficient --- src/HttpContext.h | 6 +++--- src/Log.h | 43 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/HttpContext.h b/src/HttpContext.h index 6a27d97f5..5e62321d3 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -155,12 +155,12 @@ struct HttpContext { httpContextData->router.getUserData() = {(HttpResponse *) s, httpRequest}; if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl())) { /* We have to force close this socket as we have no handler for it */ - UWS_LOG_REQUEST("No handler for route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 1); + UWS_LOG_REQUEST(1, "No handler for route ", httpRequest->getMethod(), " ", httpRequest->getUrl()); us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); return nullptr; } else { - UWS_LOG_REQUEST("Successfully handled route " + std::string(httpRequest->getMethod()) + " " + std::string(httpRequest->getUrl()), 3); + UWS_LOG_REQUEST(3, "Successfully handled route ", httpRequest->getMethod(), " ", httpRequest->getUrl()); } /* First of all we need to check if this socket was deleted due to upgrade */ @@ -181,7 +181,7 @@ struct HttpContext { /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */ if (!((HttpResponse *) s)->hasResponded() && !httpResponseData->onAborted) { - UWS_LOG_REQUEST("Error: Returning from a request handler without responding or attaching an abort handler is forbidden!", 0); + UWS_LOG_REQUEST(0, "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!"); std::terminate(); } diff --git a/src/Log.h b/src/Log.h index 9c540ada9..f24e35fbf 100644 --- a/src/Log.h +++ b/src/Log.h @@ -13,9 +13,9 @@ namespace uWS { * \param [in] message The message to be logged. * \param [in] logLevel The severity of the message. 0 is error, 1 is warning, 2 is info. With each increment the severity decrements. */ -typedef std::function LogFunction; +typedef std::function LogFunction; -inline LogFunction log = [](const std::string& message, int logLevel) -> void { +inline LogFunction log = [](std::string_view message, int logLevel) -> void { if(logLevel <= 1) { std::cerr << message << std::endl; } @@ -24,9 +24,44 @@ inline LogFunction log = [](const std::string& message, int logLevel) -> void { } }; -#define UWS_LOG_REQUEST(msg, loglevel) { \ +class LogBuffer +{ + private: + std::array buf{0}; + size_t cursor = 0; + + LogBuffer& operator<< (std::string_view sv) { + const size_t bytesFree = buf.size() - cursor; + if(sv.size() > bytesFree) + throw std::length_error("log message too long"); + memcpy(&buf[cursor], sv.data(), sv.size()); + cursor += sv.size(); + return *this; + } + + public: + template + void put(T msg) { + *this << msg; + } + template + void put(T t, Ts... ts) { + put(t); + put(ts...); + } + std::string_view get() { + std::string_view ret(buf.data(), cursor); + cursor = 0; + return ret; + } +}; + +thread_local LogBuffer logBuffer; + +#define UWS_LOG_REQUEST(loglevel, ...) { \ if constexpr(loglevel <= UWS_LOG_LEVEL) { \ - log(msg, loglevel); \ + ::uWS::logBuffer.put(__VA_ARGS__); \ + ::uWS::log(::uWS::logBuffer.get(), loglevel); \ } \ } From cba6025809e1ac9432fb89aaed3125c0ddec19a0 Mon Sep 17 00:00:00 2001 From: jf99 Date: Mon, 11 Jan 2021 16:10:45 +0100 Subject: [PATCH 5/7] adapt includes --- src/Log.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Log.h b/src/Log.h index f24e35fbf..e74bd8bf0 100644 --- a/src/Log.h +++ b/src/Log.h @@ -1,8 +1,9 @@ #ifndef UWS_LOG_H #define UWS_LOG_H +#include #include #include -#include +#include #define UWS_LOG_LEVEL 0 // override this to get more verbose logging From d4ba584f7f733f36ebf33c8451a286180fcf8aa2 Mon Sep 17 00:00:00 2001 From: jf99 Date: Tue, 12 Jan 2021 08:59:24 +0100 Subject: [PATCH 6/7] replace exception throwing by return --- src/Log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Log.h b/src/Log.h index e74bd8bf0..160724884 100644 --- a/src/Log.h +++ b/src/Log.h @@ -34,7 +34,7 @@ class LogBuffer LogBuffer& operator<< (std::string_view sv) { const size_t bytesFree = buf.size() - cursor; if(sv.size() > bytesFree) - throw std::length_error("log message too long"); + return *this; memcpy(&buf[cursor], sv.data(), sv.size()); cursor += sv.size(); return *this; From c15309261d4960743fce440955cba5b5a1a2e50f Mon Sep 17 00:00:00 2001 From: jf99 Date: Mon, 25 Jan 2021 14:51:51 +0100 Subject: [PATCH 7/7] even more logging --- src/HttpContext.h | 7 +++++++ src/Log.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/HttpContext.h b/src/HttpContext.h index 5e62321d3..2efdd6bf1 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -144,6 +144,7 @@ struct HttpContext { /* Are we not ready for another request yet? Terminate the connection. */ if (httpResponseData->state & HttpResponseData::HTTP_RESPONSE_PENDING) { + UWS_LOG_REQUEST(3, "terminating connection (HTTP_RESPONSE_PENDING)"); us_socket_close(SSL, (us_socket_t *) s, 0, nullptr); return nullptr; } @@ -166,16 +167,19 @@ struct HttpContext { /* First of all we need to check if this socket was deleted due to upgrade */ if (httpContextData->upgradedWebSocket) { /* We differ between closed and upgraded below */ + UWS_LOG_REQUEST(3, "socket was deleted due to upgrade"); return nullptr; } /* Was the socket closed? */ if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) { + UWS_LOG_REQUEST(3, "socket was closed"); return nullptr; } /* We absolutely have to terminate parsing if shutdown */ if (us_socket_is_shut_down(SSL, (us_socket_t *) s)) { + UWS_LOG_REQUEST(3, "socket was shutdown"); return nullptr; } @@ -211,11 +215,13 @@ struct HttpContext { /* Was the socket closed? */ if (us_socket_is_closed(SSL, (struct us_socket_t *) user)) { + UWS_LOG_REQUEST(3, "socket was closed"); return nullptr; } /* We absolutely have to terminate parsing if shutdown */ if (us_socket_is_shut_down(SSL, (us_socket_t *) user)) { + UWS_LOG_REQUEST(3, "socket was shutdown"); return nullptr; } @@ -343,6 +349,7 @@ struct HttpContext { httpContext = (HttpContext *) us_create_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData), options); if (!httpContext) { + UWS_LOG_REQUEST(0, "Error: Failed to create a httpContext"); return nullptr; } diff --git a/src/Log.h b/src/Log.h index 160724884..d3aa3903c 100644 --- a/src/Log.h +++ b/src/Log.h @@ -12,7 +12,7 @@ namespace uWS { /*! * \brief Log a message. The user of this lib is free to override this function object with a custom logger. * \param [in] message The message to be logged. - * \param [in] logLevel The severity of the message. 0 is error, 1 is warning, 2 is info. With each increment the severity decrements. + * \param [in] logLevel The severity of the message. 0 is error, 1 is warning, 2 is info, 3 is debug. With each increment the severity decrements. */ typedef std::function LogFunction;