Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add logging interface #1163

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/HttpContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
#include "HttpResponseData.h"
#include "AsyncSocket.h"
#include "WebSocketData.h"
#include "Log.h"

#include <string_view>
#include <iostream>
#include "f2/function2.hpp"

namespace uWS {
Expand Down Expand Up @@ -144,6 +144,7 @@ struct HttpContext {

/* Are we not ready for another request yet? Terminate the connection. */
if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
UWS_LOG_REQUEST(3, "terminating connection (HTTP_RESPONSE_PENDING)");
us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
return nullptr;
}
Expand All @@ -155,30 +156,36 @@ struct HttpContext {
httpContextData->router.getUserData() = {(HttpResponse<SSL> *) 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(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(3, "Successfully handled route ", httpRequest->getMethod(), " ", httpRequest->getUrl());
}

/* 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;
}

/* Returning from a request handler without responding or attaching an onAborted handler is ill-use */
if (!((HttpResponse<SSL> *) 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;
UWS_LOG_REQUEST(0, "Error: Returning from a request handler without responding or attaching an abort handler is forbidden!");
std::terminate();
}

Expand Down Expand Up @@ -208,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;
}

Expand Down Expand Up @@ -340,6 +349,7 @@ struct HttpContext {
httpContext = (HttpContext *) us_create_socket_context(SSL, (us_loop_t *) loop, sizeof(HttpContextData<SSL>), options);

if (!httpContext) {
UWS_LOG_REQUEST(0, "Error: Failed to create a httpContext");
return nullptr;
}

Expand Down
72 changes: 72 additions & 0 deletions src/Log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef UWS_LOG_H
#define UWS_LOG_H
#include <array>
#include <functional>
#include <iostream>
#include <string_view>

#define UWS_LOG_LEVEL 0 // override this to get more verbose logging

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, 3 is debug. With each increment the severity decrements.
*/
typedef std::function<void(std::string_view message, int logLevel)> LogFunction;

inline LogFunction log = [](std::string_view message, int logLevel) -> void {
if(logLevel <= 1) {
std::cerr << message << std::endl;
}
else {
std::cout << message << std::endl;
}
};

class LogBuffer
{
private:
std::array<char,1024> buf{0};
size_t cursor = 0;

LogBuffer& operator<< (std::string_view sv) {
const size_t bytesFree = buf.size() - cursor;
if(sv.size() > bytesFree)
return *this;
memcpy(&buf[cursor], sv.data(), sv.size());
cursor += sv.size();
return *this;
}

public:
template <typename T>
void put(T msg) {
*this << msg;
}
template <typename T, typename... Ts>
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) { \
::uWS::logBuffer.put(__VA_ARGS__); \
::uWS::log(::uWS::logBuffer.get(), loglevel); \
} \
}

} // namespace uWS

#endif // UWS_LOG_H