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

gRPC Interceptors #39

Merged
merged 6 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ FetchContent_MakeAvailable(libpqxx)

# libviper
FetchContent_Declare(libviper
URL https://github.com/uditha-atukorala/libviper/archive/refs/tags/v0.3.1.tar.gz
URL_HASH SHA256=24a79fe54708a315394938f7946dab35aa69b884f0fab4ac0a9fa42b60c93313
URL https://github.com/uditha-atukorala/libviper/archive/refs/tags/v0.3.2.tar.gz
URL_HASH SHA256=6b4bc56a4015e5a3889bac66f868947781001c621a61db4383bb528e2239722f
)
FetchContent_MakeAvailable(libviper)

Expand Down
13 changes: 13 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_subdirectory(datastore)
add_subdirectory(err)
add_subdirectory(events)
add_subdirectory(logger)
add_subdirectory(service)

# datastore
Expand Down Expand Up @@ -39,6 +40,18 @@ target_include_directories(libevents

add_library(${PROJECT_NAME}::events ALIAS libevents)

# logger
add_library(liblogger INTERFACE)
target_link_libraries(liblogger
INTERFACE logger
)

target_include_directories(liblogger
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)

add_library(${PROJECT_NAME}::logger ALIAS liblogger)

# service
add_library(libservice INTERFACE)
target_link_libraries(libservice
Expand Down
8 changes: 8 additions & 0 deletions src/logger/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
add_library(logger
logger.cpp logger.h
)

target_link_libraries(logger
PRIVATE
glaze::glaze
)
27 changes: 27 additions & 0 deletions src/logger/logger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "logger.h"

#include <chrono>

namespace logger {
std::string timestamp() {
const auto now = std::chrono::system_clock::now();
auto days = std::chrono::floor<std::chrono::days>(now);
std::chrono::year_month_day ymd(days);
std::chrono::hh_mm_ss time(std::chrono::floor<std::chrono::nanoseconds>(now - days));

char buf[std::size("2006-01-02T15:04:05.999999999Z")];
std::snprintf(
std::data(buf),
std::size(buf),
"%d-%.2u-%.2uT%.2ld:%.2ld:%.2lld.%lldZ",
static_cast<int>(ymd.year()),
static_cast<unsigned>(ymd.month()),
static_cast<unsigned>(ymd.day()),
time.hours().count(),
time.minutes().count(),
time.seconds().count(),
time.subseconds().count());

return buf;
}
} // namespace logger
21 changes: 21 additions & 0 deletions src/logger/logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <string>

#include <glaze/glaze.hpp>

namespace logger {
std::string timestamp();

template <typename... Args> void info(std::string_view source, Args &&...args) {
glz::obj obj{
"@timestamp",
timestamp(),
"severity",
"info",
"source",
source,
args...,
};

std::cout << glz::write_json(obj) << std::endl;
}
} // namespace logger
16 changes: 16 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "datastore/datastore.h"
#include "service/gatekeeper.h"
#include "service/interceptors/logger.h"

int main() {
try {
Expand Down Expand Up @@ -37,6 +38,21 @@ int main() {
builder.AddListeningPort(std::string{conf["tcp.address"]}, grpc::InsecureServerCredentials());
builder.RegisterService(&service);

// Interceptors
{
using factory_t = std::unique_ptr<grpc::experimental::ServerInterceptorFactoryInterface>;
std::vector<factory_t> creators;

if (conf["app.debug"].get<bool>()) {
factory_t logger(new service::interceptors::LoggerFactory());
creators.push_back(std::move(logger));
}

if (creators.size() > 0) {
builder.experimental().SetInterceptorCreators(std::move(creators));
}
}

std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
server->Wait();

Expand Down
2 changes: 2 additions & 0 deletions src/service/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ add_library(service
gatekeeper.rbac-policies.cpp
gatekeeper.roles.cpp
mappers.cpp mappers.h
interceptors/logger.cpp interceptors/logger.h
)

target_link_libraries(service
PUBLIC
${PROJECT_NAME}::libproto
PRIVATE
${PROJECT_NAME}::datastore
${PROJECT_NAME}::logger
)

if (GATEKEEPER_ENABLE_COVERAGE)
Expand Down
21 changes: 21 additions & 0 deletions src/service/interceptors/logger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "logger.h"

#include "logger/logger.h"

namespace service {
namespace interceptors {
Logger::Logger(grpc::experimental::ServerRpcInfo *rpc) :
_rpc(rpc), _start(std::chrono::high_resolution_clock::now()) {}

Logger::~Logger() {
std::chrono::duration<double, std::milli> diff =
std::chrono::high_resolution_clock::now() - _start;

logger::info("service", "latency_ms", diff.count(), "method", _rpc->method());
}

void Logger::Intercept(grpc::experimental::InterceptorBatchMethods *methods) {
methods->Proceed();
}
} // namespace interceptors
} // namespace service
28 changes: 28 additions & 0 deletions src/service/interceptors/logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <chrono>

#include <grpcpp/support/server_interceptor.h>

namespace service {
namespace interceptors {
class Logger final : public grpc::experimental::Interceptor {
public:
Logger(grpc::experimental::ServerRpcInfo *rpc);
~Logger();

void Intercept(grpc::experimental::InterceptorBatchMethods *methods) override;

private:
grpc::experimental::ServerRpcInfo *_rpc;

std::chrono::high_resolution_clock::time_point _start;
};

class LoggerFactory final : public grpc::experimental::ServerInterceptorFactoryInterface {
public:
grpc::experimental::Interceptor *CreateServerInterceptor(
grpc::experimental::ServerRpcInfo *info) override {
return new Logger(info);
}
};
} // namespace interceptors
} // namespace service